不要被大段的代码吓到,其实问题很简单,只需照着书上的过程走即可。
实验要求:
输入文法及待分析的输入串,输出其预测分析过程及结果。(基本要求就是:所有字符都只有一个字符组成,不能出现A*等字符,你可自行修改自己的文法后在用下面的代码)
注明:代码分了多个写,主函数是1.cpp代码如下(后期我会再发个链接过来可直接看到源文件,对不太熟悉VS工具的比较有帮助),想看中间结果的话可以将注释解开即可:
#include"head.h" #include"apart_from.h" #include"first.h" #include"follw.h" #include"table.h" #include"judge.h" int main(){ int i=0,j; while((scanf("%s",form[i].formula),form[i].formula[0])!='#'){ i++; } sum = i; apart(); First(); Follow(); printf("非终结符:\n"); printf("%s\n",ter_symbol); printf("终结符:\n"); printf("%s\n",non_ter); /* printf("first集:\n"); for(j=0;j<strlen(ter_symbol);j++) printf("%s\n",first_set[j]); printf("follow集:\n"); for(j=0;j<strlen(ter_symbol);j++) printf("%s\n",follow_set[j]); */ getTable(); //printTable();//输出预测表 printf("输入串(以‘#’号键结束):\n"); scanf("%s",inter_symbol); while(inter_symbol[strlen(inter_symbol)-1]!='#'){ printf("输入串没有以‘#’号键结束,请重新输入:\n"); scanf("%s",inter_symbol); } printf("步骤 符号栈 输入串 所用产生式\n"); printf("---- ------ ------ ----------\n"); Judge(); return 0; }
apart_from.h的代码:
void apart(){ int i,len,k=0,j,l,p; for(i=0;i<sum;i++){ for(j=0;j<k;j++){ if(ter_symbol[j]==form[i].formula[0]) break; } if(j==k) ter_symbol[k++] = form[i].formula[0]; }//非终结符 ter_symbol[k]='\0'; k=0; for(i=0;i<sum;i++){ len = strlen(form[i].formula); for(j=3;j<len;j++){ if(form[i].formula[j]=='$') break; for(l=0;l<strlen(ter_symbol);l++){ if(form[i].formula[j]==ter_symbol[l]) break; } for(p=0;p<k;p++){ if(form[i].formula[j]==non_ter[p]) break; } if(l==strlen(ter_symbol)&&p==k){ non_ter[k++]=form[i].formula[j]; } } }//终结符 non_ter[k]='\0'; }
head.h的代码:
#include<stdio.h> #include<string.h> typedef struct { char formula[200];//表达式 }grammerElement; grammerElement form[200]; //原始文法的产生式集 int sum; char ter_symbol[200];//非终结符号 char non_ter[200];//终结符号 char inter_symbol[400];//输入符号 char first_set[100][100];//各产生式右部的FIRST集 char follow_set[100][100];//各产生式左部的FOLLOW集 int M[200][200];//分析表 //判断是非终结符 int get_ter(char a){ for(int i=0;i<strlen(ter_symbol);i++) if(ter_symbol[i]==a) return i; return -1; } //判断是终结符 int get_non(char a){ for(int i=0;i<strlen(non_ter);i++){ if(non_ter[i]==a) return i; } return -1; } //判断将要加入的first集的终结符是否已经存在。 int is_sameFir(int col,int stop,char a){ for(int i=1;i<stop;i++){ if(first_set[col][i]==a) return 0; } return 1; } //判断将要加入的follow集的终结符是否已经存在。 int is_sameFol(int col,int stop,char a){ for(int i=1;i<stop;i++){ if(follow_set[col][i]==a) return 0; } return 1; } void printTable(){ for(int i=0;i<strlen(ter_symbol);i++){ for(int j=0;j<strlen(non_ter)+1;j++) printf("%d ",M[i][j]); printf("\n"); } }
first.h的代码:
//求一个非终结符的first集 int getFirst(char a,int col){ int i,j,k=1,l,p; for(i=0;i<sum;i++){ if(form[i].formula[0]==a){ for(j=0;j<strlen(non_ter);j++){ if(form[i].formula[3]==non_ter[j]) break; } //判断是否是终结符 if(j<strlen(non_ter)){ if(is_sameFir(col,k,form[i].formula[3])) first_set[col][k++]=form[i].formula[3]; continue; }//右部首字母是终结符; else if(form[i].formula[3]=='$'){ if(is_sameFir(col,k,'$')) first_set[col][k++]='$'; continue; }//右部首字母是kong; else if(form[i].formula[3]==a) continue;//右部首字母是自己; else{//printf("%d 1\n",col); for(l=3;l<strlen(form[i].formula);l++){//循环表达式找 for(j=0;j<strlen(ter_symbol);j++){//printf("%d 2\n",col); if(form[i].formula[l]==ter_symbol[j]) break; }//找到非终结符的下标 if(j==strlen(ter_symbol)){//printf("%d 3\n",col); if(is_sameFir(col,k,form[i].formula[l])) first_set[col][k++]=form[i].formula[l]; break; }//循环中碰到终结符,结束 if(first_set[j][0]=='0') getFirst(form[i].formula[l],j);//printf("%d 4\n",col);}//first集未求,递归求first集 for(p=1;p<strlen(first_set[j]);p++){//检查first集有没有空 if(first_set[j][p]=='$') break; else if(is_sameFir(col,k,first_set[j][p])) //把非空的加进first集 first_set[col][k++]=first_set[j][p];//printf("%d 5\n",col);} } if(p==strlen(first_set[j])){//没有非空的就跳出 //flag=1; break; } } if(l==strlen(form[i].formula)&&is_sameFir(col,k,'$')) first_set[col][k++]='$'; } } } first_set[col][k]='\0'; first_set[col][0]='1';//标志已经求得first集 return 0; } void First(){ int i,len_ter=strlen(ter_symbol); for(i=0;i<len_ter;i++){ first_set[i][0]='0'; } for(i=0;i<len_ter;i++){ if(first_set[i][0]=='0') getFirst(ter_symbol[i],i); } }
follow.h的代码:
int getFollow(char a,int col){ int i,j,len,k=1,p,l,flag; if(col==0) k=2; for(i=0;i<sum;i++){ len=strlen(form[i].formula); for(j=3;j<len;j++){ flag=0; if(form[i].formula[j]==a){ if(j<len-1){//printf("%d %c1\n",col,a);//当前非终结符不是最终字符 for(p=0;p<strlen(ter_symbol);p++){ if(form[i].formula[j+1]==ter_symbol[p]) break; }//找到后边非终结符的下标 if(p==strlen(ter_symbol)){//终结符 if(is_sameFol(col,k,form[i].formula[j+1])) follow_set[col][k++]=form[i].formula[j+1];//printf("%d 2\n",col); continue; } else{//printf("%d 3\n",col);//非终结符 for(l=1;l<strlen(first_set[p]);l++) if(first_set[p][l]=='$')//将来会有漏洞 {flag=1;} else if(is_sameFol(col,k,first_set[p][l])){ follow_set[col][k++]=first_set[p][l]; } } }//if/ if(j==len-1||flag){//if(col==2) return 0;//printf("%d 4 %s %s\n",col,follow_set[0],follow_set[1]);// p=get_ter(form[i].formula[0]);//找到后边非终结符的下标 if(a==form[i].formula[0]) {//printf("%d 4 %s %s\n",col,follow_set[0],follow_set[1]); break;} if(follow_set[p][0]=='0'){ getFollow(ter_symbol[p],p); //printf("%d %c5\n",col,ter_symbol[p]); } for(l=1;l<strlen(follow_set[p]);l++){ if(is_sameFol(col,k,follow_set[p][l])) follow_set[col][k++]=follow_set[p][l]; } } } } } if(strlen(follow_set[col])>1) follow_set[col][0]='1'; follow_set[col][k]='\0'; return 0; } void Follow(){ int i; for(i=0;i<strlen(ter_symbol);i++){ follow_set[i][0]='0'; } //follow_set[0][0]='1'; follow_set[0][1]='#'; for(i=0;i<strlen(ter_symbol);i++){ // printf("%s\n",follow_set[0]); if(follow_set[i][0]=='0') getFollow(ter_symbol[i],i); //printf("%c...............\n",ter_symbol[i]);} } }
judge.h的代码:
int top; char stack[200]; int x; void Judge(){ stack[0]='#'; stack[1]=form[0].formula[0]; int flag=1,step=0; int i,j,l; char print[100]; top=1; x=0;//printf("---- ------ ------\n"); printf(" %d ",step++); for(l=0;l<=top;l++) printf("%c",stack[l]); for(l=0;l<=22-top+x;l++) printf(" "); for(l=x;l<strlen(inter_symbol);l++) printf("%c",inter_symbol[l]); printf("\n"); while(flag){ if(get_non(stack[top])>=0){ if(stack[top]==inter_symbol[x]){ x++;//终结符匹配上 top--; if(step<10) printf(" %d ",step++); else printf(" %d ",step++); for(l=0;l<=top;l++) printf("%c",stack[l]); for(l=0;l<=22-top+x;l++) printf(" "); for(l=x;l<strlen(inter_symbol);l++) printf("%c",inter_symbol[l]); printf("\n"); } else break; } else if(stack[top]=='#'){ if(stack[top]==inter_symbol[x]) flag=0;//彻底结束 else break; } else{ int col=get_ter(stack[top]); int row=get_non(inter_symbol[x]); if(inter_symbol[x]=='#') row=strlen(non_ter); if(M[col][row]>=0){//非终结符 if(form[M[col][row]].formula[3]=='$'){ top--; } else { for(i=strlen(form[M[col][row]].formula)-1;i>=3;i--){ stack[top++]=form[M[col][row]].formula[i]; } top--; } if(step<10) printf(" %d ",step++); else printf(" %d ",step++); for(l=0;l<=top;l++) printf("%c",stack[l]); for(l=0;l<=22-top+x;l++) printf(" "); for(l=x;l<strlen(inter_symbol);l++) printf("%c",inter_symbol[l]); for(l=0;l<=(11-strlen(inter_symbol));l++) printf(" "); printf("%s",form[M[col][row]].formula); printf("\n"); } else break; } } if(flag){ printf("输入串无法匹配成功!\n"); } else{ printf("输入串匹配成功!\n"); } }
table.h的代码:
void getTable(){//ter_symbol[200];//非终结符号 // non_ter[200];//终结符号 int i,j,k,col,row,flag=0; for(i=0;i<strlen(ter_symbol);i++){ for(j=0;j<strlen(non_ter)+1;j++) M[i][j]=-1; } for(i=0;i<sum;i++){//printf("lalallallalallalallalalla\n"); flag=0; if((row=get_non(form[i].formula[3]))>=0){//printf("%d %d 1\n",row,i); col=get_ter(form[i].formula[0]); M[col][row]=i; }//右部是终结符 else if((row=get_non(form[i].formula[3]))==-1){//非终结符和空 //if() col=get_ter(form[i].formula[0]);//左部是行坐标 k=get_ter(form[i].formula[3]);//右部非终结符的下标 if(k>=0){ for(j=1;j<strlen(first_set[k]);j++){ if(first_set[k][j]=='$'){//非终结符的first集有空 flag=1; continue; } row=get_non(first_set[k][j]); M[col][row]=i; } } if(form[i].formula[3]=='$') { flag=1;//printf("%c##########################\n",form[i].formula[3]); } if(flag){//右部为空,或者右部的first集有空 for(j=1;j<strlen(follow_set[col]);j++){ if(follow_set[col][j]=='#') row=strlen(non_ter); else row=get_non(follow_set[col][j]); M[col][row]=i; } } } } }