• 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 }

     

     

  • 相关阅读:
    PHP 构造方法 __construct()(转)
    PHP笔记
    php的print_r第二个参数是true有啥用啊
    如何给类或方法规范地注释
    详解spl_autoload_register()  函数(转)
    PHP中文网上的分页代码
    echo 0000
    [csu/coj 1619] 递归
    [csu/coj 1083]贪心
    [csu/coj 1078]多个序列的最长公共子序列
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/11119643.html
Copyright © 2020-2023  润新知