• 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 }
  • 相关阅读:
    Linux xargs 命令
    Shell 流程控制
    springSecurity---AuthenticationProvider解析
    nginx unknown directive "stream"
    Linux清空文件内容
    解决RabbitMQ报错 Error: unable to connect to node rabbit@localhost:
    mysql bit类型 使用Mysql命令行查询的时候无法看到其值
    今日进度
    每周总结
    今日进度
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/11119803.html
Copyright © 2020-2023  润新知