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 }

 

 

原文地址:https://www.cnblogs.com/ISGuXing/p/11119643.html