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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM