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 }