编译原理实验四——实现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:
错误句子,出错提示: