词法分析实验报告.pdf
编译原理实验一编译原理实验一学学号:号:专专业:软件工程业:软件工程2 2实验题目:词法分析实验题目:词法分析姓姓名:朱彦荣名:朱彦荣完成语言:完成语言:C/C+C/C+上级系统:上级系统:VC+VC+日日期:期:2015/11/72015/11/7词法分析词法分析设计题目:设计题目:手工设计 c 语言的词法分析器(可以是 c 语言的子集)设计内容:设计内容:处理 c 语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。设计目的:设计目的:了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。结果要求:结果要求:课程设计报告。完成日期:完成日期:第十五周提交报告一一分析分析要想要想手工设计词法分析器,实现手工设计词法分析器,实现 C C 语言子集的识别,就要明白语言子集的识别,就要明白什么是词什么是词法分析器法分析器,它的它的功能功能是什么。是什么。词法分析是编译程序进行编译时词法分析是编译程序进行编译时第一个要进行的第一个要进行的任务任务,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含的文件等)之后,的文件等)之后,对整个源程序进行分解对整个源程序进行分解,分解成,分解成一个个单词一个个单词,这些单词有且,这些单词有且只有五类只有五类,分别是,分别是标识符、保留字、常数、运算符、界符标识符、保留字、常数、运算符、界符。以便为下面的语法。以便为下面的语法分析和语义分析做准备。可以说词法分析面向的对象是分析和语义分析做准备。可以说词法分析面向的对象是单个的字符单个的字符,目的是把目的是把它们它们组成有效的单词(字符串)组成有效的单词(字符串);而;而语法的分析语法的分析则是利用词法分析的结果作为则是利用词法分析的结果作为输入来分析是否符合语法规则并且进行输入来分析是否符合语法规则并且进行语法制导语法制导下的语义分析,下的语义分析,最后产生最后产生四元四元组组(中间代码中间代码),进行优化(可有可无)之后最终生成,进行优化(可有可无)之后最终生成目标代码目标代码。可见词法分析。可见词法分析是所有是所有后续工作的基础后续工作的基础,如果这一步出错,如果这一步出错,比如明明是比如明明是=却被拆分成却被拆分成 和和=就会对下文造成不可挽回的影响。因此,在进行词法分析的时候一定就会对下文造成不可挽回的影响。因此,在进行词法分析的时候一定要定义好这五种符号的集合要定义好这五种符号的集合。下面是我构造的一个。下面是我构造的一个 C C 语言子集语言子集。第一类:标识符第一类:标识符 letter(letter|digit)*letter(letter|digit)*无穷集无穷集第二类:常数第二类:常数 (digit)+(digit)+无穷集无穷集第三类:保留字第三类:保留字(32)(32)auto break case char const continueauto break case char const continuedefault do double else enum externdefault do double else enum externfloat for goto if int longfloat for goto if int longregister return short signed sizeof staticregister return short signed sizeof staticstruct switch typedef union unsigned voidstruct switch typedef union unsigned voidvolatile whilevolatile while第四类:界符第四类:界符/*/*、.+33,39,39=,40=,40左移左移,59,59右移右移,上述二元组中左边是单词的符号,上述二元组中左边是单词的符号,右边为其右边为其种别码种别码,其中常数和标识符有点特别,其中常数和标识符有点特别,因为是无穷集合,因此常数用自身来表示,种别码为因为是无穷集合,因此常数用自身来表示,种别码为 9999,标识符用标识符符号表的,标识符用标识符符号表的指针表示(当然也可用自身显示,比较容易观察)指针表示(当然也可用自身显示,比较容易观察),种别码,种别码 100100。根据上述约定,一。根据上述约定,一旦见到了种别码旦见到了种别码 syn=63,syn=63,就唯一确定了就唯一确定了 这个单词。这个单词。下面是一些变量的约定:下面是一些变量的约定:,?,:,!,?,:,!;static charstatic char IDentifierTblIDentifierTbl100050=;100050=;.+33,39,39=,40=,40左移左移,59,59右移右移,*/*/*/*/*/,?,:,!,?,:,!;static char IDentifierTbl100050=;|ch=?|ch=:)static char IDentifierTbl100050=;|ch=?|ch=:)=pProject+;pProject+;if(resourceProjectpProject=)if(resourceProjectpProject=)elseelse pProject+;pProject+;return;return;pProject-;pProject-;syn=41;syn=41;syn=42;syn=42;else if(resourceProjectpProject=!)else if(resourceProjectpProject=!)/!,!=/!,!=pProject+;pProject+;if(resourceProjectpProject=)if(resourceProjectpProject=)elseelse syn=43;syn=43;syn=68;syn=68;pProject-;pProject-;pProject+;pProject+;return;return;else if(resourceProjectpProject=&)else if(resourceProjectpProject=&)/&,&/&,&else if(resourceProjectpProject=|)else if(resourceProjectpProject=|)pProject+;pProject+;if(resourceProjectpProject=&)if(resourceProjectpProject=&)elseelse pProject+;pProject+;return;return;pProject-;pProject-;syn=52;syn=52;syn=53;syn=53;/|,|/|,|else if(resourceProjectpProject=$)else if(resourceProjectpProject=$)/结束符结束符 elseelse/不能被以上词法分析识别,则出错。不能被以上词法分析识别,则出错。printf(errorprintf(error:there is no exist%c n,ch);there is no exist%c n,ch);exit(0);exit(0);syn=0;/syn=0;/种别码为种别码为 0 0pProject+;pProject+;if(resourceProjectpProject=|)if(resourceProjectpProject=|)elseelse pProject+;pProject+;return;return;pProject-;pProject-;syn=54;syn=54;syn=55;syn=55;int main()int main()/打开一个文件,读取其中的源程序打开一个文件,读取其中的源程序char resourceProject10000;char resourceProject10000;char token20=0;char token20=0;int syn=-1,i;/int syn=-1,i;/初始化初始化int pProject=0;/int pProject=0;/源程序指针源程序指针FILE*fp,*fp1;FILE*fp,*fp1;if(fp=fopen(D:,r)=NULL)if(fp=fopen(D:,r)=NULL)/打开源程序打开源程序 resourceProjectpProject=fgetc(fp);resourceProjectpProject=fgetc(fp);while(resourceProjectpProject!=$)while(resourceProjectpProject!=$)/将源程序读入将源程序读入 resourceProjectresourceProject数组数组 resourceProject+pProject=0;resourceProject+pProject=0;pProject+;pProject+;resourceProjectpProject=fgetc(fp);resourceProjectpProject=fgetc(fp);cout cant open this file;cout cant open this file;exit(0);exit(0);fclose(fp);fclose(fp);cout endl cout endl 源程序为源程序为:endl;:endl;cout resourceProject endl;cout resourceProject endl;/对源程序进行过滤对源程序进行过滤filterResource(resourceProject,pProject);filterResource(resourceProject,pProject);cout endl cout endl 过滤之后的程序过滤之后的程序:endl;:endl;cout resourceProject endl;cout resourceProject endl;pProject=0;/pProject=0;/从头开始读从头开始读if(fp1=fopen(D:,w+)=NULL)if(fp1=fopen(D:,w+)=NULL)/打开源程序打开源程序 while(syn!=0)while(syn!=0)/启动扫描启动扫描Scanner(syn,resourceProject,token,pProject);Scanner(syn,resourceProject,token,pProject);if(syn=100)if(syn=100)/标识符标识符for(i=0;i1000;i+)for(i=0;i1000;i+)/插入标识符表中插入标识符表中if(strcmp(IDentifierTbli,token)=0)if(strcmp(IDentifierTbli,token)=0)cout cant open this file;cout=1&syn=1&syn=33&syn=33&syn=68)printf(%s ,-)n,operatorOrDelimitersyn-33);printf(%s ,-)n,operatorOrDelimitersyn-33);fprintf(fp1,(%s ,-)n,operatorOrDelimitersyn-33);fprintf(fp1,(%s ,-)n,operatorOrDelimitersyn-33);for(i=0;i100;i+)for(i=0;i100;i+)/插入标识符表中插入标识符表中 fclose(fp1);fclose(fp1);return 0;return 0;printf(printf(第第%d%d 个标识符:个标识符:%sn,i+1,IDentifierTbli);%sn,i+1,IDentifierTbli);fprintf(fp1,fprintf(fp1,第第%d%d 个标识符:个标识符:%sn,i+1,IDentifierTbli);%sn,i+1,IDentifierTbli);