当前位置:文档之家› 编译原理实验报告材料(预测分析报告表方法)

编译原理实验报告材料(预测分析报告表方法)

预测分析表方法一、实验目的理解预测分析表方法的实现原理。

二、实验内容:编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。

可通过不同的文法(通过数据表现)进行测试。

三、实验步骤1.算法数据构造:构造终结符数组:char Vt[10][5]={“id”,”+”……};构造非终结符数组:char Vn[10]={ };构造follow集数组:char *follow[10][10]={ } (可将follow集与预测分析表合并存放)数据构造示例(使用的预测分析表构造方法1):/*data1.h简单算术表达式数据*/char VN[10][5]={"E","E'","T","T'","F"}; //非终结符表int length_vn=5; //非终结符的个数char VT[15][5]={"id","+","*","(",")","#"}; //终结符表int length_vt=6; //终结符的个数char Fa[15][10]={"TE'","+TE'","","FT'","*FT'","","(E)","id"};//产生式表:0:E->TE' 1:E'->+TE' 2:E'->空// 3:T->FT' 4:T'->*FT' 5:T'->空 6:F->(E) 7:F->idint analysis_table[10][11]={0,-1,-1,0,-2,-2,0,0,0,0,0,-1,1,-1,-1,2,2,0,0,0,0,0,3,-2,-1,3,-2,-2,0,0,0,0,0,-1,5, 4,-1,5, 5,0,0,0,0,0,7,-2,-2,6,-2,-2,0,0,0,0,0};//预测分析表,-1表示出错,-2表示该行终结符的follow集合,用于错误处理,正数表示产生式在数组Fa中的编号,0表示多余的列。

(1)预测分析表的构造方法1给文法的正规式编号:存放在字符数组中,从0开始编号,正规式的编号即为该正规式在数组中对应的下标。

如上述Fa数组表示存储产生式。

构造正规式数组:char P[10][10]={“E->TE’”,”E’->+TE’”,……..}; (正规式可只存储右半部分,如E->TE’可存储为TE’,正规式中的符号可替换,如可将E’改为M ) 构造预测分析表:int analyze_table[10][10]={ } //数组元素值存放正规式的编号,-1表示出错(2)预测分析表的构造方法2可使用三维数组Char analyze_table[10][10][10]={ }或Char *analyze_table[10][10]={ }2.针对预测分析表构造方法1的查预测分析表的方法提示:(1)查非终结符表得到非终结符的序号no1(2)查终结符表得到终结符的序号no2(3)根据no1和no2查预测分析表得到对应正规式的序号no3=analyze_table[no1][no2] ,如果no3=-1 表示出错。

(4)根据no3查找对应的正规式Fa[no3](5)对正规式进行处理3.错误处理机制紧急方式的错误恢复方法(抛弃某些符号,继续向下分析)(1)栈顶为非终结符A,串中当前单词属于FOLLOW(A),则从栈中弹出A(此时可认为输入串中缺少A表示的结构),继续分析。

---------错误编号为1(2)栈顶为非终结符A,串中当前单词不属于FOLLOW(A),则可使串指针下移一个位置(认为输入串中当前单词多余),继续分析。

----------错误编号为2(3)栈顶为终结符,且不等于串中当前单词,则从栈中弹出此终结符(认为输入串中缺少当前单词)或者将串指针下移一个位置(认为串中当前单词多余)。

在程序中可选择上述两种观点中的一种进行处理。

