LR(0)是一种自底向上的语法分析方法。两个基本动作是移进和规约。
具体例子如下
已知文法G[E]
(1) E→aА
(2) E→bB
(3) A→cА
(4) A→d
(5) B→cB
(6) B→d
编写LR(0)分析算法,用于识别符号串是否为合法的句子。
设计方法
a.将文法 G[E]拓广为文法 G[E']
(0) S'→E
(1) E→aA
(2) E→bB
(3) A→cA
(4) A→d
(5) B→cB
(6) B→d
b.构造识别可归约前缀的 NFA
c. 将识别可归约前缀的 NFA 确定化成DFA
d. 根据识别可归约前缀的 DFA 构造文法的 LR(0)分析表
表2-1 LR(0)分析表
状态 |
a |
b |
c |
d |
# |
E |
A |
B |
0 |
S1 |
S2 |
|
|
|
3 |
|
|
1 |
|
|
S4 |
S5 |
|
|
6 |
|
2 |
|
|
S7 |
S8 |
|
|
|
9 |
3 |
|
|
|
|
acc |
|
|
|
4 |
|
|
S4 |
S5 |
|
|
10 |
|
5 |
r4 |
r4 |
r4 |
r4 |
r4 |
|
|
|
6 |
r1 |
r1 |
r1 |
r1 |
r1 |
|
|
|
7 |
|
|
S7 |
S8 |
|
|
|
11 |
8 |
r6 |
r6 |
r6 |
r6 |
r6 |
|
|
|
9 |
r2 |
r2 |
r2 |
r2 |
r2 |
|
|
|
10 |
r3 |
r3 |
r3 |
r3 |
r3 |
|
|
|
11 |
r5 |
r5 |
r5 |
r5 |
r5 |
|
|
|
e. 设计 LR(0)分析程序
自底向上的语法分析的两个基本动作就是,移进与规约。分析一下表 2-1 中 文法的 LR(0)分析表,可以发现这两个动作在表中都有。进一步分析可知,这些 移进与规约动作在表的前面终结符列中,因此,这部分称之为 ACTION 表。
表中不但给出了两个基本动作,还给出了规约时,弹出产生式右部,压入左 部之后,应该转换到的状态。例如,当前状态为 9,状态 9 为句柄识别态,查表 得:r2,表示使用第二个产生式E→bB 进行规约。规约动作分为两步:第一步弹 出句柄 bB,从识别文法可归约前缀的 DFA 中可知,弹出句柄 bB后,从当前状态为 9 回到状态 0;第二步就是压入左部 E, 从当前状态 0,转换到状态 3。在表中 的第 0 行第 E 列中就给出状态 3。
分析表 可知,表中的非终结符列填入的是某一规约动作,压入产生式左 部(非终结符)之后,转换到的状态。因此,这部分称之为 GOTO 表。
实验代码:
1 #include<bits/stdc++.h> 2 #define ROW 13 3 #define COLUMN 9 4 using namespace std; 5 //产生式 6 string products[7][2]={ 7 "","", 8 "E","aA", 9 "E","bB", 10 "A","cA", 11 "A","d", 12 "B","cB", 13 "B","d" 14 }; 15 //LR(0)分析表 16 string actiontable[ROW][COLUMN]={ 17 {" " ,"a" ,"b" ,"c" ,"d" ,"#" ,"E" ,"A" ,"B"}, 18 {"0" ,"s1" ,"s2" ," " ," " ," " ,"3" ," " ," "}, 19 {"1" ," " ," " ,"s4" ,"s5" ," " ," " ,"6" ," "}, 20 {"2" ," " ," " ,"s7" ,"s8" ," " ," " ," " ,"9"}, 21 {"3" ," " ," " ," " ," " ,"acc"," " ," " ," "}, 22 {"4" ," " ," " ,"s4" ,"s5" ," " ," " ,"10" ," "}, 23 {"5" ,"r4" ,"r4" ,"r4" ,"r4" ,"r4" ," " ," " ," "}, 24 {"6" ,"r1" ,"r1" ,"r1" ,"r1" ,"r1" ," " ," " ," "}, 25 {"7" ," " ," " ,"s7" ,"s8" ," " ," " ," " ,"11"}, 26 {"8" ,"r6" ,"r6" ,"r6" ,"r6" ,"r6" ," " ," " ," "}, 27 {"9" ,"r2" ,"r2" ,"r2" ,"r2" ,"r2" ," " ," " ," "}, 28 {"10","r3" ,"r3" ,"r3" ,"r3" ,"r3" ," " ," " ," "}, 29 {"11","r5" ,"r5" ,"r5" ,"r5" ,"r5" ," " ," " ," "}}; 30 stack<int> sstatus; //状态栈 31 stack<char> schar; //符号栈 32 struct Node{ 33 char type; 34 int num; 35 }; 36 //打印步骤 37 void print_step(int times){ 38 stack<char> tmp2; 39 cout<<times<<setw(4); 40 while(!schar.empty()){ 41 char t=schar.top(); 42 schar.pop(); 43 tmp2.push(t); 44 cout<<t; 45 } 46 while(!tmp2.empty()){ 47 int t=tmp2.top(); 48 tmp2.pop(); 49 schar.push(t); 50 } 51 } 52 //查表 53 Node Action_Goto_Table(int status,char a){ 54 int row=status+1; 55 string tmp; 56 for(int j=1;j<COLUMN;j++){ 57 if(a==actiontable[0][j][0]){ 58 tmp=actiontable[row][j]; 59 } 60 } 61 Node ans; 62 if(tmp[0]>='0'&&tmp[0]<='9'){ 63 int val=0; 64 for(int i=0;i<tmp.length();i++){ 65 val=val*10+(tmp[i]-'0'); 66 } 67 ans.num=val; 68 ans.type=' '; 69 }else if(tmp[0]=='s'){ 70 int val=0; 71 for(int i=1;i<tmp.length();i++){ 72 val=val*10+(tmp[i]-'0'); 73 } 74 ans.type='s'; 75 ans.num=val; 76 }else if(tmp[0]=='r'){ 77 int val=0; 78 for(int i=1;i<tmp.length();i++){ 79 val=val*10+(tmp[i]-'0'); 80 } 81 ans.type='r'; 82 ans.num=val; 83 }else if(tmp[0]=='a'){ 84 ans.type='a'; 85 }else{ 86 ans.type=' '; 87 } 88 return ans; 89 } 90 //LR(0)分析算法 91 bool LR0(string input){ 92 while(!sstatus.empty()){ 93 sstatus.pop(); 94 } 95 while(!schar.empty()){ 96 schar.pop(); 97 } 98 int times=0; 99 bool flag=true; 100 int st=0; 101 sstatus.push(st); 102 schar.push('#'); 103 int i=0; 104 char a=input[i]; 105 while(true){ 106 Node action=Action_Goto_Table(st,a); 107 if(action.type=='s'){ 108 st=action.num; 109 sstatus.push(st); 110 schar.push(a); 111 a=input[++i]; 112 print_step(++times); 113 cout<<setw(10)<<'s'<<st<<endl; 114 115 }else if(action.type=='r'){ 116 int n=action.num; 117 string ls=products[n][0]; 118 string rs=products[n][1]; 119 for(int j=0;j<rs.length();j++){ 120 sstatus.pop(); 121 schar.pop(); 122 } 123 schar.push(ls[0]); //only one char 124 st=sstatus.top(); 125 action =Action_Goto_Table(st,ls[0]); 126 st=action.num; 127 sstatus.push(st); 128 print_step(++times); 129 cout<<setw(10)<<'r'<<" "<<ls<<"->"<<rs<<endl; 130 131 }else if(action.type=='a'){ 132 flag=true; 133 break; 134 }else{ 135 flag=false; 136 break; 137 } 138 } 139 return flag; 140 } 141 int main(){ 142 string input; 143 while(cin>>input){ 144 if(LR0(input)){ 145 cout<<"syntax correct"<<endl; 146 }else{ 147 cout<<"syntax error"<<endl; 148 } 149 } 150 return 0; 151 }