版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
编译原理实验2——语法分析(C++代码实现)⼀、实验⽬的语法分析是编译程序中的核⼼部分。本实验通过设计⼀个典型的⾃顶向下语法分析程序——LL(1)语法分析程序,进⼀步理解并掌握语法分析的原理和实现技术。⼆、实验原理语法分析的主要任务是“组词成句”,将词法分析给出的单词序列按语法规则构成更⼤的语法单位,如“程序、语句、表达式”等;或者说,语法分析的作⽤是⽤来判断给定输⼊串是否为合乎⽂法的句⼦。按照⽣成语法树的⽅向不同,常⽤的语法分析⽅法有两类:⾃顶向下分析和⾃底向上分析。⾃顶向下分析也称⾯向⽬标的分析⽅法,也就是从⽂法的开始符出发,试图推导出与输⼊单词串相匹配的句⼦。⾃底向上分析也称移进-归约分析⽅法,从输⼊单词串开始,试图归约到⽂法的开始符。预测分析法(LL(1)⽅法)的基本思想是:从⽂法开始符S出发,从左到右扫描源程序,每次通过向前查看1个字符,选择合适的产⽣式,⽣成句⼦的最左推导。三、实验步骤与要求1、复习教材第4章,进⼀步理解LL(1)⽅法的原理和实现技术。根据预测分析程序的框图(教材P94-图5.11),编写⼀个语法分析程序。可根据⾃⼰的能⼒选择以下三项(由易到难)之⼀作为分析算法的输⼊:(1)根据⽂法,⼈⼯构造分析表M,直接输⼊表M。(2)输⼊⽂法的FIRST集和FOLLOW集,由程序⾃动⽣成该⽂法的预测分析表M。(3)输⼊⽂法,由程序⾃动⽣成该⽂法的预测分析表M。2、程序具有通⽤性,即所编制的LL(1)语法分析程序能够适⽤于不同⽂法以及各种输⼊单词串。3、有运⾏实例。对于输⼊的⼀个⽂法和⼀个单词串,语法分析程序应能正确地判断此单词串是否为该⽂法的句⼦,并要求输出分析过程。4、设计合理的数据结构,特别是⽂法、预测分析表、分析栈等的存储结构。四、实验代码//#include"pch.h"#include<iostream>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<stack>usingnamespacestd;voidGramF();//分解产⽣式程序voidGramIn();//⽂法输⼊程序voidWordIn();//⽂字输⼊程序boolIs(charx,chara[],intn);//是否在集合中voidGetFirst(chara);//first集求解程序voidADD(string&a,string&b);//集合相加程序集合voidADDfollow(string&a,string&b);//(follow)相加程序intBack(chara);//根据字母返回下标程序voidGetFollow(chara);//follow集求解程序boolIsChar(chara,stringb);//判断⼀个字符是否在⼀个集合中的程序voidFAtable();//预测分析表构建程序voidGAnalysis();//⽂法分析程序voidclearF();//净化程序voidcc();//i+()*ABCDEA->BCC->+BC|@B->DEE->*DE|@D->(A)|iinttable[100][100]={0};//预测表charVt[100]={""};//终结符charVn[100]={""};//⾮终结符stringGenerative[100]={""};//⽂法产⽣式存储stringGenerativeNew[100]={""};//⽂法产⽣式分解后的存储stringfirst[100]={""};//first集合stringfollow[100]={""};//follow集合charword[100]={""};//待测试的⽂字intVtNum=0;//终结符号的个数intVtNum=0;//终结符号的个数intVnNum=0;//⾮终结符号的个数intGenNum=0;//⽂法产⽣式个数intGenNumNew=0;//⽂法产⽣式分解后的个数stack<char>st;//预测分析栈voidcc(){inti,j,k,q,p;for(i=0;i<VnNum;i++){j=0;while(first[i][j]!='\0'){k=j+1;while(first[i][k]!='\0'){if(first[i][j]==first[i][k])first[i][k]='';k++;}j++;}q=0;while(first[i][q]!='\0'){if(first[i][q]!=''){break;}else{p=q+1;while(first[i][p]!=''){if(first[i][p]=='\0')break;else{first[i][q]=first[i][p];first[i][p]='';}}}q++;}q=0;while(first[i][q]!='\0'){if(first[i][q]=='')first[i][q]='\0';q++;}}}/*************************/分解⽂法产⽣式程序voidGramF(){intj,z=0,x;for(inti=0;i<GenNum;i++){x=0;while(1){charch1=Generative[i][x];if(ch1=='\0'||ch1=='|')break;GenerativeNew[z]+=Generative[i][x];x++;}z++;j=0;while(Generative[i][j]!='\0'){if(Generative[i][j]=='|'){j++;for(x=0;x<3;x++){GenerativeNew[z]+=Generative[i][x];}while(1){while(1){charch2=Generative[i][j];if(ch2=='\0'||ch2=='|')break;GenerativeNew[z]+=Generative[i][j];j++;}z++;}else{j++;}}}GenNumNew=z;}/************⽂法输⼊程序*************/voidGramIn(){inti=0;printf("请输⼊终结符号:\n");scanf_s("%c",Vt+i,1);while(*(Vt+i)!='\n'){i++;scanf_s("%c",Vt+i,1);}Vt[i]='#';i++;VtNum=i;//输⼊结束存储终结符号个数i=0;//i初始化值准备输⼊⾮终结符号printf("请输⼊⾮终结符号:\n");scanf_s("%c",Vn+i,1);while(*(Vn+i)!='\n'){i++;scanf_s("%c",Vn+i,1);}VnNum=i;//输⼊结束存储⾮终结符号个数i=0;//i初始化值准备输⼊⽂法产⽣式printf("请输⼊⽂法产⽣式:\n");charch;while(cin>>Generative[i]){i++;if((ch=getchar())=='\n')break;}GenNum=i;//输⼊结束存储⽂法产⽣式个数}/************⽂字输⼊程序*************/voidWordIn(){printf("请输⼊您需要测试的⽂字:\n");inti=0;//getchar();scanf_s("%c",word+i);while(*(word+i)!='\n'){i++;scanf_s("%c",word+i);}}/************是否在集合中*************/boolIs(charx,chara[],intn){for(inti=0;i<n;i++){if(a[i]==x)returntrue;}returnfalse;returnfalse;}/************first集求解程序*************/voidGetFirst(chara){intk=0;for(inti=0;i<GenNumNew;i++){if(GenerativeNew[i][0]!=a)continue;if(Is(GenerativeNew[i][3],Vt,VtNum)){//如果该⾮终结符产⽣式右部第⼀个字符是终结符,号则直接将其计⼊左部⾮终结符的FIRST集first[Back(GenerativeNew[i][0])]+=GenerativeNew[i][3];}elseif(Is(GenerativeNew[i][3],Vn,VnNum)){//如果该⾮终结符号右部第⼀个字符是⾮终结符,号则对该右部第⼀个字符的FIRST进⾏求解,并将其加⼊左部字符的GetFirst(GenerativeNew[i][3]);FIRST集ADD(first[Back(GenerativeNew[i][0])],first[Back(GenerativeNew[i][3])]);}elseif(GenerativeNew[i][3]=='@'){//,FIRST如果该⾮终结符产⽣式是个空则将空加⼊左部字符的集intj=0;while(first[Back(GenerativeNew[i][0])][j]!='\0'){if(first[Back(GenerativeNew[i][0])][j]=='@'){k=1;break;}j++;}if(!k)first[Back(GenerativeNew[i][0])]+='@';}}}/************follow*************/集清除重复元素程序voidclearF(){inti,j,k,q,p;//follow集下⾯是清除for(i=0;i<VnNum;i++){j=0;while(follow[i][j]!='\0'){k=j+1;while(follow[i][k]!='\0'){if(follow[i][j]==follow[i][k])follow[i][k]='';k++;}j++;}q=0;p=0;while(follow[i][q]!='\0'){if(follow[i][q]!=''){break;}else{p=q+1;while(follow[i][p]!=''){if(follow[i][p]=='\0')break;else{follow[i][q]=follow[i][p];follow[i][p]='';}}}q++;}}q=0;while(follow[i][q]!='\0'){if(follow[i][q]=='')follow[i][q]='\0';q++;}}}/************集合相加程序*************/voidADD(string&a,string&b){inti=0,zk=1,j=0;while(b[j]!='\0'){i=0;zk=1;while(a[i]!='\0'){if(b[j]==a[i]||b[j]=='@'){zk=-1;break;}i++;}if(zk==1)a+=b[j];j++;}}/************集合(follow)相加程序*************/voidADDfollow(string&a,string&b){inti=0,zk=1,j=0;while(b[j]!='\0'){i=0;zk=1;while(a[i]!='\0'){if(b[j]==a[i]){zk=-1;break;}i++;}if(zk==1)a+=b[j];j++;}}/************follow集求解程序*************/voidGetFollow(chara){inti=Back(a),j;//if(i==0||i==1||i==2||i==3){//如果待求解字符是开始字符,则把'#'加⼊其//if(IsChar(a,follow[Back(a)]))follow[Back(a)]+='#';FOLLOW集for(j=0;j<GenNumNew;j++){if(GenerativeNew[j][3]==a&&GenerativeNew[j][4]!='\0'){//如果是A->Bbif(Is(GenerativeNew[j][4],Vt,VtNum)){//如果b是终结符号,直接加⼊follow(B)if(IsChar(GenerativeNew[j][4],follow[Back(a)]))//判断b是否在follow(B)中continue;elsefollow[Back(a)]+=GenerativeNew[j][4];}elseif(Is(GenerativeNew[j][4],Vn,VnNum)){//如果b是⾮终结符号,需要判断if(IsChar('@',first[Back(GenerativeNew[j][4])])){//如果b可以推出空'@',则需要将follow(A)加⼊follow(B)GetFollow(GenerativeNew[j][0]);ADDfollow(follow[Back(a)],follow[Back(GenerativeNew[j][0])]);}ADD(follow[Back(a)],first[Back(GenerativeNew[j][4])]);ADD(follow[Back(a)],first[Back(GenerativeNew[j][4])]);}}elseif(GenerativeNew[j][4]==a&&GenerativeNew[j][5]!='\0'){//如果是A->aBbif(Is(GenerativeNew[j][5],Vt,VtNum)){//如果b是终结符号,直接加⼊follow(B)if(IsChar(GenerativeNew[j][5],follow[Back(a)]))//判断b是否在follow(B)中continue;elsefollow[Back(a)]+=GenerativeNew[j][5];}elseif(Is(GenerativeNew[j][5],Vn,VnNum)){//如果b是⾮终结符号,需进⾏判断if(IsChar('@',first[Back(GenerativeNew[j][5])])){//如果b可以推出空'@',则需要将follow(A)加⼊follow(B)GetFollow(GenerativeNew[j][0]);ADDfollow(follow[Back(a)],follow[Back(GenerativeNew[j][0])]);}ADD(follow[Back(a)],first[Back(GenerativeNew[j][5])]);}}elseif(GenerativeNew[j][4]==a&&GenerativeNew[j][5]=='\0'){//如果是A->aBGetFollow(GenerativeNew[j][0]);//直接将follow(A)加⼊follow(B)ADDfollow(follow[Back(a)],follow[Back(GenerativeNew[j][0])]);}}//}}/************判断⼀个字符是否在⼀个集合中的程序*************/boolIsChar(chara,stringb){inti=0;while(b[i]!='\0'){if(a==b[i])returntrue;i++;}returnfalse;}/*************************/预测分析表构建程序voidFAtable(){inti,j;for(i=0;i<VtNum;i++){for(j=0;j<GenNumNew;j++){if(Vt[i]==GenerativeNew[j][3])//如果终结符中则将A->a放⼊table[A,Vt[i]]Vt[i]A->afirst(a),在的中table[Back(GenerativeNew[j][0])][i]=j;elseif(Is(GenerativeNew[j][3],Vn,VnNum)){if(IsChar(Vt[i],first[Back(GenerativeNew[j][3])])){table[Back(GenerativeNew[j][0])][i]=j;}}elseif(GenerativeNew[j][3]=='@'){//如果当前的产⽣式是:A->a且,a='@',则判断当前的Vt[i]是否在if(IsChar(Vt[i],follow[Back(GenerativeNew[j][0])])){table[Back(GenerativeNew[j][0])][i]=j;}}}}}/************根据字母返回终结符下标程序*************/intBBack(chara){for(inti=0;i<VtNum;i++){if(a==Vt[i])returni;}return-1;}/************根据字母返回⾮终结符下标程序*************//************根据字母返回⾮终结符下标程序*************/intBack(chara){for(inti=0;i<VnNum;i++){if(a==Vn[i])returni;}return-1;}/************⽂法分析程序*************/voidGAnalysis(){inti=0,x,y,k,error=0,n=1;chara;stringchan="";st.push('#');st.push(Vn[0]);a=st.top();while(!(a==word[i]&&a=='#')){if(Is(st.top(),Vn,VnNum)){x=Back(st.top());y=BBack(word[i]);k=table[x][y];//获得产⽣式if(k==-1){error++;cout<<"步骤["<<n<<"]:识别错误!跳过"<<word[i]<<";\n";n++;i++;break;}else{chan=GenerativeNew[k];k=0;st.pop();while(chan[k]!='\0'){k++;}k--;if(chan[k]!='@'){while(chan[k]!='>'){st.push(chan[k]);k--;}//i++;cout<<"步骤["<<n<<"]:⽤"<<chan<<"的右部分逆序⼊栈已经完成;\n";n++;}else{cout<<"步骤["<<n<<"]:⽤"<<chan<<";\n";n++;//i++;}}}elseif(Is(st.top(),Vt,VtNum)){if(st.top()==word[i]){cout<<"步骤["<<n<<"]:匹配栈顶和当前符号"<<word[i]<<",成功;\n";st.pop();i++;n++;}else{cout<<"步骤["<<n<<"]:识别失败!!\n";n++;break;}}a=st.top();a=st.top();}if(error){cout<<"步骤["<<n<<"]:识别错误!!错误跳过次数:"<<error<<"\n";n++;}else{cout<<"步骤["<<n<<"]:识别成功!!\n";n++;}}voidChuShi(){for(inti=0;i<100;i++){for(intj=0;j<100;j++){table[i][j]=-1;}}}intmain(){usingstd::cout;cout.setf(std::ios::left);ChuShi();//初始化⼆维数组GramIn();//输⼊⾮终结、终结字符和⽂法产⽣式GramF();//⽂法产⽣式分析完毕inti,j;for(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 怒江云南怒江州福利彩票管理中心招聘龙江路公益大厅工作人员笔试历年参考题库附带答案详解
- 张掖2025年甘肃张掖市临泽县教育系统引进人才20人笔试历年参考题库附带答案详解
- 2025年度金融服务:企业融资贷款合同3篇
- 2025年度环保设施施工合同书2篇
- 南京江苏南京医科大学马克思主义学院招聘笔试历年参考题库附带答案详解
- 十堰2024年湖北丹江口市大学生乡村医生专项招聘3人笔试历年参考题库附带答案详解
- 2024年触摸屏及嵌入式控制系统项目可行性研究报告
- 上海2024年上海市金山区行政事业国有资产管理中心招聘笔试历年参考题库附带答案详解
- 2025年度金融机构外汇借款合同范本(含违约责任)6篇
- 2025年广西梧州住房公积金管理中心招聘历年高频重点提升(共500题)附带答案详解
- 新教材人教版高中物理选择性必修第二册全册各章节课时练习题及章末测验含答案解析(安培力洛伦兹力电磁感应交变电流等)
- 初级养老护理员培训全套
- 集中供热管网系统一次网的调节方法
- GB/T 41095-2021机械振动选择适当的机器振动标准的方法
- MRP、MPS计划文档教材
- 甲状腺疾病护理查房课件
- 安全安全带检查记录表
- GB∕T 26520-2021 工业氯化钙-行业标准
- 2022年浙江省绍兴市中考数学试题及参考答案
- Listen-to-this-3-英语高级听力-(整理版)
- 生活垃圾焚烧处理建设项目评价导则(2022)
评论
0/150
提交评论