电子科技大学计算机学院实验中心计算机专业类课程实验报告课程名称:编译原理学院:计算机科学与工程专业:计算机科学与技术学生姓名:林怡学号:2012060020023指导教师:陈昆日期:2015年6月5日电子科技大学实验报告实验一一、实验名称:词法分析器的设计与实现二、实验学时:4三、实验内容和目的:实验内容:求n!的极小语言的源程序作为词法分析的输入程序,根据给定的文法对其进行词法分析并将单词符号与种别组成的二元式按指定格式输出到out.dyd文件中,同时将词法错误输出到error.err文件中。其中二元式文件out.dyd有如下要求:(1)二元式形式:单词符号种别(2)每行后加上“...EOLN24”(3)文件结尾加上“...EOF25”出错文件error.err中错误信息格式如下:***LINE:行号错误性质电子科技大学计算机学院实验中心实验目的:通过设计并实现一个词法分析器,了解和掌握词法分析程序设计的原理及相应的程序设计方法,同时提高编程能力。四、实验原理:1、编译程序要求对高级语言编写的源程序进行分析和合成,生成目标程序。词法分析是对源程序进行的首次分析,实现词法分析的程序为词法分析程序。像用自然语言书写的文章一样,源程序是由一系列的句子组成的,句子是由单词符号按一定的规则构成的,而单词符号又是由字符按一定规则构成,因此,源程序实际上是由满足程序语言规范的字符按照一定的规则组合起来构成的一个字符串。2、词法分析的功能是从左到右逐个地扫描源程序字符串,按照词法规则识别出单词符号作为输出,对识别过程中发现的词法错误,输出相关信息。3、单词符号是程序语言最基本的语法符号,为便于语法分析,通常将单词符号分为五类(标识符,基本字,常数,运算符,界符),而本次实验中单词符号与其对应的种别如下图所示:4、状态转换图是有限有向图,是设计词法分析器的有效工具。图中的节点代表状态,节点间的有向边代表状态之间的转换关系,有向边上标记的字符表示状态转换的条件。本实验中的状态转换图如下图所示:5、本程序所设计主要方法及作用如下:①intisletter(charc)判别字符c是否为字母②intisdigital(charc)判别字符c是否为数字③intmatch_reserve(char*p)匹配字符串p是否为保留字④voidmatch_symbol(constchar*p)匹配字符串p是否为标识符电子科技大学计算机学院实验中心⑤voidmatch_double_operator(char*p)匹配字符串p是否为双运算符⑥voidmatch_single_operator(char*p)匹配字符串p是否为单运算符⑦voidoutfile()将词法分析所得的二元式按固定格式写入文件out.dyd五、实验器材(设备、元器件)C语言+windows7+CodeBlocks+gcc六、实验步骤:1、将源程序保存到in.pas文件中;2、从in.pas文件中读取字符串保存到buf数组,若整个输入文件已读取完毕,程序结束;3、每次从buf数组中读入一个字符,若已读到buf最后一个字符,返回第2步继续执行;3-a如果该字符是字母或数字将其连接到temp字符串尾部,buf索引index加1,判断buf[index]是否为0,若为0说明temp字符串为一完整单词,跳到第4步执行;若不为0,继续执行第3步;3-b如果读入的不是字母/数字,首先判断并匹配temp中是否已出现保留字/标识符,如果没有,通过预读buf中的下一个字符来进一步判断temp中存放的是单运算符还是双运算符或换行符,最终写入相应二元式,返回第3步继续执行;4、判断temp字符串是否为保留字,若不是保留字,进一步判断它是标识符还是常量,最终生成相应二元式,返回第3步继续执行;【注】这里省略了对于非法字符的出错处理七、实验数据及结果分析:1、测试程序如图,在测试程序中故意添加了一些词法错误如:将保留字写成begin,常数1kkk,符号!=,用于检测本实验程序的查错能力;2、程序运行完毕,得到out.dyd文件,内容如图所示:电子科技大学计算机学院实验中心3、报错文件error.err内容如图:由上图可以看出,本词法分析程序,可以识别部分非法的常数以及字母表以外的非法字符,但对于将begin写成begin这一类的词法错误,并未做处理,而是将其放到语法分析的部分来处理。八、实验结论、心得体会和改进建议:1、本词法分析程序可以正确的按照给定的文法识别出源程序中的单词符号及其对应的种别并生成相应的二元式文件,并具有一定的处理错误信息的能力;2、由实验结果截图可以看到,本实验仅能对一部分的词法错误作出响应,而一个完整的词法分析程序还应该能够识别出如标识符前缀为保留字等错误,并且错误信息文件.err中还应该包括行号,所以还可以对本实验进行改进;3、通过本次实验,我设计并实现了一个简单的词法分析器,在这个过程中加深了我对于词法分析的原理及其过程的理解,而对于词法错误的处理也在一定程度上提高了我的编程能力。电子科技大学计算机学院实验中心实验代码如下:#includestdio.h#includestring.h#includestdlib.h#defineBEGIN1#defineEND2#defineINTEGER3#defineIF4#defineTHEN5#defineELSE6#defineFUNCTION7#defineREAD8#defineWRITE9#defineSYMBOL10//标识符#defineCONSTANT11//常数#defineEQ12//=#defineNE13//#defineLE14//=#defineLT15//#defineBE16//=#defineBT17//#defineSUB18//-#defineMUL19//*#defineASSIGN20//:=#defineLBRAC21//(#defineRBRAC22//)#defineSEM23//;#defineBUFLEN50#defineTEMPLEN2*BUFLENinttype=0;charval[TEMPLEN];FILE*infile;//.pasFILE*outfile;//.dydFILE*errfile;//.errcharbuf[BUFLEN];//读入缓冲区chartemp[TEMPLEN];charreserve[2];/******判别是否字母*****/intisletter(charc){if(((c='a')&&(c='z'))||((c='A')&&(c='Z')))return1;elsereturn0;}/********判别是否数字********/intisdigital(charc){if(c='0'&&c='9')return1;return0;}/********匹配保留字******/intmatch_reserve(char*p){memset(val,0,TEMPLEN);if(!(strcmp(p,begin))){type=BEGIN;strcpy(val,begin);to_outfile();return1;}elseif(!(strcmp(p,end))){type=END;strcpy(val,end);to_outfile();return1;}elseif(!(strcmp(p,integer))){type=INTEGER;strcpy(val,integer);to_outfile();return1;}elseif(!(strcmp(p,if))){type=IF;电子科技大学计算机学院实验中心strcpy(val,if);to_outfile();return1;}elseif(!(strcmp(p,then))){type=THEN;strcpy(val,then);to_outfile();return1;}elseif(!(strcmp(p,else))){type=ELSE;strcpy(val,else);to_outfile();return1;}elseif(!(strcmp(p,function))){type=FUNCTION;strcpy(val,function);to_outfile();return1;}elseif(!(strcmp(p,read))){type=READ;strcpy(val,read);to_outfile();return1;}elseif(!(strcmp(p,write))){type=WRITE;strcpy(val,write);to_outfile();return1;}elsereturn0;}/**********匹配标识符**********/voidmatch_symbol(constchar*p,intlen){//以字母开头,是标识符if(isletter(p[0])){type=SYMBOL;strcpy(val,p);to_outfile();}//不是以字母开头的是常数elseif(isdigital(p[0])){type=CONSTANT;strcpy(val,p);to_outfile();inti;for(i=1;istrlen(val);i++){if(isletter(val[i]))fprintf(errfile,标识符%s不正确\n,val);break;}}//不是以字母开头也不是以数字开头的报错else{strcpy(val,p);to_outfile();fprintf(errfile,标识符%s不正确\n,val);}}/********匹配双运算符********/voidmatch_double_operator(char*p){if(!(strcmp(p,:=))){type=ASSIGN;strcpy(val,:=);to_outfile();}elseif(!(strcmp(p,))){type=NE;strcpy(val,);to_outfile();}电子科技大学计算机学院实验中心elseif(!(strcmp(p,=))){type=LE;strcpy(val,=);to_outfile();}elseif(!(strcmp(p,=))){type=BE;strcpy(val,=);to_outfile();}else{strcpy(val,p);to_outfile();fprintf(errfile,运算符%s不正确\n,val);}}/**********匹配单个运算符********/voidmatch_single_operator(char*p){if(!(strcmp(p,))){type=LT;strcpy(val,);to_outfile();}elseif(!(strcmp(p,))){type=BT;strcpy(val,);to_outfile();}elseif(!(strcmp(p,-))){type=SUB;strcpy(val,-);to_outfile();}elseif(!(strcmp(p,*))){type=MUL;strcpy(val,*);to_outfile();}elseif(!(strcmp(p,=))){type=EQ;strcpy(val,=);to_outfile();}elseif(!(strcmp(p,())){type=LBRAC;strcpy(val,();to_outfile();}elseif(!(strcmp(p,)))){type=RBRAC;strcpy(val,));to_outfile();}elseif(!(strcmp(p,;))){type=SEM;strcpy(val,;);to_outfile();}elseif(!(strcmp(p,