zoukankan      html  css  js  c++  java
  • LL(1)算法

    编译原理的语法分析中一个入门的算法就是LL(1)算法了,这里做一个总结。首先比较重要的是FIRST集和FOLLOW集合的生成。

    先上个例子吧:

        

      首先说一下FIRST集的生成,这个就要看产生式右部对应的首字母的“终结符”的个数的表现了,例如:A-> +TA|-TA|k   所以 A的FIRST集为+-k ;   同理B->*FB|/FB|k,所以B的FIRST集是*/k;  D的FIRST集是xyz;    接着我们再分析F,对F分析可以得FIRST集是  (  和  D的FIRST的并集,即(xyz,同理可以得到T和E的FIRST都是(xyz。

      我们接着分析FOLLOW集。首先要说一点,可以观察按照FOLLOW集按照“非终结符顺序”从上到下是递增的(这是什么规律,但是几乎所有的LL1(1)分析表都有这个现象),从上至下依次分析,对于E,观察所有的产生式的右部:有F-> (E)|D  这个式,则我们可以得知E的FOLLOW集为#).      接下来我们分析A的FOLLOW集,观察所有的产生式的右部,发现没有跟着A的终结符,哎,没办法,照抄上面的吧:即A得FOLLOW集和E的一样,都是#)。      然后我们分析T,发现T后面总是跟着A,则A的FIRST集应该包含于T的FOLLOW集中(当然,有空k的要去掉k),  再加上上面“遗传”下来的,所以T的FOLLOW集是+-#).  同理分析下去就会得到全部的非终结符的FOLLOW集。

      接着是如何运用FIRST和FOLLOW集生成LL(1)分析表。首先对所有的非终结符的FIRST进行填充,并留下这些FIRST的空k符号。这一遍刷完之后,再特别处理空k,对有空k的非终结符,将它的FOLLOW集中的所有的元素,都写成空k的式输入到LL(1)分析表中去。这样就大功告成了。  

    不妨再贴一个例子:

       

    题目1:

    题目描述

     输入开始符号,非终结符,终结符,产生式,LL(1)分析表
    输出LL(1)分析表

    G[E]:E →E+T | E-T | T

    T →T*F | T/F | F

    F →(E) | D

    D →x | y | z  

    消除左递归G1[E]: 

    E →TA 

    A →+TA | -TA | e 

    T →FB 

    B →*FB | /FB | e 

    F →(E) | D 

    D →x | y | z  

    输入格式

     输入开始符号;
    非终结符个数,非终结符,空格符分隔;
    终结符个数,终结符,空格符分隔;
    产生式的个数,各产生式的序号,产生式的左边和右边符号,空格符分隔;
    LL(1)分析表中的产生式个数,序号,行符号,列符号,产生式编号,空格符分隔;

    输出格式

     第一行:空,安终结符循序输出终结符,结束符‘#’,每个符号占5格;
    其余行:非终结符符号,各对应终结符的产生式的右边,每个符号占5格;

    样例输入
     将样例输入复制到剪贴板
    E
    6  E A T B F D
    9 + - * / ( ) x y z 
    13
    1  E TA
    2  A +TA
    3  A -TA
    4  A k
    5  T FB
    6  B *FB
    7  B /FB
    8  B k
    9  F (E)
    10 F D
    11 D x
    12 D y
    13 D z
    25
    1  E ( 1
    2  E x 1
    3  E y 1
    4  E z 1
    5  A + 2
    6  A - 3
    7  A ) 4
    8  A # 4
    9  T ( 5
    10 T x 5
    11 T y 5
    12 T z 5
    13 B + 8
    14 B - 8
    15 B * 6
    16 B / 7
    17 B ) 8
    18 B # 8
    19 F ( 9
    20 F x 10
    21 F y 10
    22 F z 10
    23 D x 11
    24 D y 12
    25 D z 13
    
    样例输出
             +    -    *    /    (    )    x    y    z    #
        E                       TA        TA   TA   TA     
        A  +TA  -TA                   k                   k
        T                       FB        FB   FB   FB     
        B    k    k  *FB  /FB         k                   k
        F                      (E)         D    D    D     
        D                                  x    y    z     

    AC代码:
     1 #include <iostream>
     2 using namespace std;
     3 
     4 string S="";                                                                                          //开始符号 
     5 struct { int number;string sign[20]; string res_LL[20][20]; } not_endsign={0};                       //非终结符
     6 struct { int number;string sign[20]; } end_sign={0};                                                  //终结符
     7 struct { int number;int order[100]; string left[100],right[100]; } production={0};                    //产生式 
     8 struct { int number;int order[100]; string rank[100],col[100];int production_num[100];  } LL={0};   //LL(1)分析表 
     9 
    10 void input();
    11 void print(string a);
    12 
    13 int main(){
    14     input();
    15     end_sign.sign[end_sign.number] = "#";
    16     end_sign.number++;
    17     
    18     //刷整个的分析表,将分析表中的数据填入到not_endsign中去 
    19     for(int i=0;i<LL.number;i++){
    20         //得到LL一条数据的“行”对应的“非终结符” 
    21         int j;
    22         for(j=0;j<not_endsign.number&& not_endsign.sign[j]!=LL.rank[i];j++ ); 
    23         
    24         //得到LL一条数据的“列”对应的“终结符” 
    25         int z;
    26         for(z=0;z<end_sign.number&&end_sign.sign[z]!=LL.col[i];z++ ); 
    27         
    28         //得到LL一条数据的要赋予的值   
    29         not_endsign.res_LL[j][z] = production.right[LL.production_num[i]-1 ];
    30     }
    31     
    32     //单独处理“#” 
    33     
    34     cout<<"     ";
    35     for(int i=0;i<end_sign.number;i++){
    36         cout<<"    "<<end_sign.sign[i];
    37     }
    38     cout<<endl;  
    39     
    40     for(int i=0;i<not_endsign.number;i++){
    41         print(not_endsign.sign[i]); 
    42         cout<<not_endsign.sign[i];
    43         for(int j=0;j<end_sign.number ;j++){
    44             print(not_endsign.res_LL[i][j] );
    45             cout<<not_endsign.res_LL[i][j];
    46         }
    47         cout<<endl;
    48     }
    49     
    50     return 0;
    51 } 
    52 
    53 void print(string a){
    54     for(int i=0;i<5-a.length();i++){
    55         cout<<" ";
    56     }
    57     return ;
    58 }
    59 void input(){
    60     cin>>S;
    61     cin>>not_endsign.number;
    62     for(int i=0;i<not_endsign.number;i++){
    63         cin>>not_endsign.sign[i];
    64     }
    65     
    66     cin>>end_sign.number;
    67     for(int i=0;i<end_sign.number;i++){
    68         cin>>end_sign.sign[i];
    69     }
    70     
    71     cin>>production.number;
    72     for(int i=0;i<production.number;i++){
    73         cin>>production.order[i]>>production.left[i]>>production.right[i];
    74     }
    75     
    76     cin>>LL.number;
    77     for(int i=0;i<LL.number;i++){
    78         cin>>LL.order[i]>>LL.rank[i]>>LL.col[i]>>LL.production_num[i];
    79     }
    80     return ;
    81 }
    View Code

    题目2:

    题目描述

     输入开始符号,非终结符,终结符,产生式,LL(1)分析表
    输出LL(1)分析表

    输入格式

     输入开始符号;
    非终结符个数,非终结符,空格符分隔;
    终结符个数,终结符,空格符分隔;
    产生式的个数,各产生式的序号,产生式的左边和右边符号,空格符分隔;
    LL(1)分析表中的产生式个数,序号,行符号,列符号,产生式编号,空格符分隔;
    输入一个算术式符号串,用#结束

    输出格式

     输出推导过程,每一步一行,中间“ & ”前是已经识别的子串,后是栈中信息。

    样例输入
     将样例输入复制到剪贴板
    E
    6  E A T B F D
    9  + - * / ( ) x y z 
    13
    1  E TA
    2  A +TA
    3  A -TA
    4  A k
    5  T FB
    6  B *FB
    7  B /FB
    8  B k
    9  F (E)
    10 F D
    11 D x
    12 D y
    13 D z
    25
    1  E ( 1
    2  E x 1
    3  E y 1
    4  E z 1
    5  A + 2
    6  A - 3
    7  A ) 4
    8  A # 4
    9  T ( 5
    10 T x 5
    11 T y 5
    12 T z 5
    13 B + 8
    14 B - 8
    15 B * 6
    16 B / 7
    17 B ) 8
    18 B # 8
    19 F ( 9
    20 F x 10
    21 F y 10
    22 F z 10
    23 D x 11
    24 D y 12
    25 D z 13
    (x+(y-x*z)*(y+x*z))+x/z#
    
    样例输出
    # & E#
    # & TA#
    # & FBA#
    # & (E)BA#
    #( & E)BA#
    #( & TA)BA#
    #( & FBA)BA#
    #( & DBA)BA#
    #( & xBA)BA#
    #(x & BA)BA#
    #(x & A)BA#
    #(x & +TA)BA#
    #(x+ & TA)BA#
    #(x+ & FBA)BA#
    #(x+ & (E)BA)BA#
    #(x+( & E)BA)BA#
    #(x+( & TA)BA)BA#
    #(x+( & FBA)BA)BA#
    #(x+( & DBA)BA)BA#
    #(x+( & yBA)BA)BA#
    #(x+(y & BA)BA)BA#
    #(x+(y & A)BA)BA#
    #(x+(y & -TA)BA)BA#
    #(x+(y- & TA)BA)BA#
    #(x+(y- & FBA)BA)BA#
    #(x+(y- & DBA)BA)BA#
    #(x+(y- & xBA)BA)BA#
    #(x+(y-x & BA)BA)BA#
    #(x+(y-x & *FBA)BA)BA#
    #(x+(y-x* & FBA)BA)BA#
    #(x+(y-x* & DBA)BA)BA#
    #(x+(y-x* & zBA)BA)BA#
    #(x+(y-x*z & BA)BA)BA#
    #(x+(y-x*z & A)BA)BA#
    #(x+(y-x*z & )BA)BA#
    #(x+(y-x*z) & BA)BA#
    #(x+(y-x*z) & *FBA)BA#
    #(x+(y-x*z)* & FBA)BA#
    #(x+(y-x*z)* & (E)BA)BA#
    #(x+(y-x*z)*( & E)BA)BA#
    #(x+(y-x*z)*( & TA)BA)BA#
    #(x+(y-x*z)*( & FBA)BA)BA#
    #(x+(y-x*z)*( & DBA)BA)BA#
    #(x+(y-x*z)*( & yBA)BA)BA#
    #(x+(y-x*z)*(y & BA)BA)BA#
    #(x+(y-x*z)*(y & A)BA)BA#
    #(x+(y-x*z)*(y & +TA)BA)BA#
    #(x+(y-x*z)*(y+ & TA)BA)BA#
    #(x+(y-x*z)*(y+ & FBA)BA)BA#
    #(x+(y-x*z)*(y+ & DBA)BA)BA#
    #(x+(y-x*z)*(y+ & xBA)BA)BA#
    #(x+(y-x*z)*(y+x & BA)BA)BA#
    #(x+(y-x*z)*(y+x & *FBA)BA)BA#
    #(x+(y-x*z)*(y+x* & FBA)BA)BA#
    #(x+(y-x*z)*(y+x* & DBA)BA)BA#
    #(x+(y-x*z)*(y+x* & zBA)BA)BA#
    #(x+(y-x*z)*(y+x*z & BA)BA)BA#
    #(x+(y-x*z)*(y+x*z & A)BA)BA#
    #(x+(y-x*z)*(y+x*z & )BA)BA#
    #(x+(y-x*z)*(y+x*z) & BA)BA#
    #(x+(y-x*z)*(y+x*z) & A)BA#
    #(x+(y-x*z)*(y+x*z) & )BA#
    #(x+(y-x*z)*(y+x*z)) & BA#
    #(x+(y-x*z)*(y+x*z)) & A#
    #(x+(y-x*z)*(y+x*z)) & +TA#
    #(x+(y-x*z)*(y+x*z))+ & TA#
    #(x+(y-x*z)*(y+x*z))+ & FBA#
    #(x+(y-x*z)*(y+x*z))+ & DBA#
    #(x+(y-x*z)*(y+x*z))+ & xBA#
    #(x+(y-x*z)*(y+x*z))+x & BA#
    #(x+(y-x*z)*(y+x*z))+x & /FBA#
    #(x+(y-x*z)*(y+x*z))+x/ & FBA#
    #(x+(y-x*z)*(y+x*z))+x/ & DBA#
    #(x+(y-x*z)*(y+x*z))+x/ & zBA#
    #(x+(y-x*z)*(y+x*z))+x/z & BA#
    #(x+(y-x*z)*(y+x*z))+x/z & A#
    #(x+(y-x*z)*(y+x*z))+x/z & #

    AC代码:
      1 #include <iostream>
      2 #include <stack>
      3 using namespace std;
      4 
      5 string S="";                                                                                          //开始符号 
      6 struct { int number;string sign[20]; string res_LL[20][20]; } not_endsign={0};                       //非终结符
      7 struct { int number;string sign[20]; } end_sign={0};                                                  //终结符
      8 struct { int number;int order[100]; string left[100],right[100]; } production={0};                    //产生式 
      9 struct { int number;int order[100]; string rank[100],col[100];int production_num[100];  } LL={0};   //LL(1)分析表 
     10 string test;
     11 
     12 void input();
     13 void print(string left,stack<string >  right);
     14 
     15 int main(){
     16     input();
     17     
     18     //定义输出结果 
     19     string left;
     20     stack<string >  right;
     21     
     22     right.push(S) ;    
     23     print(left,right);
     24 
     25     while(!right.empty()){ 
     26         string top = right.top();
     27         string firstletter = test.substr(0,1);
     28         if(top==firstletter){
     29             left += top;
     30             test = test.substr(1,test.length()-1 );
     31             right.pop();
     32             print(left,right);
     33             
     34             continue;  
     35         }
     36         else {
     37             //替换掉 top  
     38             for(int i=0;i<LL.number;i++){
     39                  if(LL.rank[i]==top &&LL.col[i]==firstletter ){
     40                      right.pop();
     41                      string temp = production.right[LL.production_num[i]-1 ];
     42                     if(temp=="k") continue;
     43                      while(temp.length()!=0){
     44                         string temp0 = temp.substr( temp.length()-1,1);
     45                         right.push(temp0);
     46                         temp = temp.substr(0,temp.length()-1);  
     47                     }
     48                      
     49                  }
     50             } 
     51             
     52         }
     53         
     54         print(left,right);
     55     }
     56     
     57     return 0;
     58 } 
     59 
     60 void print(string left,stack<string >  right){ 
     61     cout<<"#"<<left<<" & ";
     62     string temp="";
     63     while(!right.empty()){
     64         cout<<right.top();
     65         temp+=right.top();
     66         right.pop();
     67     }
     68     cout<<"#"<<endl;
     69     
     70     while(temp.length()!=0){
     71         string temp0 = temp.substr( temp.length()-1,1);
     72         right.push(temp0);
     73         temp = temp.substr(0,temp.length()-1);  
     74     }
     75     
     76     return ;
     77 }
     78 
     79 void input(){
     80     cin>>S;
     81     cin>>not_endsign.number;
     82     for(int i=0;i<not_endsign.number;i++){
     83         cin>>not_endsign.sign[i];
     84     }
     85     
     86     cin>>end_sign.number;
     87     for(int i=0;i<end_sign.number;i++){
     88         cin>>end_sign.sign[i];
     89     }
     90     
     91     cin>>production.number;
     92     for(int i=0;i<production.number;i++){
     93         cin>>production.order[i]>>production.left[i]>>production.right[i];
     94     }
     95     
     96     cin>>LL.number;
     97     for(int i=0;i<LL.number;i++){
     98         cin>>LL.order[i]>>LL.rank[i]>>LL.col[i]>>LL.production_num[i];
     99     }
    100     
    101     cin>>test;
    102     return ;
    103 }
    View Code
  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/liugl7/p/5341044.html
Copyright © 2011-2022 走看看