编译原理词法分析程序实验报告(共20页).doc
精选优质文档-倾情为你奉上正规文法:ELB|N|SS|*|(|)|,|.|:=|;|>|<|=|>=|<=|<>NDN|DD0|1|2|3|4|5|6|7|8|9LA|B|C|.|Y|Z|a|b|c|.|y|zBLB|DB|L|D状态图: 空白 字母与数字210 字母 非字母与数字 *4 数字 非数字 5 +6 * . . .87 : = 1001109 > = . * . 非= . 120 其他其中一个圆圈的是非终态,两个圆圈的是终态,两个圆圈且带一个*的是终态且多读了一个字符。单词种别定义: 单词符号种别编码单词符号种别编码program116begin2*17end3(18var4)19int5,20and6.21or7:=22not8;23if9>24then10<25else11=26while12>=27do13<=28标示符14<>29常数(整)15 运行环境介绍:采用C+语言编写,VS2010编译调试。 关键算法描述: ch=fgetc(fp1); lineNum+; if (ch='/') ch=fgetc(fp1); lineNum+; if(ch='/') ch=fgetc(fp1); while (ch!=EOF&&ch!='n') ch=fgetc(fp1); if(ch='n') rowNum+; lineNum=0; else break; else if(ch='*'&&Mark!=1) long len=ftell(fp1); int rn=rowNum; int ln=lineNum; int sign=0; ch=fgetc(fp1); lineNum+; while (ch!=EOF&&sign!=2) if(ch='n') rowNum+; lineNum=0; if(ch='/'&&sign=1)sign=2; else sign=0; if(ch='*')sign=1; ch=fgetc(fp1); lineNum+; if(sign=2) fseek(fp1,-1L,1); lineNum-; else Mark=1; fseek(fp1,len-2,0); lineNum=ln-2; rowNum=rn; ch=' ' else Error_Handle(rowNum,lineNum-1);fseek(fp1,-1L,1);lineNum-; 此段代码主要用于对注释的处理,当读到一个字符是' / ',继续读其下一位字符,如果下一位字符是' / ',则其后整行内容作为注释,不对其进行词法分析,一直往后读直到遇到换行符'n' 。如果下一位字符是' * ',则一直往后读,直到遇到一个连续的*/,其中间内容作为注释,不对其进行词法分析;如果读到文件结尾也没用遇到一个连续的*/,则将字符指针移回' / '处,并将Mark变量置为1。如果下一位字符不是' / ',也不是' * '或Mark为1,则对/进行报错处理。此过程的状态转换图如下:3214 / 非 *76 / * * /5 非/ 不是' / ',也不是' * '或Mark为1 状态3表示为行注释,本行'/'后面的内容都是注释;状态7表示为/* */注释,/*和*/中间的内容为注释;状态5表示既不是行注释,也不是/* */注释,要进行其他处理(如:报错)。由于报错需要准错的指出错误的行号和列号,在程序中定义了两个变量rowNum和lineNum,每当读一个字符时,lineNum加1,当读到换行符时,rowNum加1,并将lineNum置0,在对注释进行处理的时候也遵循这样的操作。这样,即使有注释也可以准确的指出错误的行和列了。 else if(IsLetter(ch)while(IsLetter(ch)|IsDigit(ch) Concat(ch);ch=fgetc(fp1);lineNum+;fseek(fp1,-1L,1);lineNum-;int code=Reserve();if(code=0) int Id_Num=0;vector<string>:size_type i;for(i=0;i<Id.size();i+)if(stricmp(strToken,Idi.c_str()=0) Id_Num=i+1; break; if(Id_Num=0)Id.push_back(strToken);Tuple t;t.i=14;t.j=Id.size();return t;else Tuple t;t.i=14;t.j=Id_Num;return t;else Tuple t; t.i=code; t.j=-1; return t;此段代码主要是对标识符的处理,若读到一个字母,则一直往后读,直到读到的字符不是一个字母或数字,然后调用Reserve()函数判断此字符串是不是关键字,若是关键字则返回此关键字的种别编码;若是标识符,则查标识符表,若标识符表中无此标识符,则将此标识符加入标识符表,然后返回标识符的种别编码和在标识符表中的位置。最后将字符指针向前移一位else if(IsDigit(ch)while(IsDigit(ch) Concat(ch);ch=fgetc(fp1);lineNum+;fseek(fp1,-1L,1);lineNum-; int Id_Num=0;vector<string>:size_type i;for(i=0;i<Constant.size();i+)if(strcmp(strToken,Constanti.c_str()=0) Id_Num=i+1; break; if(Id_Num=0) Constant.push_back(strToken); Tuple t; t.i= 15; t.j=Constant.size(); return t; Tuple t; t.i= 15; t.j=Id_Num; return t;此段代码主要是对常数的处理,由于过程和上述对标识符的处理类似,故不再详细描述。测试报告:测试用例:Program example ; var int j,m,n; Begin /*there is * a / comment*/ i:=2; j:=6; m:=3; /there is a comment n:=j+m; If n>=3 and n<5 then j:=j-1; end . 测试结果:测试用例:program aa ; var int a ; begin a:=2; while a<10 do if a>3 then /*Here is a comment*/ begin if a<=5 then a:=4+a else a:=2*a; end /another comment else a:=a+1; end.测试结果:实验总结:通过这次实验,掌握了词法的形式化描述,熟悉了状态转换图,掌握了词法分析的一些基本思想,实验中也遇到了不少问题,但是通过查询有关资料,都一一解决了,学到了不少的东西。最后,感谢易萍雯老师的精心讲解。附件(源代码):#include "stdafx.h"#include <stdio.h> #include <string> #include <stdlib.h> #include <conio.h>#include <iostream>#include <vector> #include <cstring>using namespace std;struct Tuple int i;int j; class Lex_analysis FILE *fp1; char fname1100; char ch; char*RS 13; char strToken100; int rowNum; int lineNum; int Isopen; int Mark; vector<string> Id; vector<string> Constant; vector<Tuple> Error_info;public: Lex_analysis() Isopen=0;rowNum=1;lineNum=0;Mark=0;RS0="program"RS1="begin" RS2="end"RS3="var"RS4="int"RS5="and"RS6="or"RS7="not"RS8="if"RS9="then"RS10="else"RS11="while"RS12="do" ; int Reserve(); int IsLetter(char ch); int IsDigit(char ch); void Concat(char ch); void Error_Handle(int n,int m); void display_Error_info(); void dispaly_Id(); void dispaly_Constant(); Tuple Analysis(); ;Tuple Lex_analysis:Analysis() memset(strToken,0,sizeof(strToken); if(Isopen=0) cout<<"请?输?入?要癮进?行D词洙?法?分?析?的?文?件t路·径?"<<endl; cin>>fname1; if(fp1=fopen(fname1,"r")=NULL) printf("Cannot open file!"); _getch(); exit(1); Isopen=1; while (ch!=EOF) ch=fgetc(fp1); lineNum+; if (ch='/') ch=fgetc(fp1); lineNum+; if(ch='/') ch=fgetc(fp1); while (ch!=EOF&&ch!='n') ch=fgetc(fp1); if(ch='n') rowNum+; lineNum=0; else break; else if(ch='*'&&Mark!=1) long len=ftell(fp1); int rn=rowNum; int ln=lineNum; int sign=0; ch=fgetc(fp1); lineNum+; while (ch!=EOF&&sign!=2) if(ch='n') rowNum+; lineNum=0; if(ch='/'&&sign=1)sign=2; else sign=0; if(ch='*')sign=1; ch=fgetc(fp1); lineNum+; if(sign=2) fseek(fp1,-1L,1); lineNum-; else Mark=1; fseek(fp1,len-2,0); lineNum=ln-2; rowNum=rn; ch=' ' else Error_Handle(rowNum,lineNum-1);fseek(fp1,-1L,1);lineNum-; else if(ch=EOF);else if(ch=' ');else if(ch='t')lineNum=lineNum+3;else if(ch='n') rowNum+; lineNum=0; else if(IsLetter(ch)while(IsLetter(ch)|IsDigit(ch) Concat(ch);ch=fgetc(fp1);lineNum+;fseek(fp1,-1L,1);lineNum-;int code=Reserve();if(code=0) int Id_Num=0;vector<string>:size_type i;for(i=0;i<Id.size();i+)if(stricmp(strToken,Idi.c_str()=0) Id_Num=i+1; break; if(Id_Num=0)Id.push_back(strToken);Tuple t;t.i=14;t.j=Id.size();return t;else Tuple t;t.i=14;t.j=Id_Num;return t;else Tuple t; t.i=code; t.j=-1; return t;else if(IsDigit(ch)while(IsDigit(ch) Concat(ch);ch=fgetc(fp1);lineNum+;fseek(fp1,-1L,1);lineNum-; int Id_Num=0;vector<string>:size_type i;for(i=0;i<Constant.size();i+)if(strcmp(strToken,Constanti.c_str()=0) Id_Num=i+1; break; if(Id_Num=0) Constant.push_back(strToken); Tuple t; t.i= 15; t.j=Constant.size(); return t; Tuple t; t.i= 15; t.j=Id_Num; return t;else if(ch='+') Tuple t; t.i= 16; t.j=-1; return t;else if(ch='*') Tuple t; t.i= 17; t.j=-1; return t;else if(ch='(') Tuple t; t.i= 18; t.j=-1; return t;else if(ch=')') Tuple t; t.i= 19; t.j=-1; return t;else if(ch=',') Tuple t; t.i= 20; t.j=-1; return t;else if(ch='.') Tuple t; t.i= 21; t.j=-1; return t;else if(ch=':') ch=fgetc(fp1); if(ch='=') Tuple t; t.i= 22; t.j=-1; return t; Error_Handle(rowNum,lineNum);fseek(fp1,-1L,1);lineNum-;else if(ch='') Tuple t; t.i= 23; t.j=-1; return t;else if(ch='>') ch=fgetc(fp1); if(ch='=') Tuple t; t.i= 27; t.j=-1; return t; fseek(fp1,-1L,1); lineNum-; Tuple t; t.i= 24; t.j=-1; return t;else if(ch='<') ch=fgetc(fp1); if(ch='=') Tuple t; t.i= 28; t.j=-1; return t; else if(ch='>') Tuple t; t.i= 29; t.j=-1; return t; fseek(fp1,-1L,1); lineNum-; Tuple t; t.i= 25; t.j=-1; return t;else if(ch='=') Tuple t; t.i= 26; t.j=-1; return t;else Error_Handle(rowNum,lineNum); fclose(fp1); Tuple t; t.i=-1; t.j=-1; return t; int Lex_analysis: Reserve()for(int i=1;i<=13 ;i+)if(_stricmp(strToken,RSi-1)=0)return(i);return 0;void Lex_analysis:Concat(char ch)char C2; C0=ch; C1='0' strcat_s(strToken,C);int Lex_analysis:IsLetter(char ch)if(ch>='a'&&ch<='z')return 1;if(ch>='A'&&ch<='Z')return 1;return 0;int Lex_analysis:IsDigit(char ch)if(ch>='0'&&ch<='9')return 1;return 0;void Lex_analysis:Error_Handle(int n,int m)Tuple t;t.i=n;t.j=m;Error_info.push_back(t);void Lex_analysis:display_Error_info()cout<<"错误信息:"<<endl;vector<Tuple>:size_type i; for(i=0;i<Error_info.size();i+) cout<<i+1<<" :"<<"未识别的符号在"<<Error_infoi.i<<"行D"<<Error_infoi.j<<"列"<<endl;void Lex_analysis:dispaly_Id() cout<<"标示符表"<<endl; vector<string>:size_type i; for(i=0;i<Id.size();i+) cout<<i+1<<" "<<Idi<<endl;void Lex_analysis:dispaly_Constant() cout<<"常数表"<<endl; vector<string>:size_type i; for(i=0;i<Constant.size();i+) cout<<i+1<<" "<<Constanti<<endl;int _tmain(int argc, _TCHAR* argv)Lex_analysis L1;Tuple tupl;tupl=L1.Analysis();while(tupl.i!=-1)cout<<"("<<tupl.i<<" "if(tupl.j=-1)cout<<'-'<<")"<<endl;else cout<<tupl.j<<")"<<endl;tupl=L1.Analysis();L1.dispaly_Id();L1.dispaly_Constant();L1.display_Error_info();getch();return 0;专心-专注-专业