-------------错误编号3因此error()函数的编写方式可按如下方式处理Error(int errornum){If(errornum==1)………………Else if(errornum==2)……………Else ………………..//或者可用choose case语句处理}4.增加了错误处理的预测分析程序预测分析程序的算法:将“#”和文法开始符依次压入栈中;把第一个输入符号读入a;do{把栈顶符号弹出并放入x中;if(x∈VT){if(x==a) 将下一输入符号读入a;else error(3);}elseif(M[x,a]=“x→y1y2…yk”){按逆序依次把yk、yk−1、…、y1压入栈中;输出“x→y1y2…yk”;}else if a∈follow(x)error(1); else error(2);//在前述的数据定义中查表为-2表示a∈follow(x)}while(x!=“#”)给定算术表达式文法,编写程序。

测试数据:1.算术表达式文法E→TE’E’→ +TE’|- TE’|εT→FT’T’→*FT’ |/ FT’ |%FT’|εF→(E) |id|num给定一符合该文法的句子,如id+id*id$,运行预测分析程序,给出分析过程和每一步的分析结果。

输出形式参考下图($为结束符):#include<stdio.h>#include<string.h>#include<stdlib.h>#define TT 0char aa[20]=" ";int pp=0;# if TTchar VN[5]={'E','e','T','t','F'}; //非终结符表int length_vn=5; //非终结符的个数char VT[10]={'*','l','m','+','-','(',')','i','n','#'}; //终结符表l->/ m->% i->id n->numint length_vt=10; //终结符的个数charFa[12][6]={"Te","+Te","-Te","NULL","Ft","*Ft","nFt","mFt","NULL","(E)","i", "n"};//产生式表:0:E->Te 1:e->+Te 2:e->-Te 3:e->空charF[12][6]={"E->","e->","e->","e->","T->","t->","t->","t->","t->","F->","F->" ,"F->"};int analysis_table[5][10]={-2,-2,-2,-2,-2,0,-1,0,0,-1,-2,-2,-2,1,2,-2,3,-2,-2,3,-2,-2,-2,-1,-1,4,-1,4,4,-1,5,6,7,8,8,-2,8,-2,-2,8,-1,-1,-1,-1,-1,9,-1,10,11,-1};# elsechar VN[4]={'A','Z','B','Y'}; //非终结符表int length_vn=4; //非终结符的个数char VT[5]={'a','l','d','b','#'}; //终结符表int length_vt=5; //终结符的个数char Fa[6][6]={"aZ","ABl","NULL","dY","bY","NULL"};char F[6][6]={"A->","Z->","B->","Y->"};int analysis_table[4][5]={0,-2,-1,-2,-1,1,-2,2,-2,2,-2,-1,3,-2,-2,-2,5,-2,4,-2};# endifchar stack[50];int top=-1;void initscanner() //程序初始化:输入并打开源程序文件{int i=0;FILE *fp;if((fp=fopen("a.txt","r"))==NULL){printf("Open error!");exit(0);}char ch=fgetc(fp);while(ch!=EOF){aa[i]=ch;i++;ch=fgetc(fp);}fclose(fp);}void push(char a){top++;stack[top]=a;}char pop(){return stack[top--];}int includevt(char x){for(int i=0;i<length_vt;i++){if(VT[i]==x) return 1;}return 0;}int includean(char x,char a){int i,j;for(i=0;i<length_vn;i++)if(VN[i]==x) break;for(j=0;j<length_vt;j++)if(VT[j]==a) break;return analysis_table[i][j];}void destory(){int flag=0;int flagg=0;push('#'); //将"#"和文法开始符依次压入栈中push(VN[0]);char a=aa[pp]; //把第一个输入符号读入achar x;do{if(flag==0)x=pop(); //把栈顶符号弹出并放入x中flag=0;printf("%c\t\t\t%c\t",x,a);if(includevt(a)==1){if(includevt(x)==1){if(x==a){if(a=='#'){flagg=1;printf("结束\n");}else printf("匹配终结符%c\n",x);pp++;a=aa[pp]; //将下一输入符号读入a;}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}else if(includean(x,a)>=0){int h=includean(x,a);printf("展开非终结符%s%s\n",F[h],Fa[h]);int k;for(k=0;k<10;k++)if(Fa[h][k]=='\0') break;if(k==4){//printf("+++++++++++pop %c \n",x);}else{while(k!=0) //按逆序依次把yk、yk?1、…、y1压入栈中{k--;push(Fa[h][k]);}}}else if(includean(x,a)==-1){flag=1;printf("出错,从栈顶弹出%c\n",x);x=pop();}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}while(x!='#');if(flagg==0){printf("%c\t\t\t%c\t",x,a);printf("结束\n");}}int main(){printf("请输入1 or 0:\n");//scanf("%d",TT);printf("语法分析工程如下:\n");initscanner();printf("要分析的语句是:%s\n",aa);printf("语法分析工程如下:\n");printf("栈顶元素\t\t当前单词记号\t\t\t动作\n");printf("--------------------------------------------------------------------\n");destory();return 0;}四、实验小结我成功的完成了实验基本要求和选做内容。

相关主题