[计算机软件及应用]编译原理实验报告词法分析.doc

上传人:rrsccc 文档编号:11040055 上传时间:2021-06-20 格式:DOC 页数:31 大小:379.50KB
返回 下载 相关 举报
[计算机软件及应用]编译原理实验报告词法分析.doc_第1页
第1页 / 共31页
[计算机软件及应用]编译原理实验报告词法分析.doc_第2页
第2页 / 共31页
[计算机软件及应用]编译原理实验报告词法分析.doc_第3页
第3页 / 共31页
[计算机软件及应用]编译原理实验报告词法分析.doc_第4页
第4页 / 共31页
[计算机软件及应用]编译原理实验报告词法分析.doc_第5页
第5页 / 共31页
点击查看更多>>
资源描述

《[计算机软件及应用]编译原理实验报告词法分析.doc》由会员分享,可在线阅读,更多相关《[计算机软件及应用]编译原理实验报告词法分析.doc(31页珍藏版)》请在三一文库上搜索。

1、编译原理实验报告词法分析器学院:计算机科学与技术时间:2012/6/9一、 问题描述选择计算机高级程序语言之一 C语言,运用恰当的词法分析技术线路,设计和实现其对应的词法分析器提示:技术线路选择如下两种之一:正则式NFADFAmin DFA程序设计或 正则文法NFADFAmin DFA程序设计。要求:分析器输出结果存入到磁盘文件中,具有出错处理功能。二、 系统分析编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。词法分析阶段是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或

2、符号)。词法分析程序实现这个任务。从左到右逐个字符对构成源程序的字符串进行扫描,依据词法规则,识别出一个一个的标记(token),把源程序变为等价的标记串序列。执行词法分析的程序称为词法分析器,也称为扫描器。本次实验,我选择用C+来实现这个词法分析器。程序语言的单词符号一般分为以下六种:关键字、标识符、常量、运算符、界符、字符串词法分析程序所输出的单词符号常常采用以下二元式表示:(单词 种别,单词自身的值),单词的种别是语法分析所需要的信息,而单 词自身的值是编译其他阶段需要的信息。 单词的种别可以用整数编码表示,比如标识符编码为 1,程序最 后输出的形式应为: 关键字 int (2 , in

3、t ) 标识符 t_val (1 , t_val) 常量 3.14e+2 (3 , 3.14e+2)其中,本次实验设计的如下:(1)关键字有34个:分别包括char,int,short,long,signed,unsigned,float,double,const,void,volatile,enum,struct,union,typedef,auto,extern,static,register,if,else,switch,case,default,while,do,for,break,continue,goto,return,sizeof,#include,#define前面32个是标准

4、C的关键字,后两个是预编译的关键字。(2)常量分为:小数,整数,浮点数,字符。本次实验中,设计了小数,整数和浮点数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就是a表示的并不是对应的数值。(3)运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设计进去了。其中包括 +,+,+=, -,-=,-,-, *,*=, /,/=, , , = ,=,=,=,66union14=68auto1672if20=73else2174switch2285#include33+=86#define34-=87ID标识符40*=88NUM常量50/=89=51%=90+5

5、2=91-53%92?95“9394采用的技术路线是正则式NFADFAmin DFA程序设计三、 系统设计l=az,AZ;d=09;1. 关键字:关键字是最好识别的,他都是由字母组成,在程序中,只要写一个小程序将设计的34个关键字保存在一个string类型的vector中,然后做一次循环,将字符串逐个与34个关键字对比,相同则取出对应的种别编码,存入事先设计好的vector中。本次设计中关键字有34个:分别包括char,int,short,long,signed,unsigned,float,double,const,void,volatile,enum,struct,union,typede

6、f,auto,extern,static,register,if,else,switch,case,default,while,do,for,break,continue,goto,return,sizeof,#include,#define前面32个是标准C的关键字,后两个是预编译的关键字。2. 标识符:标识符的正规式为:(l|_)(l|d|_)*对应的NFA为:l|_21l|d|_实际应用到程序上的DFA为:12l|_3l|d|_非l|d|_其中,状态3中代表标识符。事实上,关键字是特殊的标识符,所以首先先将他们归为一类,之后再写程序将其区别,在这里就不画出图了。3. 常量分为:小数,整数

