一、题目
对下列文法,用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] << " "; } cout << endl<< "VN:"; for (int i = 0; i <3; i++) { cout << vn[i] << " "; } 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<<" "; showStack(symbols); cout<<" "; cout<<input.substr(com); cout<<" "<<nowcout<<" "<<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 << " Error" << endl; break; } else if (action[i][t] == "acc") { show("",0); //cout << "acc" << " 分析成功" << endl; break; } } } int main() { init(); cout<<"输入的文法:"<<endl; cin>>input; cout<<"状态栈 符号栈 输入串 ACTION GOTO "; show("0",0); analysis(input); return 0; }