递归下降语法分析
一、实验目的:
利用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 }