编译原理实验——LR分析

编译原理实验四——实现LR分析器模型的总控程序
一 LR分析器模型
在这里插入图片描述
二.具体动作
(1)移进【shift】
若ACTION[Si,a]=Sj,a为终结符,则把a移入文法符号栈,Sj移入状态栈;
(2)归约【reduce】
若ACTION[Si,a]=rj,a为终结符或#,则用第j个产生式(A->β)归约,将两个栈弹出∣β∣个元素,这时当前面临符号为第j个产生式左部的非终结符(A);若状态栈当前的栈顶状态为Sk,且GOTO[Sk,A]=j,则非终结符A移入符号栈,j移入状态栈;
(3)接受【accept】
若ACTION[Si,a]=acc,a为#,则为接受,表明分析成功;
(4)报错【error】
若ACTION[Si,a]=空白,则转向出错处理。
三.总控程序算法逻辑
在这里插入图片描述
四 总控程序代码

#include <iostream>
#include <stack>
#include <string>
#include <map>
#include <typeinfo>
#include <vector>
using namespace std;
/*
(0)E -> S
(1)S -> BB
(2)B -> aB
(3)B -> b
*/
stack<int> stateStack;//状态栈
stack<char> signStack;//符号栈
string inputS; //输入串
map<int, map<char, string> > ACTION = {
	{0,{{'a',"s3"},{'b',"s4"},{'#'," "  }}},
	{1,{{'a'," " },{'b'," " },{'#',"acc"}}},
	{2,{{'a',"s3"},{'b',"s4"},{'#'," "  }}},
	{3,{{'a',"s3"},{'b',"s4"},{'#'," "  }}},
	{4,{{'a',"r3"},{'b',"r3"},{'#',"r3"  }}},
	{5,{{'a'," " },{'b'," " },{'#',"r1" }}},
	{6,{{'a',"r2"},{'b',"r2" },{'#',"r2" }}},
};//ACTION表
map<int, map<char, string> > GOTO = {
	{0,{{'S',"1"},{'B',"2"}}},
	{1,{{'S'," "},{'B'," "}}},
	{2,{{'S'," "},{'B',"5"}}},
	{3,{{'S'," "},{'B',"6"}}},
	{4,{{'S'," "},{'B'," "}}},
	{5,{{'S'," "},{'B'," "}}},
	{6,{{'S'," "},{'B'," "}}}
};//GOTO表
struct rule {
	char left;
	string right;//产生式左部和右部
};//产生式
rule rules[4] = {
	{'E',"S"},
	{'S',"BB"},
	{'B',"aB"},
	{'B',"b" }
};//带编号的产生式

void analyse_LR() {
	string s = inputS + "#"; //让串以“#”结尾
	//初始化符号栈,状态栈,并取出状态栈和符号栈栈顶元素
	stateStack.push(0);
	signStack.push('#');
	int S = stateStack.top();
	char a = s[0];
	//定义字符串保存各个栈的情况,用于打印各个栈的情况
	string state="0";
	string sign = "#";
	string ss = s;
	int step = 1;
	//开始进行分析
	cout << " " << "步骤" << "\t" << "符号栈" << "\t\t" << "状态栈" << "\t\t" << "输入串" << "\t\t"
		<< "Action" << "\t\t" << "GOTO" << endl;;
	while (ACTION[S][a] != "acc") { //如果
		cout << " " << step << "\t" << state << "\t\t" << sign<< "\t\t"<<ss<< "\t\t";
		string tmps = ACTION[S][a];
		if (tmps[0] == 's') { //ACTION表中对应Si,处理移进状态
			int num = tmps[1] - '0';
			stateStack.push(num);
			signStack.push(a);
			s = s.substr(1, s.size());
			ss = s; 
			//维护输出的内容
			cout << tmps << endl;
			state += tmps.substr(1,1);
			sign += a;
		}
		else if (tmps[0] == 'r') { //ACTION表中对应ri,处理规约状态
			int num = tmps[1] - '0';
			char left = rules[num].left;
			string right = rules[num].right;
			int len = right.size();
			//将当前状态栈和符号栈退栈len个符号
			int len2 = len;
			while (len2--) {
				stateStack.pop();
				signStack.pop();
			}
			//同时维护用于输出的串
			state = state.substr(0,state.size()-len);
			sign = sign.substr(0,sign.size() - len);
			//将产生式左部入符号栈,GTTO[S][a]如状态栈
			signStack.push(left);
			int S2 = stateStack.top();
			string tmps2 = GOTO[S2][left];
			int num2 = tmps2[0] - '0';
			stateStack.push(num2);
			cout << tmps << "\t\t"<<tmps2<<endl;
			//维护输出的串
			state = state.append(tmps2);
			sign = sign + left;
		}
		else { //如果ACTION表中对应的既不是Si,也不是ri,则出错,进行出错处理
			cout << "syntax error!" << endl;
			exit(0);
		}
		step++;
		S = stateStack.top();
		a = s[0];
	}
	if (ACTION[S][a] == "acc") {
		cout << " " << step << "\t" << state << "\t\t" << sign << "\t\t" << ss << "\t\t";
		cout << "acc" << endl;
	}
	return;
}

int main() {
	cout << "请输入要分析的句子:(不用#结尾)";
	cin >> inputS;
	cout << endl;
	analyse_LR();
	return 0;
}

五.实验结果
正确句子,出现acc:
在这里插入图片描述
错误句子,出错提示:
在这里插入图片描述

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值