一、题目
对下列文法,用SLR(1)分析法对任意输入的符号串进行分析:
(1)S->E
(2)E->E+T
(3)E->T
(4)T->T*F
(5)T->F
(6)F->(E)
(7)F->i
二、设计思路
(1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
分析器的动作就是由栈顶状态和当前输入符号所决定。
LR分析器由三个部分组成:
其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。
ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。动作有四种可能:
(1)移进:
action[i,a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。
(2)归约:
action[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A- B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。
(3)接受acc:
当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。
(4)报错:
当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。
三、源代码
#include<bits/stdc++.h>
using namespace std;
char vt[6] = { 'i', '+', '*', '(', ')', '#' }; //终结符
char vn[3] = { 'E', 'T', 'F' }; //非终结符
//文法
string wf[7] =
{
"S->E",
"E->E+T",
"E->T",
"T->T*F",
"T->F",
"F->(E)",
"F->i"
};
//action表
string action[12][6] =
{
"s5", "^", "^", "s4", "^", "^",
"^", "s6", "^", "^", "^", "acc",
"^", "r2", "s7", "^", "r2", "r2",
"^", "r4", "r4", "^", "r4", "r4",
"s5", "^", "^", "s4", "^", "^",
"^", "r6", "r6", "^", "r6", "r6",
"s5", "^", "^", "s4", "^", "^",
"s5", "^", "^", "s4", "^", "^",
"^", "s6", "^", "^", "s11", "^",
"^", "r1", "s7", "^", "r1", "r1",
"^", "r3", "r3", "^", "r3", "r3",
"^", "r5", "r5", "^", "r5", "r5"
};
//goto表
int goto_[12][3] =
{
1, 2, 3,
0, 0, 0,
0, 0, 0,
0, 0, 0,
8, 2, 3,
0, 0, 0,
0, 9, 3,
0, 0, 10,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0
};
//当前状态
string nowcout="0";
//输入串的游标
int com = 0;
int num = 1;
int t=0;
//输入串
string input = "";
stack <char> symbols;//创建一个符号栈
stack <int> status;//创建一个状态栈
void show(string statuA,int statuG);
void init()
{
cout<<"输入的文法"<<endl;
for (int j = 0; j < 6; j++)
{
cout << wf[j] << endl;
}
cout << "VT:";
for (int i = 0; i < 6; i++)
{
cout << vt[i] << "\t";
}
cout << endl<< "VN:";
for (int i = 0; i <3; i++)
{
cout << vn[i] << "\t";
}
cout << endl;
symbols.push('#');
status.push(0);
}
//获取非终结符所在下标
int getVtNowIndex(char now)
{
for(int i=0;i<6;i++)
{
if(now==vt[i])
{
return i;
}
}
return -1;
}
//获取终结符所在下标
int getVnNowIndex(char now)
{
for(int i=0;i<3;i++)
{
if(now==vn[i])
{
return i;
}
}
return -1;
}
//输出栈中元素但是不破坏栈的结构
int showStack(stack<int >&s){
stack <int> temp;
int num=s.size();
for(int i=0;i<num;i++)
{
temp.push(s.top());
s.pop();
}
for(int i=0;i<num;i++)
{
cout<<temp.top();
s.push(temp.top());
temp.pop();
}
}
//输出栈中元素但是不破坏栈的结构
char showStack(stack<char >&s){
stack <char> temp;
int num=s.size();
for(int i=0;i<num;i++)
{
temp.push(s.top());
s.pop();
}
for(int i=0;i<num;i++)
{
cout<<temp.top();
s.push(temp.top());
temp.pop();
}
}
//格式化输出
void show(string statuA,int statuG)
{
showStack(status);
cout<<"\t";
showStack(symbols);
cout<<"\t";
cout<<input.substr(com);
cout<<"\t\t"<<nowcout<<"\t"<<statuG<<endl;
}
//移进
void yj(int statu,char symbol)
{
symbols.push(symbol);
status.push(statu);
string statuA = "s"+statu;
show(statuA,0);
com++;
}
//规约
void gy(int index)
{
int n = wf[index].length()-3;
for(int i=0;i<n;i++)
{
symbols.pop();
status.pop();
}
symbols.push(wf[index][0]);
int indexj = getVnNowIndex(wf[index][0]);
int indexi = status.top();
status.push(goto_[indexi][indexj]);
string statuA = "r"+index;
show(statuA,goto_[indexi][indexj]);
}
//分析
void analysis(string s)
{
while(com<input.size())
{
int i = status.top();
char ch = s[com];
t=getVtNowIndex(ch);
nowcout=action[i][t];
if (action[i][t][0] == 's')
{
int t1 = action[i][t][1]-'0';
yj(t1, ch);
}
else if (action[i][t][0] == 'r')
{
gy(action[i][t][1]-'0');
}
else if (action[i][t] == "^")
{
cout << "\tError" << endl;
break;
}
else if (action[i][t] == "acc")
{
show("",0);
//cout << "acc" << "\t 分析成功" << endl;
break;
}
}
}
int main()
{
init();
cout<<"输入的文法:"<<endl;
cin>>input;
cout<<"状态栈\t符号栈\t输入串\t\tACTION\tGOTO\n";
show("0",0);
analysis(input);
return 0;
}
View Code
四、运行结果