递归下降语法分析

一、实验目的:

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

 

二、实验原理

每个非终结符都对应一个子程序。

该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

  • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
  • 每遇到一个非终结符,则调用相应的子程序

 

三、实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

例如:

输入begin a:=9;x:=2*3;b:=a+x end #

输出success

输入x:=a+b*c  end #

输出‘end' error

 

四、实验步骤

1.待分析的语言的语法(参考P90)

2.将其改为文法表示,至少包含

–语句

–条件

–表达式

3. 消除其左递归

4. 提取公共左因子

5. SELECT集计算

6. LL(1)文法判断

7. 递归下降分析程序

 

1. 文法 G(S):

(1)S -> AB

(2)A ->Da|ε

(3)B -> cC

(4)C -> aADC |ε

(5)D -> b|ε

验证文法 G(S)是不是 LL(1)文法?

First(A)={b,a}

First(B)={c}

First(C)={a}

First(D)={b}

First(ε)={ε}

 Follow(A)={c,b,a,#}

Follow(B)={#}

Follow(C)={#}

Follow(D)={a,#}

Select(A ->Da)=First(Da)={b,a}

Select(A ->ε)=First(ε)-{ε} U Follow(A)={c,b,a,#}

Select(A ->Da) ∩ Select(A ->ε)={b,a}≠∅

G(S)不是 LL(1)文法

 

2.(上次作业)消除左递归之后的表达式文法是否是LL(1)文法?

First(TE’)=First(T)={ ( , i }

First(T’)={ * , ε }

First(E’)={ + , ε }

First(+TE’)={+}

First(ε)={ε}

First(FT’)=First(F)={ ( , i }

First(*FT’)={*}

First((E))={ ( }

First(i)={ i }

 

Follow(E)={ ) , #}

Follow(E’)=Follow(E)={ ) , #}

Follow(T)=(First(E’)-{ε}) U Follow(E’)={ + , ) , #}

Follow(T’)=Follow(T)={ + , ) , #}

Follow(F)=(First(T’)-{ε}) U Follow(T’)={* , + , ) , #}

 

Select(E->TE') =First(TE’)=First(T)={ ( , i }

Select(E'->+TE') =First(+TE’)= { + }

Select(E'->ε) = (First(ε) -{ε}) U Follow(E') = { ) , # }

Select(T->FT') = First(FT’)=First(F)={ ( , i }

Select(T'->*FT') = First(*FT')={ * }

Select(T'->ε) = First(ε) -{ε} U Follow(T') = { + , ) , # }

Select( F->(E)) = First((E))={ ( }

Select( F->i )=First(i)= { i }

 

Select(E’ -> +TE’) ∩ Select(E'->ε) = Ø

Select(T'->*FT') ∩ Select(T'->ε) = Ø

Select( F->(E)) ∩ Select( F->i ) = Ø

是LL(1)文法

3.接2,如果是LL(1)文法,写出它的递归下降语法分析程序代码。

E()

    {T();

       E'();

     }

E'()

T()

T'()

F()

 

void ParseE(){

 

  switch(lookahead){

 

    case '(','i':

      ParseT();

      ParseE'();

 

      break;

 

    default:

 

      print("syntax error \n");

      exit(0);

 

   }

 

 }

 

void ParseE'(){

  switch(lookahead){

 

    case '+':

      MatchToken('+');

      ParseT();

      ParseE'();

 

      break;

 

    case ')','#':

 

      break;

 

    default:

 

      print("syntax error \n");

      exit(0);

   }

 

 }

 

void ParseT(){ 

 

  switch(lookahead){

 

    case '(','i':

      ParseF();

      ParseT'();

 

      break;

 

    default:

 

      print("syntax error \n");

      exit(0);

   }

 

 }

 

void ParseT'(){

 

  switch(lookahead){

 

    case '*':

      MatchToken('*');

      ParseF();

      ParseT'();

 

      break;

 

    case '+',')','#':

 

      break;

 

    default:

 

      print("syntax error \n");

      exit(0);

   }

 }

 

void ParseF(){

 

  switch(lookahead){

 

    case '(':

      MatchToken('(');

      ParseE();

      MatchToken(')');

 

      break;

 

    case 'i':

      MatchToken('i');

      break;

      default:

 

      print("syntax error \n");

      exit(0);

   }

 }

 4.加上实验一的词法分析程序,形成可运行的语法分析程序,分析任意输入的符号串是不是合法的表达式。

 1 //引入头文件 
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 //声明变量 
  6 char prog[800],dc[8]; //程序段  单词 
  7 char ch;  //单词中的字符 
  8 int syn,p,m=0; //单词符号种别码   指针p 
  9 int n,sum=0;  //整数sum 
 10 char *word[6]={"begin","if","then","while","do","end"};  //保留字 
 11 int kk=0; //判断是否有错误 
 12 //声明函数 
 13 void scaner();
 14 void lrparser();
 15 void yucu();
 16 void statement();
 17 void condition();
 18 void expression();
 19 void term();
 20 void factor();
 21 
 22 void scaner(){  //读取一个字符 
 23     m=0;
 24     //初始化数组dc 
 25     for(n=0;n<8;n++){
 26         dc[n]=NULL;
 27     }
 28     ch=prog[p++];
 29     //遇到空格指针加1 
 30     while(ch==' '){
 31         ch=prog[p];
 32         p++;
 33     }
 34     //标识符 
 35     if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
 36         m=0;
 37         while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
 38             dc[m++]=ch;
 39             ch=prog[p++];
 40         }
 41         p--;
 42         syn=10;
 43         //保留字 
 44         for(n=0;n<6;n++){
 45             if(strcmp(dc,word[n])==0){
 46                 syn=n+1;
 47                 break;
 48             }
 49         }
 50     }
 51     //数字 
 52     else if((ch>='0'&&ch<='9')){
 53         sum=0;
 54         while((ch>='0'&&ch<='9')){
 55             sum=sum*10+ch-'0';
 56             ch=prog[p++];
 57         }
 58         p--;
 59         syn=11;
 60     }
 61     else{
 62         switch(ch){
 63             case '<':m=0;
 64                 dc[m++]=ch;
 65                 ch=prog[p++];
 66                 if(ch=='>'){
 67                     syn=22;
 68                     dc[m++]=ch;
 69                 }
 70                 else if(ch=='='){
 71                     syn=21;
 72                     dc[m++]=ch;
 73                 }
 74                 else{
 75                     syn=20;
 76                     p--;
 77                 }
 78                 break;
 79             case '>':m=0;
 80                 dc[m++]=ch;
 81                 ch=prog[p++];
 82                 if(ch=='='){
 83                     syn=24;
 84                     dc[m++]=ch;
 85                 }
 86                 else{
 87                     syn=23;
 88                     p--;
 89                 }
 90                 break;
 91             case ':':m=0;
 92                 dc[m++]=ch;
 93                 ch=prog[p++];
 94                 if(ch=='='){
 95                     syn=18;
 96                     dc[m++]=ch;
 97                 }
 98                 else{
 99                     syn=17;
100                     p--;
101                 }
102                 break;
103             case '*':syn=15;dc[0]=ch;break;
104             case '/':syn=16;dc[0]=ch;break;
105             case '+':syn=13;dc[0]=ch;break;
106             case '-':syn=14;dc[0]=ch;break;
107             case '=':syn=25;dc[0]=ch;break;
108             case ';':syn=26;dc[0]=ch;break;
109             case '(':syn=27;dc[0]=ch;break;
110             case ')':syn=28;dc[0]=ch;break;
111             case '#':syn=0;dc[0]=ch;break;
112             case '\n':syn=-2;dc[0]=ch;break;        
113         }
114     }
115 }
116 
117 //程序,判断是否以begin开始,end #结束 
118 void lrparser(){
119     if (syn==1) { //begin
120         scaner();
121         yucu();
122         if (syn==6) { //end
123             scaner();
124             if (syn==0 && kk==0){
125                 printf("success \n");
126             } 
127         } 
128         else {
129             printf("error,lose 'end' ! \n");
130             kk=1;
131             exit(0);
132         }
133     } 
134     else {
135         printf("error,lose 'begin' ! \n");
136         kk=1;
137         exit(0);
138     }
139     return;
140 }
141 
142 //语句串 
143 void yucu() {
144     statement();
145     while(syn==26) { 
146         scaner();
147         statement();
148     }
149     return;
150 }
151 //语句 
152 void statement(){
153     if (syn==10) { //为标识符
154         scaner();
155         if (syn==18) { //为 :=
156             scaner();
157             expression();
158         } 
159         else {
160             printf("error!");
161             kk=1;
162             exit(0);
163         }
164     }
165     else if(syn==2){  //为if 
166         condition();
167         scaner();
168         if(syn==3){
169             statement(); 
170         }
171         else{
172             printf("error,lose 'then' ! \n");
173             kk=1;
174             exit(0);
175         }
176     }
177     else {
178         printf("error!");
179         kk=1;
180         exit(0);
181     }
182     
183     return;
184 }
185 //条件
186 void condition(){
187     expression();
188     if(syn==25||syn==0||syn==20||syn==21||syn==23||syn==24){
189         scaner(); 
190     }
191     else{
192         printf("error! \n");
193         kk=1;
194         exit(0);
195     }
196     expression();
197     return;
198 } 
199 //表达式 
200 void expression(){
201     term();
202     while(syn==13 || syn==14) {
203         scaner();
204         term();
205     }
206     return;
207 }
208 //
209 void term(){
210     factor();
211     while(syn==15 || syn==16) {
212         scaner();
213         factor();
214     }
215     return;
216 }
217 //因子 
218 void factor(){
219     if(syn==10 || syn==11){
220         scaner(); //为标识符或整常数时,读下一个单词符号
221     }
222     else if(syn==27) {
223         scaner();
224         expression();
225         if(syn==28){
226             scaner();
227         }
228         else {
229             printf(" ')' 错误\n");
230             kk=1;
231             exit(0);
232         }
233     } else {
234         printf("表达式错误\n");
235         kk=1;
236         exit(0);
237     }
238     return;
239 }
240 int main(void){
241     //指针从0开始
242     p=0;
243     int i;
244     printf("请输入源程序:\n");
245     do {
246         scanf("%c",&ch);
247         prog[p++]=ch;
248     } while(ch!='#');
249     //指针从0开始 
250     p=0;
251     do{
252         scaner();
253         lrparser();
254     }while(syn!=0);
255     printf("语法分析结束!\n");
256     
257 } 
posted @ 2019-11-28 16:30  Doctor-Chan  阅读(733)  评论(0编辑  收藏  举报