编译原理实验-词法语法分析-附源代码_第1页
编译原理实验-词法语法分析-附源代码_第2页
编译原理实验-词法语法分析-附源代码_第3页
编译原理实验-词法语法分析-附源代码_第4页
编译原理实验-词法语法分析-附源代码_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

编译原理实验报告**************************************************************************************************************************************************************<常量说明>::=CONST<常量定义>{,<常量定义>};<常量定义>::=<标识符>=<无符号整数><无符号整数>::=<数字>{<数字>}<变量说明>::=VAR<标识符>{,<标识符>};<标识符>::=<字母>{<字母>|<数字>}<过程说明>::=<过程首部><分程序>{;<过程说明>};<过程首部>::=PROCEDURE<标识符>;<语句>::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句><写语句>|<空><赋值语句>::=<标识符>:=<表达式><复合语句>::=BEGIN<语句>{;<语句>}END<条件语句>::=<表达式><关系运算符><表达式>|ODD<表达式><表达式>::=[+|-]<项>{<加法运算符><项>}<项>::=<因子>{<乘法运算符><因子>}<因子>::=<标识符>|<无符号整数>|‘(’<表达式>‘)’<加法运算符>::=+|-<乘法运算符>::=*|/<关系运算符>::==|#|<|<=|>|>=<条件语句>::=IF<条件>THEN<语句><过程调用语句>::=CALL标识符<当循环语句>::=WHILE<条件>DO<语句><读语句>::=READ‘(’<标识符>{,<标识符>}‘)’<写语句>::=WRITE‘(’<表达式>{,<表达式>}‘)’<字母>::=a|b|…|X|Y|Z<数字>::=0|1|…|8|9【预处理】对于一个pl0文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。【实验一】词法分析【实验目的】给出PL/0文法规范,要求编写PL/0语言的词法分析程序。【实验内容】已给PL/0语言文法,输出单词(关键字、专用符号以及其它标记)。【实验要求】确定编译中使用的表格、标识符与关键字的区分方法等。把词法分析器设计成一个独立一遍的过程。词法分析器的输出形式采用二元式序列,例如:【输入输出】输入:PL/0源程序。例:a+15*b输出:(ident,a)(plus,+)(number,15)(times,*)(ident,b)【实验结果】实验结果与实验要求相同,没有异议,对输入字符采取一个一个读入,到达句柄时,则采取LL(1)文法进行规约。实验结果如下:实验结果用文本来进行输入输出,所以在工程目录下还会有一个文本输入,输出文件。分别为in.txtout.txt【实验体会】在编写这段代码的过程中,比较麻烦得还是之前的语法预处理阶段,将不满足ll(1)文法的语法转化为标准的ll(1)文法。程序在处理词法分析的过程就是不断通过getsym()这个函数来条用getch(),不断形成一个一个的词汇,供下面语法分析时使用。记录词汇类型的sym是一个枚举类型。使用起来会方便许多,比较系统。其中还用到了文本输入输出的技巧,把读出的词汇保存起来。词法分析还是比较简单,在编写代码的时候没有太大的阻碍。通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。【实验二】语法分析【实验目的】给出PL/0文法规范,要求编写PL/0语言的语法分析程序。【实验内容】已给PL/0语言文法,构造表达式部分的语法分析器。【实验要求】将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。把语法分析器设计成一个独立一遍的过程。语法分析器的编写方法采用递归子程序法。【输入输出】输入:PL/0表达式,用实验一的输出形式作为输入。例如:对于PL/0表达式,输出:对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。【实验结果】实验结果与实验要求相同,没有异议,对输入字符采取一个一个读入,对输入的一个语句进行判断,判断语法的正误,采用对算法的判断,若全为数字则进行最后的计算【实验体会】通过语法分析可以判断当前输入语句是否正确,实验通过对数学式的处理来进行对语句的判断是否正确,若正确则只要输入“语句正确”即可,若语句错误则需要根据错误的原因输出错误的理由,以方便编译员修改自己的代码。实现方法是通过对文本文件的输入,当前数据与即将输入的字符串进行匹配,若不符合LL(1)文法则判定为错误,若符合则继续向下完成语法分析。【源代码】#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>#include<iostream>#include<stack>#include<string>#include<fstream>usingnamespacestd;ifstreamfin("in.txt");ofstreamfout("out.txt");enumsymbol{//0 1 23 4 5 6 7 nul, ident, number,plus, minus, times, slash, oddsym, eql, neq, lss, leq, gtr, geq, lparen, rparen, comma, semicolon, period, becomes, beginsym, endsym, ifsym, thensym, whilesym, writesym, readsym, dosym, callsym, constsym, varsym, procsym};#definesymnum32charsymwork[symnum][10];//单符号chara[al+1];//tempcharID[al+1];intcc=0,ll=0,num;//当前在行的位置cc,行字符的长度ll,num数字的值intnn=0;charline[81];intflg=0;//正数;//charline[81];enumsymbolssym[256];enumsymbolwsym[norw];//intcc,ll;//ch[cc]interr;voidinit(){ inti; for(i=0;i<=255;i++) ssym[i]=nul;//0 ssym['+']=plus; ssym['-']=minus; ssym['*']=times; ssym['/']=slash; ssym['(']=lparen; ssym[')']=rparen; ssym['=']=eql; ssym[',']=comma; ssym['.']=period; ssym['#']=neq;//notequal ssym[';']=semicolon; strcpy(&symwork[plus][0],"plus"); strcpy(&symwork[minus][0],"minus"); strcpy(&symwork[times][0],"times"); strcpy(&symwork[slash][0],"slash"); strcpy(&symwork[lparen][0],"lparen"); strcpy(&symwork[rparen][0],"rparen"); strcpy(&symwork[eql][0],"eql"); strcpy(&symwork[comma][0],"comma"); strcpy(&symwork[neq][0],"neq"); strcpy(&symwork[period][0],"period"); strcpy(&symwork[semicolon][0],"semicolon"); strcpy(&word[0][0],"begin");//关键字小写字母 strcpy(&word[1][0],"call"); strcpy(&word[2][0],"const"); strcpy(&word[3][0],"do"); strcpy(&word[4][0],"end"); strcpy(&word[5][0],"if"); strcpy(&word[6][0],"odd"); strcpy(&word[7][0],"procedure"); strcpy(&word[8][0],"read"); strcpy(&word[9][0],"then"); strcpy(&word[10][0],"var"); strcpy(&word[11][0],"while"); strcpy(&word[12][0],"write"); wsym[0]=beginsym; wsym[1]=callsym; wsym[2]=constsym; wsym[3]=dosym; wsym[4]=endsym; wsym[5]=ifsym; wsym[6]=oddsym;}voidWordAnalyse(){ switch(sym) { casenul://fout<<"("<<"nul"<<","<<ID<<")"<<endl; break; caseident:fout<<"("<<"ident"<<","<<ID<<")"<<endl; cout<<"("<<"ident"<<","<<ID<<")"<<endl;break; casenumber:fout<<"("<<"number"<<","<<num<<")"<<endl; cout<<"("<<"number"<<","<<num<<")"<<endl;break; caseplus:fout<<"("<<"plus"<<","<<ID<<")"<<endl; cout<<"("<<"plus"<<","<<ID<<")"<<endl;break; caseminus:fout<<"("<<"minus"<<","<<ID<<")"<<endl; cout<<"("<<"minus"<<","<<ID<<")"<<endl;break; casetimes:fout<<"("<<"times"<<","<<ID<<")"<<endl; caselss:fout<<"("<<"lss"<<","<<ID<<")"<<endl; cout<<"("<<"lsst"<<","<<ID<<")"<<endl;break; caseeql:fout<<"("<<"eql"<<","<<ID<<")"<<endl; cout<<"("<<"eql"<<","<<ID<<")"<<endl;break; caseneq:fout<<"("<<"neq"<<","<<ID<<")"<<endl; cout<<"("<<"neq"<<","<<ID<<")"<<endl;break; caseleq:fout<<"("<<"leq"<<","<<ID<<")"<<endl; cout<<"("<<"leq"<<","<<ID<<")"<<endl;break; casegtr:fout<<"("<<"gtr"<<","<<ID<<")"<<endl; cout<<"("<<"gtr"<<","<<ID<<")"<<endl;break; casegeq:fout<<"("<<"geq"<<","<<ID<<")"<<endl; cout<<"("<<"geqt"<<","<<ID<<")"<<endl;break; caselparen:fout<<"("<<"lparent"<<","<<ID<<")"<<endl; cout<<"("<<"lparent"<<","<<ID<<")"<<endl;break; caserparen:fout<<"("<<"rparent"<<","<<ID<<")"<<endl; cout<<"("<<"rparent"<<","<<ID<<")"<<endl;break; casecomma:fout<<"("<<"comma"<<","<<ID<<")"<<endl; cout<<"("<<"comma"<<","<<ID<<")"<<endl;break; casesemicolon:fout<<"("<<"semicolon"<<","<<ID<<")"<<endl; cout<<"("<<"semicolon"<<","<<ID<<")"<<endl;break; caseperiod:fout<<"("<<"period"<<","<<ID<<")"<<endl; cout<<"("<<"period"<<","<<ID<<")"<<endl;break; casebecomes:fout<<"("<<"becomes"<<","<<ID<<")"<<endl; cout<<"("<<"becomes"<<","<<ID<<")"<<endl;break; casebeginsym:fout<<"("<<"beginsym"<<","<<ID<<")"<<endl; cout<<"("<<"beginsym"<<","<<ID<<")"<<endl;break; caseendsym:fout<<"("<<"endsym"<<","<<ID<<")"<<endl; cout<<"("<<"endsym"<<","<<ID<<")"<<endl;break; caseifsym:fout<<"("<<"ifsym"<<","<<ID<<")"<<endl; cout<<"("<<"ifsym"<<","<<ID<<")"<<endl;break; casethensym:fout<<"("<<"thensym"<<","<<ID<<")"<<endl; cout<<"("<<"thensym"<<","<<ID<<")"<<endl;break; casewhilesym:fout<<"("<<"whilesym"<<","<<ID<<")"<<endl; cout<<"("<<"whilesym"<<","<<ID<<")"<<endl;break; casewritesym:fout<<"("<<"writesym"<<","<<ID<<")"<<endl; cout<<"("<<"writesym"<<","<<ID<<")"<<endl;break; casereadsym:fout<<"("<<"readsym"<<","<<ID<<")"<<endl; cout<<"("<<"readsym"<<","<<ID<<")"<<endl;break; }}intgetch(){ if(cc==ll) { if(fin.eof()) { cout<<"programincpmplete!!!"<<endl; return-1; } ll=cc=0; fin.getline(line,81); ll=strlen(line); ch=''; return0; } if(cc==0) cout<<line<<endl; ch=line[cc]; cout<<ch<<endl; cc++; nn=cc; return0;}#definegetchdoif(-1==getch())return-1//词法分析部分实验1intgetsym()//读符号大写字母不要出现{ inti,j,k; //用于循环等辅助计数 while(ch==''||ch==9||ch==10)////////////////////////////////////////// { getchdo; } getchdo; } ID[k]=0; i=0; j=norw; do/*搜索当前符号是否为保留字*/ { k=(i+j)/2; if(strcmp(ID,word[k])<=0)j=k-1; if(strcmp(ID,word[k])>=0)i=k+1; }while(i<=j); if(i-1>j)sym=wsym[k];elsesym=ident;/*搜索失败,则是名字或数字*/ } else { if(ch>='0'&&ch<='9') { k=0; num=0; sym=number; do{ ID[k]=ch; num=num*10+ch-'0'; k++; getchdo; }while(ch>='0'&&ch<='9'); if(flg==1){ num=-num; flg=0; } ID[k]=0; k--; if(k>nmax) sym=becomes; strcpy(ID,":="); getchdo; } else { sym=nul; strcpy(ID,"NULL"); } } else { if(ch=='>') { getchdo; if(ch=='=') { sym=geq; strcpy(ID,">="); getchdo; } else { sym=gtr; strcpy(ID,">"); } } else { if(ch=='<') { strcpy(ID,"<"); } } else { sym=ssym[ch]; strcpy(ID,&ch); //if(sym!=period) { getchdo; } } } } } } return1;}//语法分析部分实验2intlp=0;intrp=0;#definegetsymdoif(-1==getsym())return-1#defineexpressiondo()if(-1==expression())return-1#definetermdo()if(-1==term())return-1#definefactordo()if(-1==factor())return-1intexpression();//语法分析intfactor(){ if(sym!=ident&&sym!=number&&sym!=lparen) { err++; if(err==1)printf("语法错误:\n"); printf("error----FactorNeedsIdentorNumberorLparen\n"); } if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=rparen) { err++; if(err==1)printf("语法错误:\n"); printf("变量后没有跟上+-*\\\n"); } if(lp==0&&sym==rparen) { err++; if(err==1)printf("语法错误:\n"); printf("没有左括号匹配\n"); } } elseif(sym==number) { WordAnalyse(); if(getsym()==-1) { return-1; } if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=rparen) { err++; if(err==1)printf("语法错误:\n"); printf("数字后没有跟上+-*\\\n"); } if(lp==0&&sym==rparen) { err++; if(err==1)printf("语法错误:\n"); printf("没有左括号匹配\n"); { lp--; err++; if(err==1)printf("语法错误:\n"); printf("error----NeedsRparen\n"); return-1; } expressiondo(); if(sym==rparen) { WordAnalyse(); lp--; if(getsym()==-1) { return-1; } if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus) { err++; if(err==1)printf("语法错误:\n"); printf("括号后没有跟上+-*\\\n"); } } el

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论