编译原理预测分析表方法实验报告
- 格式:docx
- 大小:26.90 KB
- 文档页数:19
预测分析表方法一、实验目的理解预测分析表方法的实现原理。
二、实验内容:编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。
可通过不同的文法(通过数据表现)进行测试。
二、实验内容提示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.错误处理机制紧急方式的错误恢复方法(抛弃某些符号,继续向下分析)可认为输入串中缺少 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)-2 表示 a follow (x )else error(3);} elseif(M[x,a] =“ x f y1y2 …yk ”){按逆序依次把yk 、yk-1 、…、y1压入栈中;输出"x f y1y2 …yk ”;}else if a follow (x) error(1); else error (2);//在前述的数据定义中查表为 }while(x!=“ # ”)三•实验要求给定算术表达式文法,编写程序。
测试数据: 1 .算术表达式文法E f TE 'E ' f +TE '卜 TE ' | & T f FT 'T' f *FT' |/ FT ' |%FT ' | £F f (E) |id |n um孑F i y y F 41 > ・丄}} > > > -- > >一> --一一一J -一一*一JAE TF T一E rF T- F T E t^^itl洛+谒id符”符id语士匚±匚士匚摩匚士匚“住匚士匚庁匚厅匚丙匚士匚冬冬冬+1口冬冬吉冬空、土口冬土□冬吉冬冬,却二SN―-SN--Sh|」SMJ心士£J玄」总丁£一2"H-上^—£■士■』」:」匚」厂尸十二「二L椁^-二-二厂J?--yL厂utL~rr^N -----T7T7T7®4/42^r74/_®幵Sr3开呼开开東驚四展四展四驚结二一-二去・干巳-—pid$ tress any key to continueTEFTld>*号> >M T」符二E T FT頁TEs^id符矗丛善r+击口丄口士口^-n吉吉悅线线共结n结碁皱统—JLLLthr^x-11二-J^F.^M^LrrE—二二二■二**二一二一隽开幵配开开克出覆结idid给定一符合该文法的句子,如id+id*id$ ,运行预测分析程序,给出分析过程和每一步的分析结果。
输出形式参考下图($为结束符)札頂元素当前单词记号动作动作ress an</ key €o continue#in clude<stdio.h>i->id#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->%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 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);}elsewhile(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];}}elseflag=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);动作 \n");\n");printf(" 语法分析工程如下 :\n");printf(" 栈顶元素 \t\t 当前单词记号 \t\t\tprintf("destory(); return 0;。