7、,浮点数,字符。本次实验中,设计了小数,整数和浮点数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就是a表示的并不是对应的数值,而是将作为符号记录,而将字母a当作了一个标识符,所以程序写的不是很到位,还有很多小细节上没有很好的处理。而小数,整数,浮点数这三类我又将他归并后分为了无符号数和有符号数两类。在这里先给出无符号数的正规式和DFA。至于有符号数,除了开始有符号外,之后的判断与无符号数是一致的,所以在这里不在重复的给出,到了+号和号的时候再给出对应的判断。无符号数正规式:d(d)*|(d(d)*|)(.d(d)*( |e(+|-|)d(d)*)|e(|+|-)d(d

8、)*)下面给出无符号数的DFA:14d5非l|d|_|.|e6l|_.7l|_|.d8dl|_|.10非l|d|_|.|e9e1211d+|-d6+|-|l|_|.|e+|-|l|_|.|ed13非+|-|l|_|.|e14151716dd+|-l|_|e|.el|_|e|.|+|-非+|-|l|_|.|e|dl|_|e|.|+|-dd解释一下上面图的终结状态:状态5:表示整数,如123,78等状态6:表示错误,包括以数字开头字母结尾的错误标识符,有多个小数点的数字,有多个E或e的数字等,这些都是词法错误。状态10:表示小数,如12.34,7.1等状态13:表示带有指数前面是小数的数,比如1.

9、2e+12,2.34e14等状态16:表示带有指数前面是整数的数,如:2e+12,4e11等上述图中还省略了以小数点或字母e开头的DFA,但是这和上面所画的大同小异,所以在这里就不在重复的给出。画图确实比较麻烦。至于有符号数,和上面的图实际上相差的也不多,就是在1号状态之前多了一个加号和减号的判断,这里也不再画出。4. 运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设计进去了。其中包括 +,+,+=, -,-=,-,-, *,*=, /,/=, , = ,=,=,=,141615=17*非=1918=20/非=2221=23!非=2524=26=非=2827=29非=313

10、0=3332=非=3435非=|38=非=4041非=|4342=44%非=4645=47&48非=|&504951|52非=|=53“”54”55,”56”57”58”59”60(”61)”上面设计了各种运算符和界符的处理,这里再介绍一下两种不同注释。1/2/*8非/|*354非nn非 *6非*|/*7/5. 字符串:在本次实验设计中,并没有将字符串的设计设计出来,所以就不能对字符串进行识别,所以没有这个功能,只能对符号”进行判断。至此,整个实验的基本设计已经完成,由于这些图画的都很麻烦,在这里就不在综合的画一次。前面的表述应该是比较清楚的了。所有的细节都要通过编程来实现了。四、 系统实现1

11、.程序设计与具体实现:本次实验,我是用的C+语言写的,运用到了C+中自带的也是常用的一些类,如STRING,VECTOR,FSTREAM等。利用C+的好处是,数据结构的定义直接用VECTOR就行了,操作起来很方便,而利用STRING的功能,也使程序中字符串的操作也可以简化一些。下面是词法分析主程序的流程图:开始输入原文件的路径、名称打开文件成功?将文件中的数据流读入string类型的cstr中保存循环除去空格,换行,保存标识符、单个运算符、终结符到vector中结束调用扫描分析子程序scan,将分析结果存入vector中调用输出函数,将文件写入指定的文件中NY是否有错误?YN下面给出简化了的扫

12、描分析子程序的流程图:开始i=0ivector.size()YVectori是否为单个字符?字母数字运算符分界符对应的处理过程标识符常量对应的处理过程错误报错结束2.实验运行截图:1)成功运行截图:从上面的截图中可以看出本次实验的基本任务是完成了。能够成功的完成词法的分类与辨认。其中,包括关键字(如int,void),标识符(如fa,a),各种常量(如 -10,1.2e+12),还有各类的终结符,还有就是两种注释都能成功的屏蔽,没有影响到正确的词法分析。这里给出源文件及词法分析后的文件。C语言源文件:#includevoid main()int a10;int i=-10; /abcint y

13、=1.2e+12;/* a+b=c */void fa();char cha11;x+=y;a-y=c;while(i)i=i-1;xyz+;printf(abcdefg);词法分析后的文件:67 , 2.)这里再给出出现错误时的截图。本次程序设计,错误又分为两类,一种是出现了不该有的字符(如与$),还有一类就是错误的标识符或是错误的常量。3.源代码此处将源代码放到最后再给出,以便于后续的阅读。五、 系统评价从前面的报告中,可以看出,本次实验的任务(完成一个词法分析器)是基本完成了。主要实现了以下的功能:1) 对C语言源程序,运用恰当的词法分析路线,将源程序通过分析器的分析将结果输出存入磁盘文

14、件中; 程序最 后输出的形式应为: 关键字 int (2 , “ int” ) 标识符 t_val (1 , “t_val”) 常量 3.14e+2 (3 , “3.14e+2”)2) 具有一定出错处理功能虽然完成了这个实验的基本任务,但是从前面的分析中,也可以知道,本次实验在设计的过程中就是很粗糙的,期间忽略了很多问题,下面将问题都一一列出:(1)设计程序时,关键字设计了34个:其中前面32个是标准C的关键字,后两个是预编译的关键字(这两个并不是标准的关键字)。其实标准的关键字还不止这么几个,这里就没有列出一些少见的关键字,这也不是很重要,写不写的意义都不是很大,所以就这样略过了。(2)常量

15、分为:小数,整数,浮点数,字符。本次实验中,设计了小数,整数和浮点数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就是a表示的并不是对应的数值。在这里,我在设计的时候就是按无符号数和有符号数来区别的。首先设计的是无符号数,在上面的设计过程中,可以看到这是一个比较复杂的过程,在这种设计下,基本上所有的无符号数我都能识别并分类,但是,设计之前我并没有考虑到这些数的后面可以跟上一些U,L,UL等标识。当我考虑到时,我觉得更改设计会增加很多麻烦,所以直接就忽略了这种情况。对于点开头的数字以及e开头的数字我都是有设计的,但是在编写程序的时候就实现了前面一种,以至于以e开头的常量,

16、在我的词法分析程序中,并不能识别。而有符号数事实上就是在无符号数上增加一个+或-,有了前面设计的基础,这个设计就很好实现了,在本次实验中还是实现了。剩下的就还有字符常量了。字符常量考虑的东西是很多的,比如a,表示的是一个常量,又如0表示的也是常量,这种常量的多样性导致了设计困难。在此本次实验中,并不能实现相应的功能。(3)运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设计进去了。其中包括 +,+,+=, -,-=,-,-, *,*=, /,/=, , , = ,=,=,=,=,!=,&,&,&=,|,|,|=,%,%=, ,;但是还是有个别的运算符没有设计进去,比如?:,这

17、是个三目的运算符,设计起来估计很麻烦,所以就没设计,还有就是强制类型转换(类型),取地址&,指针*,指针的.运算都没有很好的设计思考,都是直接忽略了。而关于界符,由于没有深入的思考,直接就将下列符号当作一个界符,并没有去考虑他是否还有其余的作用,显得很是粗糙。以下九个符号,都是当作一般符号处理:” , : , , , , , , ? , 。没有具体的去考虑单个字符如 a表示的实际上是一个数,”0123asd”表示的是字符串(虽然没错,但是自己写的程序却会报错,因为将0123asd当成了一个错误的数字),n表示的是换行符等等,都没有考虑,所以程序的功能很是简陋。虽然设计的很简陋,但是除了一般的功

18、能外,还是增加了一些功能的。对于C语言中的两种注释,自己还是花了点功夫的。行注释/与段注释/* */都能识别出来,并将注释的内容屏蔽,而不保存到输出文件中去。这也是唯一一个不是亮点的亮点了。(4)字符串:实验中并没有考虑字符串的读写,直接将他设计成了标识符(5)标识符:除了上述说的,还有就是一些不该出现的符号,比如#$等,剩下的基本上都是标识符了。本次实验,在很大程度上,提高了自己对编译程序的理解。关于c+程序的设计,大多都是使用了相关类的自带函数功能。关于设计的思想,都是个人思考的观点。大致方向上不会出问题的,至于细节,自己也不知道是对是错。虽然程序写的漏洞百出,但是,值得高兴的是大致完成了

19、程序的设计。根据自己的设计思路,程序的思想还是显而易见的。但是可读性估计不是很好,可修改性也很差,代码的编程不够简洁,这些都是实力问题。还需要很多的练习来提高自己。词法分析器源代码#include #include #include #include /* 单词种别码*/#define _CHAR 1#define _INT 2#define _SHORT 3#define _LONG 4#define _SIGNED 5#define _UNSIGNED 6#define _FLOAT 7#define _DOUBLE 8#define _CONST 9#define _VOID 10#de

20、fine _VOLATILE 11#define _ENUM 12#define _STRUCT 13#define _UNION 14#define _TYPEDEF 15#define _AUTO 16#define _EXTERN 17#define _STATIC 18#define _REGISTER 19#define _IF 20#define _ELSE 21#define _SWITCH 22#define _CASE 23#define _DEFAULT 24#define _WHILE 25#define _DO 26#define _FOR 27#define _BRE

21、AK 28#define _CONTINUE 29#define _GOTO 30#define _RETURN 31#define _SIZEOF 32#define _INCLUDE 33#define _DEFINE 34/* 以上为关键字的种别码*/#define _ID 40 /标识符 #define _NUM 50 /数 #define _AS 51 /= #define _PLUS 52 /+ #define _SUB 53 /- #define _TIMES 54 / * #define _DIV 55 / / #define _LP 56 / (#define _RP 57

22、/ )#define _LB1 58 / #define _RB1 59 / #define _LB2 60 / #define _RB2 61 / #define _COM 62 / ,#define _COL 63 / :#define _SEM 64 / ;#define _POINT 65 / .#define _LG 66 / #define _LT 67 / =#define _LE 69 / #define _B 73 / =#define _C 74 / #define _D 75 / #define _O 85 / +=#define _P 86 / -=#define _Q

23、 87 / *=#define _R 88 / /=#define _S 89 / %=#define _T 90 / =#define _U 91 / %#define _V 92 / #define _W 93 / #define _X 94 / ?#define _EROOR -1 / 错误 using namespace std; int ERROR_NUM=0; /记载词法编译错误个数 bool isnum(string str) / 判断是不是合法的数字 int y; int i; int j=0; int k=0; for(i=0;istr.size();i+) if(!(str

24、i=0) k+; if(k-j)1)cout数字串str出现词法错误!1) cout数字串str出现词法错误!endl; return false; else if(stri=E|stri=e)&(stri-1=0)&(stri+1=0)|(y=i+1)=str.size() continue; else cout数字串str出现词法错误!endl; return false; return true;/*该函数用来略过空格和换行符,找到有效字符的位置 第一个参数为目标字符串,第二个参数为开始位置 返回值为连续的空格和换行后的第一个有效字符在字符串的位置*/int valuable(strin

25、g str,int i) while(true) if(stri!= &stri!=n) return i; i+; int isexp(string str,int i) if(stri=/&stri+1=/) while(stri!=n) i+; return i;int iskey(string str) /判断是不是关键字 string p34=char,int,short,long,signed,unsigned,float,double,const,void,volatile,enum,struct,union,typedef,auto,extern,static,register

26、,if,else,switch,case,default,while,do,for,break,continue,goto,return,sizeof,#include,#define;vector ppp(p,p+34);int u;for(u=0;uppp.size();u+)if(!pare(pppu)return u+1;return 0; vectorpair scan(vector vec)/本次程序的主要分析程序 vectorpair temp; int i; for(i=0;i) if(veci+1=) string jk=veci; jk.append(vec+i,0,1);

27、 pair pp(_ME,jk); temp.push_back(pp); continue; else if(veci+1=&veci+2!=) string jk=veci; jk.append(vec+i,0,1); pair pp(_A,jk); temp.push_back(pp); continue; else if(veci+1=&veci+2=) string jk=veci; jk.append(vec+i,0,1); jk.append(vec+i,0,1); pair pp(_B,jk); temp.push_back(pp); continue; else pair pp(_LG,veci);/标识符 temp.push_back(pp); else if(veci=)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1