一、实验目的:
利用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 #include "string.h" 2 #include<stdio.h> 3 #include<stdlib.h> 4 char prog[80],token[8]; 5 int syn,p,m,n,sum=0; 6 char ch; 7 char *rwtab[6]= {"begin","if","then","while","do","end"}; 8 void lrparser(); 9 void yucu(); 10 void statement(); 11 void expression(); 12 void term(); 13 void factor(); 14 int kk=0; 15 16 int scaner() { 17 m=0; 18 for(n=0; n<8; n++) token[n]=NULL; 19 ch=prog[p++]; 20 while(ch==' ') ch=prog[p++]; 21 if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) { 22 while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) { 23 token[m++]=ch; 24 ch=prog[p++]; 25 } 26 token[m++]='\0'; 27 syn=10; 28 p=p-1; //回退一个字符 29 for(n=0; n<6; n++) { 30 if(strcmp(token,rwtab[n])==0) { 31 syn=n+1; 32 break; 33 } 34 } 35 } else if(ch>='0' && ch<='9') { 36 sum=0; 37 while(ch>='0' && ch<='9') { 38 sum=sum*10+ch-'0'; 39 ch=prog[p++]; 40 } 41 p=p-1; 42 syn=11; 43 } else { 44 switch(ch) { 45 case '<': 46 m=0; 47 token[m++]=ch; 48 ch=prog[p]; 49 if(ch=='>') { 50 syn=21; 51 token[m++]=ch; 52 } else if(ch=='=') { 53 syn=22; 54 token[m++]=ch; 55 } else { 56 syn=20; 57 p=p-1; 58 } 59 p=p+1; 60 token[m]='\0'; 61 break; 62 case '>': 63 m=0; 64 token[m++]=ch; 65 ch=prog[p++]; 66 if(ch=='=') { 67 syn=24; 68 token[m++]=ch; 69 } else { 70 syn=23; 71 p=p-1; 72 } 73 break; 74 case ':': 75 m=0; 76 token[m++]=ch; 77 ch=prog[p++]; 78 if(ch=='=') { 79 syn=18; 80 token[m++]=ch; 81 } else { 82 syn=17; 83 p=p-1; 84 } 85 break; 86 case '+': 87 syn=13; 88 token[0]=ch; 89 break; 90 case '-': 91 syn=14; 92 token[0]=ch; 93 break; 94 case '*': 95 syn=15; 96 token[0]=ch; 97 break; 98 case '/': 99 syn=16; 100 token[0]=ch; 101 break; 102 case ';': 103 syn=26; 104 token[0]=ch; 105 break; 106 case '(': 107 syn=27; 108 token[0]=ch; 109 break; 110 case ')': 111 syn=28; 112 token[0]=ch; 113 break; 114 case '=': 115 syn=25; 116 token[0]=ch; 117 break; 118 case '#': 119 syn=0; 120 token[0]=ch; 121 break; 122 default: 123 syn=-1; 124 } 125 } 126 } 127 void lrparser() { 128 if (syn==1) { //begin 129 scaner(); 130 yucu(); 131 if (syn==6) { //end 132 scaner(); 133 if (syn==0 && kk==0) printf("success \n"); 134 } else { 135 if(kk!=1) printf("error,lose 'end' ! \n"); 136 kk=1; 137 } 138 } else { 139 printf("error,lose 'begin' ! \n"); 140 kk=1; 141 } 142 return; 143 } 144 145 void yucu() { 146 statement(); 147 while(syn==26) { 148 scaner(); 149 statement(); 150 } 151 return; 152 } 153 154 void statement() { 155 if (syn==10) { //为标识符 156 scaner(); 157 if (syn==18) { //为 := 158 scaner(); 159 expression(); 160 } else { 161 printf("error!"); 162 kk=1; 163 } 164 } else { 165 printf("error!"); 166 kk=1; 167 } 168 return; 169 } 170 171 172 void expression() { 173 term(); 174 while(syn==13 || syn==14) { 175 scaner(); 176 term(); 177 } 178 return; 179 } 180 181 182 void term() { 183 factor(); 184 while(syn==15 || syn==16) { 185 scaner(); 186 factor(); 187 } 188 return; 189 } 190 191 192 void factor() { 193 if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号 194 else if(syn==27) { 195 scaner(); 196 expression(); 197 if(syn==28)scaner(); 198 else { 199 printf(" ')' 错误\n"); 200 kk=1; 201 } 202 } else { 203 printf("表达式错误\n"); 204 kk=1; 205 } 206 return; 207 } 208 209 210 int main() { 211 p=0;int i; 212 213 printf("请输入源程序:\n"); 214 do { 215 scanf("%c",&ch); 216 prog[p++]=ch; 217 } while(ch!='#'); 218 p=0; 219 scaner(); 220 lrparser(); 221 printf("语法分析结束!\n"); 222 // getch(); 223 } 224
引用于https://blog.csdn.net/Leslie___Cheung/article/details/78938252