LR(1)分析法

SLR(1)方法的出现,解决了大部分的移进和规约冲突、规约和规约的冲突。并且SLR(1)其优点是状态数目少,造表算法简单,大多数程序设计语言基本上都可用SLR(1)文法来描述。

但是仍然有一些文法,不能用SLR(1)解决。

例如:

S->BB;

B->aB;

B->b;

该文法我们可以看到,在S->BB中,第一个B和第二个B的follow集是不同的。为了解决这个问题,于是诞生了LR(1)分析方法。

解决办法是在每个项目集的产生式后加上follow集。比如:

S-> ·BB, #

B-> · aB, a/b

B-> · b ,a/b

这样就是是同一个非终结符,但是仍旧可以根据不同状态集内的产生式的follow集进行不冲突的规约和移进。

目前LR(1)分析法仍旧是应用非常广泛,是当前最一般的分析方法,几乎所有的上下文无关文法描述的程序设计语言都可以通过LR(1)分析法分析。

为了解决LR(1)分析法状态过多的问题,于是提出了LALR(1)分析法,将“心”相同的状态合并,从而减少状态数。

具体例子如下:

文法G[E]

(0)S’->S

(1)S->BB

(2)B->Ab

(3)B->b

1、构造项目集

 2、构造LR(分析表)

状态

a

b

#

S

B

0

S3

S4

 

1

2

1

 

 

Acc

 

 

2

S6

S7

 

 

5

3

S3

S4

 

 

8

4

R3

R3

 

 

 

5

 

 

R1

 

 

6

S6

S7

 

 

9

7

 

 

R3

 

 

8

R2

R2

 

 

 

9

 

 

R2

 

 

 

3、编程

  1 #include<bits/stdc++.h>
  2 #define ROW 11
  3 #define COLUMN 6
  4 using namespace std;
  5 //产生式
  6 string products[4][2]={
  7 {"S'","S"},
  8 {"S","BB"},
  9 {"B","aB"},
 10 {"B","b"}
 11 };
 12 //分析表
 13 string actiontable[ROW][COLUMN]={
 14 {"","a","b","#","S","B"},
 15 {"0","s3","s4","","1","2"},
 16 {"1","","","acc","",""},
 17 {"2","s6","s7","","","5"},
 18 {"3","s3","s4","","","8"},
 19 {"4","r3","r3","","",""},
 20 {"5","","","r1","",""},
 21 {"6","s6","s7","","","9"},
 22 {"7","","","r3","",""},
 23 {"8","r2","r2","","",""},
 24 {"9","","","r2","",""}
 25 };
 26 stack<int> sstatus; //状态栈
 27 stack<char> schar; //符号栈
 28 struct Node{
 29     char type;
 30     int num;
 31 };
 32 //打印步骤
 33 void print_step(int times){
 34     stack<char> tmp2;
 35     cout<<times<<setw(4);
 36     while(!schar.empty()){
 37         char t=schar.top();
 38         schar.pop();
 39         tmp2.push(t);
 40         cout<<t;
 41     }
 42     while(!tmp2.empty()){
 43         int t=tmp2.top();
 44         tmp2.pop();
 45         schar.push(t);
 46     }
 47 }
 48 //查表
 49 Node Action_Goto_Table(int status,char a){
 50     int row=status+1;
 51     string tmp;
 52     for(int j=1;j<COLUMN;j++){
 53         if(a==actiontable[0][j][0]){
 54             tmp=actiontable[row][j];
 55         }
 56     }
 57     Node ans;
 58     if(tmp[0]>='0'&&tmp[0]<='9'){
 59         int val=0;
 60         for(int i=0;i<tmp.length();i++){
 61             val=val*10+(tmp[i]-'0');
 62         }
 63         ans.num=val;
 64         ans.type=' ';
 65     }else if(tmp[0]=='s'){
 66         int val=0;
 67         for(int i=1;i<tmp.length();i++){
 68             val=val*10+(tmp[i]-'0');
 69         }
 70         ans.type='s';
 71         ans.num=val;
 72     }else if(tmp[0]=='r'){
 73         int val=0;
 74         for(int i=1;i<tmp.length();i++){
 75             val=val*10+(tmp[i]-'0');
 76         }
 77         ans.type='r';
 78         ans.num=val;
 79     }else if(tmp[0]=='a'){
 80         ans.type='a';
 81     }else{
 82         ans.type=' ';
 83     }
 84     return ans;
 85 }
 86 //LR(1)分析法
 87 bool LR1(string input){
 88     while(!sstatus.empty()){
 89         sstatus.pop();
 90     }
 91     while(!schar.empty()){
 92         schar.pop();
 93     }
 94     int times=0;
 95     bool flag=true;
 96     int st=0;
 97     sstatus.push(st);
 98     schar.push('#');
 99     int i=0;
100     char a=input[i];
101     while(true){
102         Node action=Action_Goto_Table(st,a);
103         if(action.type=='s'){
104             st=action.num;
105             sstatus.push(st);
106             schar.push(a);
107             a=input[++i];
108             print_step(++times);
109             cout<<setw(10)<<'s'<<st<<endl;
110 
111         }else if(action.type=='r'){
112             int n=action.num;
113             string ls=products[n][0];
114             string rs=products[n][1];
115             for(int j=0;j<rs.length();j++){
116                 sstatus.pop();
117                 schar.pop();
118             }
119             schar.push(ls[0]); 
120             st=sstatus.top();
121             action =Action_Goto_Table(st,ls[0]);
122             st=action.num;
123             sstatus.push(st);
124             print_step(++times);
125             cout<<setw(10)<<'r'<<" "<<ls<<"->"<<rs<<endl;
126 
127         }else if(action.type=='a'){
128             flag=true;
129             break;
130         }else{
131             flag=false;
132             break;
133         }
134     }
135     return flag;
136 }
137 int main(){
138     string input;
139     while(cin>>input){
140         if(LR1(input)){
141             cout<<"syntax correct"<<endl;
142         }else{
143             cout<<"syntax error"<<endl;
144         }
145     }
146     return 0;
147 }

 

posted @ 2019-07-02 12:11  ISGuXing  阅读(9919)  评论(0编辑  收藏  举报