12.实验二 递归下降语法分析

 

 

 

 

 

一、实验目的

利用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.标识符(10)

2.无符号数(11)

3.保留字(一词一码)

4.运算符(一词一码)

5.界符(一词一码)

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 char prog[80],token[20]; // token: 单词符号的字符串
  5 char ch;
  6 int syn,n,sum; // syn:单词符号的种别码 sum:整数
  7 int p,m;  //下标 
  8 char *rwtab[6]= {"begin","if","then","while","do","end"}; 
  9 
 10 void fenxi();  //分析程序 匹配的方法
 11 void yuchu();   // 对语法进行预处理 
 12 void yuju();  //语句  匹配语法声明(赋值)
 13 void biaodashi();   //表达式 匹配运算符
 14 void term();    // 术语 */运算符 
 15 void factor();   //因素  匹配括号 
 16 int kk=0; //出错处理标记
 17 
 18 void scaner() {
 19     m=0;
 20     for(n=0; n<8; n++) token[n]=NULL;
 21     ch=prog[p++];
 22     while(ch==' ') ch=prog[p++];
 23     if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {
 24         while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {
 25             token[m++]=ch;
 26             ch=prog[p++];
 27         }
 28         token[m++]='\0';
 29         syn=10;
 30         printf("1.标 识 符 (%c,%d)\n",token[0],syn);
 31         p=p-1;      //回退一个字符
 32         for(n=0; n<6; n++) {
 33             if(strcmp(token,rwtab[n])==0) {
 34                 syn=n+1;
 35                 printf("3.保 留 字 (%s,%d)\n",token,syn);
 36                 break;
 37             }
 38         }
 39     } else if(ch>='0' && ch<='9') {
 40         sum=0;
 41         while(ch>='0' && ch<='9') {
 42             sum=sum*10+ch-'0';
 43             ch=prog[p++];
 44         }
 45         p=p-1;
 46         syn=11;
 47         printf("2.无符号数 (%d,%d)\n",sum,syn);
 48     } else {
 49         switch(ch) {
 50             case '+':
 51                 syn=13;
 52                 token[0]=ch;
 53                 printf("4.运 算 符 (%c,%d)\n",token[0],syn);
 54                 break;
 55             case '-':
 56                 syn=14;
 57                 token[0]=ch;
 58                 printf("4.运 算 符 (%c,%d)\n",token[0],syn);
 59                 break;
 60             case '*':
 61                 syn=15;
 62                 token[0]=ch;
 63                 printf("4.运 算 符 (%c,%d)\n",token[0],syn);
 64                 break;
 65             case '/':
 66                 syn=16;
 67                 token[0]=ch;
 68                 printf("4.运 算 符 (%c,%d)\n",token[0],syn);
 69                 break;
 70             case ':':
 71                 m=0;
 72                 token[m++]=ch;
 73                 ch=prog[p++];
 74                 if(ch=='=') {
 75                     syn=18;
 76                     token[m++]=ch;
 77                     printf("4.运 算 符 (:=,%d)\n",syn);
 78 //                    printf("运 算 符 (4,':=')\n");
 79                 } else {
 80                     syn=17;
 81                     p=p-1;
 82                     printf("4.运 算 符 (%c,%d)\n",token[0],syn);
 83                 }
 84                 break;
 85             case '<':
 86                 m=0;
 87                 token[m++]=ch;
 88                 ch=prog[p];
 89                 if(ch=='>') {
 90                     syn=21;
 91                     token[m++]=ch;
 92                     printf("4.运 算 符 (<>,%d)\n",syn);
 93                 } else if(ch=='=') {
 94                     syn=22;
 95                     token[m++]=ch;
 96                     printf("4.运 算 符 (<=,%d)\n",syn);
 97                 } else {
 98                     syn=20;
 99                     p=p-1;
100                     printf("4.运 算 符 (%c,%d)\n",token[0],syn);
101                 }
102                 p=p+1;
103                 token[m]='\0';
104                 break;
105             case '>':
106                 m=0;
107                 token[m++]=ch;
108                 ch=prog[p++];
109                 if(ch=='=') {
110                     syn=24;
111                     token[m++]=ch;
112                     printf("4.运 算 符 (>=,%d)\n",token[0],syn);   
113                 } else {
114                     syn=23;
115                     p=p-1;
116                     printf("4.运 算 符 (%c,%d)\n",token[0],syn);
117                 }
118                 break;
119             case '=':
120                 syn=25;
121                 token[0]=ch;
122                 printf("4.运 算 符 (%c,%d)\n",token[0],syn);
123                 break;
124             case ';':
125                 syn=26;
126                 token[0]=ch;
127                 printf("5.界    符 (%c,%d)\n",token[0],syn);
128                 break;
129             case '(':
130                 syn=27;
131                 token[0]=ch;
132                 printf("5.界    符 (%c,%d)\n",token[0],syn);
133                 break;
134             case ')':
135                 syn=28;
136                 token[0]=ch;
137                 printf("5.界    符 (%c,%d)\n",token[0],syn);
138                 break;
139             case '#':
140                 syn=0;
141                 token[0]=ch;
142                 break;
143             default:
144                 syn=-1;
145         }
146     }
147 }
148 //分析程序 匹配的方法
149 void fenxi() {  
150     if (syn==1) { //begin
151         scaner();
152         yuchu();
153         if (syn==6) { //end
154             scaner();
155             if (syn==0 && kk==0) printf("success \n"); // #
156         } else {
157             if(kk!=1) printf("error--lose 'end'\n");
158             kk=1;
159         }
160     } else {
161         printf("error--lose 'begin'\n");
162         kk=1;
163     }
164     return;
165 }
166 //对语法进行预处理
167 void yuchu() { 
168     yuju();
169     while(syn==26) {    // ;
170         scaner();
171         yuju();
172     }
173     return;
174 }
175 //语句  匹配语法声明(赋值)
176 void yuju() {
177     if (syn==10) { //为标识符
178         scaner();
179         if (syn==18) { //为 :=
180             scaner();
181             biaodashi();
182         } else {
183             printf("error");
184             kk=1;
185         }
186     } else {
187         printf("error");
188         kk=1;
189     }
190     return;
191 }
192  
193 //表达式 匹配运算符
194 void biaodashi() {
195     term();
196     while(syn==13 || syn==14) {  //+和-
197         scaner();
198         term();
199     }
200     return;
201 }
202  
203 // 术语 */运算符
204 void term() {
205     factor();
206     while(syn==15 || syn==16) {  // *和/
207         scaner();
208         factor();
209     }
210     return;
211 }
212 //因素  匹配括号
213 void factor() {
214     if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号
215     else if(syn==27) {   //
216         scaner();
217         biaodashi();
218         if(syn==28)scaner();  //
219         else {
220             printf("error--')'  \n");
221             kk=1;
222         }
223     } else {
224         printf("error\n");
225         kk=1;
226     }
227     return;
228 }
229  
230  
231 int main() {
232     p=0;int i;
233     printf("请输入源程序:\n");
234     do {
235         scanf("%c",&ch);
236         prog[p++]=ch;
237     } while(ch!='#');
238     printf("\n------分析结果------\n");
239     p=0;
240     scaner();
241     fenxi();
242     printf("分析结束!\n");
243 }
View Code

运行结果:

 

posted @ 2019-11-28 23:20  linyanli  阅读(325)  评论(0编辑  收藏  举报