LR(0)分析法


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 }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM