《2022年安徽工业大学编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《2022年安徽工业大学编译原理实验报告.docx(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、编译原理试验报告:叶玉虎班级:计 122 班指导老师:王森玉试验日期: 2021/5/11学习文档 仅供参考试验内容:试验环境:Visual Studio2021试验目的 :让同学们把握 FIRST集合和FOLLOW 集合的求法试验代码:#include #include #define MAX 50char cssMAXMAX;/储存全部的产生式int count=0; int cnt=0;struct L/ 储存全部的终结符char ch;int flag;/1: 能推出 ,0:不能,初值:-1 int num;char firstMAX; int s;/first 的长度char fol
2、lowMAX;int l;/follow 的长度lMAX;/对输入的格式进行掌握 ,并校验输入是否符合格式int handlechar aint len,i=0,j,k;len=strlena; whileai.=10ifai=$return 2;if =ai|9=aii+;continue;ifai=A&aielseprintf 产生式格式错误 n; return -1;j=i; k=0;whileaj.= &aj.=9&aj.=$&aj.=10ifaj=|csscountk=0; count+;ifaj+1= |aj=9|aj=$|aj=10printf 产生式格式错误 n; return
3、 0;csscount0=ai;csscount1=ai+1;csscount2=ai+2; k=3;j+;continue;csscountk=aj; k+;j+;elsecsscountk=0; i=j;count+;printf 产生式格式错误 n;return -1;return 0;/从键盘获得输入int inputn;char aMAX*MAX; int v;printf 输入产生式 ,产生式之间以空格回车或 Tab键分隔 ,并以$键终止 .n;printf 用表示虚拟符号 ,终结符用大写字母表示 ,其他字符表示非终结符while1fgetsa,MAX*MAX,stdin; v=h
4、andlea;ifv=-1return -1; ifv=2return 0;/求出能推出的非终结符void seekEmptyint i,j,k,t;int flag=0,flag2=0; int len,c;char aMAXMAX,ch; fori=0;icount;i+strcpyai,cssi;/求出含有的非终结符的个数 ,并把各终结符储存起来fori=0;icount;i+forj=0;jcnt;j+iflj.ch=ai0lj.num+; flag=1; break;elseflag=0;t|.flaglcnt.ch=ai0; lcnt.flag=-1;lcnt.num=1;lcnt
5、.s=0;lcnt.l=0; cnt+; flag=1; continue;c=count; whilecfori=0;ic;i+/假如该终结符推出,从 a 中删除全部带有该终结符的产生式ifai3=ch=ai0; forj=0;jc;j+ifch=aj0ifj.=c-1fork=j;kc-1;k+ strcpyak,ak+1;elsec-;j-;c-;j-;forj=0;jcnt;j+ifch=lj.chi-;lj.flag=1; break;continue;len=strlenai; forj=3;jlen;j+/当该产生式右边含有非终结符时从 a中删除该条记录ifaijZflag2=1
6、; break;ifflag2fork=0;kcnt;k+ifai0=lk.chlk.num-;iflk.num=0lk.flag=0; break;ifi.=c-1fork=i;kc-1;k+strcpyak,ak+1;c-;i-;flag2=0; continue;/假如产生式右边为非终结符看看该终结符能不能推出forj=3;j=A&aij=Zfork=0;kcnt;k+ifaij=lk.chiflk.flag=0flag2=1; break;else iflk.flag=1fort=j;tlen-1;t+ ait=ait+1;ailen-1=0;j-;len-; break;break;
7、ifflag2break;ifai3=0ch=ai0; forj=0;jc;j+ifch=aj0ifj.=c-1fork=j;kc-1;k+ strcpyak,ak+1;elsec-;j-;i-;c-;j-;fork=0;kcnt;k+ifch=lk.chlk.flag=1; break;ifflag2fork=0;kcnt;k+ifai0=lk.chlk.num-;iflk.num=0lk.flag=0;ifi.=c-1fork=i;kc-1;k+strcpyak,ak+1;c-;i-;flag2=0; continue;/求每个非终结符的 First集合void seekFirstVnin
8、t i,j,k,t,t1,t2,c,item;int len,s,flag=0,flag2=0,fchange; char aMAXMAX,chMAX;fori=0;icount;i+strcpyai,cssi;c=count; while1fchange=0; fori=0;ic;i+/右部为 ,将并入到左部的 First中ifai3=/*forj=0;jcnt;j+iflj.ch=ai0fork=0;klj.s;k+ iflj.firstk=ai3if.flagflag=1; break;lj.firstlj.s=ai3; lj.s+; lj.firstlj.s=0; fchange=1;
9、break;flag=0;*/从当前列表 a中删除ifi.=c-1forj=i;jc-1;j+ strcpyaj,aj+1;c-;i-;continue;len=strlenai;/产生式右边符号为终结符时 ,将该终结符并入到左部的 First集合中forj=3;jlen;j+ifaijZfork=0;kcnt;k+ifai0=lk.chfort=0;tlk.s;t+ifaij=lk.firsttflag=1; break;if.flaglk.firstlk.s=aij; lk.s+; lk.firstlk.s=0; fchange=1;flag=0; break;/从a 中删除该条产生式if
10、i.=c-1fork=i;k=A&aij=Z/* 将该非终结符的 FIRST集合除去并入到当前非终结符的 FIRST集合中 */fork=0;kcnt;k+ifaij=lk.chfort=0;tcnt;t+ifai0=lt.chfort1=0;t1lk.s;t1+fort2=0;t2lt.s;t2+iflk.firstt1=lt.firstt2break;ift2=lt.s&lk.firstt1.=fchange=1; lt.firstlt.s=lk.firstt1; lt.s+; lt.firstlt.s=0;break;break;iflk.flagcontinue;elsebreak;i
11、f.fchangefori=0;icnt;i+ifli.flagli.firstli.s=;li.s+; li.firstli.s=0;printfFIRST%c:%sn,li.ch,li.first;printfn; break;/求产生式右部的 First集合void seekFirstRightstruct Rightchar aMAX; char firstMAX; int s;rMAX;int i,j,k,t;int cnt=0,len,len1,flag=0; fori=0;icount;i+forj=0;jcnt;j+if.strcmpcssi+3,rj.aflag=1; bre
12、ak;ifflagflag=0; continue;strcpyrj.a,cssi+3; rj.s=0;cnt+;fori=0;icnt;i+len=strlenri.a; forj=0;jlen;j+/遇到终结符ifri.aj=ri.firstri.s=; ri.s+; ri.firstri.s=0; break;else ifri.ajZelseri.firstri.s=ri.aj; ri.s+; ri.firstri.s=0; break;fork=0;kcnt;k+ifri.aj=lk.chlen1=strlenlk.first; fort=0;tlen1;t+iflk.firstt.
13、=ri.firstri.s=lk.firstt; ri.s+; ri.firstri.s=0;break;iflk.flagifj=len-1ri.firstri.s=; ri.s+; ri.firstri.s=0;continue;elsebreak;fori=0;icnt;i+printfFIRST%s: %sn,ri.a,ri.first;printfn;/求每个非终极符的 Follow集合void seekFollowint i,j,k,t,t1,t2,t3,c=0; int flag=0,len;int fchange;/判定一次循环是否有改动的地方char aMAXMAX,chMA
14、X;fori=0;icount;i+len=strlencssi; forj=3;j=A&cssij=Zbreak;ifj.=lenstrcpyac,cssi; c+;l0.followl0.l=#; l0.l+;l0.followl0.l=0;while1fchange=0; fori=0;ic;i+len=strlenai; forj=3;j=A&aij=A&aij-1=Zfork=0;kcnt;k+ifaij-1=lk.chfort=0;tcnt;t+ifaij=lt.chfort1=0;t1lt.s;t1+iflt.firstt1= continue;fort2=0;t2=A&cht3
15、=Zfork=0;kcnt;k+ifch0=lk.chfort=0;tcnt;t+ifcht3=lt.chfort1=0;t1lk.l;t1+fort2=0;t2=A&aij-1=Zfork=0;kcnt;k+ifaij-1=lk.chfort=0;tlk.l;t+ ifaij=lk.followtbreak; ift=lk.lfchange=1; lk.followlk.l=aij; lk.l+; lk.followlk.l=0;if.fchangefori=0;iMH|aH-LSo| K-dML| L-eHfM-K|bLM测试数据 2: S-aHH-aMd|d M-Ab| A-aM|e试验感想 :经过这几次的试验,不仅让我们更加深刻的知道了first集合和 follow集合的运算步骤和方法, 仍很好的培育了我们动手才能;虽然这两个集合用笔算的方法很简洁,但是要让电脑来演算就不是那么简洁了,这需要设计合理的数据结构和算法才能正确地求出结果;当然在设运算法的时候难免会显现错误,这就需要我们这些程序员们认真的去调试,发觉错误并改正; 本以为这次的试验代码不会很长,但是实际写好了却有好几百行,可能是我的算法不够好吧; 总的来讲这次的试验没有遇到太大的问题,由于课上老师很认真的给我们讲解了它 们的求法,笔推也做了好几次练习,让我们理清了思路;