词法分析器重点_第1页
词法分析器重点_第2页
词法分析器重点_第3页
词法分析器重点_第4页
词法分析器重点_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

1、编译原理课程实验报告题目 L语言的词法分析程序 专业 计算机科学与技术 班级 2014级 学号 姓名 张衡 石河子大学信息学院计算机系2016年10月30日一. 实验序号:编译原理词法分析实验二. 实验题目:L语言的词法分析程序三. 实验日期: 2016年10月30日 四. 实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五. 实验要求1) 词法分析程序主要识别用L语言编写的源程序中的各类单词,并以所在行号和二元式(单词类别,单词值)的形式输出2) 标识符类单词词法规则“以字母或下划线开头,后面可以跟字母、数字、下划线”;“区分大小写字母“;”长度最多为8个字符“。3) 常量

2、类单词分为数值型常量、字符型常量、字符串常量。1. 数值型常量分为整型常量和小数常量。整型常量有十进制(0-9组成)和十六进制(0-9、A-F组成)两种;小数常量分为定点小数和科学计数法两种,其中定点小数由0-9和一个小数点组成,科学记数法由0-9、小数点和E组成。2. 字符型常量由一对<>带一个字符组成。3. 字符串常量由一对“”带一个或多个字符组成。4) 运算符有算术运算符(+、-、*、/、*);关系运算符(= =、>、>=、<、<=、!=)。5) 分界符有;、,、和(、)。每条语句以;结束。6) 进行单词拼写错误检查,并输出错误信息和所在行号。六. 实

3、验步骤1) 用L语言编写测试用例源程序,用C语言编写词法分析程序。2) 运行词法分析程序,读入L语言的测试用例源程序,进行词法分析。3) 设立断点,单步运行词法分析程序,依次单个输出单词。分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。4) 根据上述“实验要求”修改或编写词法分析程序,同时也应修改L语言测试用例源程序中的相应的单词。5) 运行修改后的词法分析程序,读入修改后的L语言测试用例源程序,进行词法分析。七L语言词法分析程序的有限自动机(状态转换图表示) 状态转换图如下页所示: 转下页数字数字其他数字X非数字数字012435691307014000其他18 =

4、 非=0非=,字符 >170其他016=其他 >字符 <015字符其他字符 ”01211 “100其他字母或者 _字母或者 _其他01-9或A-F80e数字其他数字. =其他=192332522224002862100其他非=0=!非!其他*0其他非*027其他0其他,030其他/032其他;034其他(36其他)038八.实验结果(测试用例源程序,运行结果截图) 1、测试用例程序begin"string" if(num1>num2) studn&t=num2=16; texttttt4=0XA& if(num1=num2) peak

5、1=a+b*c/d; peak2*; grade<grade2; for(i=1;i<=2;) name1>=name2; grade1!=grade2; sdkfajslw; text1=9;text2=32.25;text3= 3.34125e3; text4=0XA6; BEGIN <a>,"stringfgdf"<> end end;2、运行结果:2.1 初始页面2.2读入字符串2.3 词法分析结果(包括错误检查)九实验体会(词法分析程序修改的地方,解决问题的方法、心得体会等) 本次词法分析器课程设计,写了两个周,终于完成了

6、,写完了之后看着自己做的词法分析器心里还是有一点小小的满足感。毕竟是写完了,感觉不到有啥困难,但回想一下整个词法分析器的设计过程,其实问题接踵而至,搞得我焦头烂额,尤其是一个小的功能写错了之后,反复的查找错误,调试程序,周六周日晚上为了解决掉它加班到晚上三四点,最后发现三个小时左右也就顺利完成了三种类型左右的单词识别,我想这就是以后一个作为程序员该有的工作责任吧-加班加点! 在第一节实验课老师给我们下发词法分析器的课程设计任务时,老师给我们讲解了好多次才听懂实验到底是干嘛的,顿时感觉好难,该怎么写,一节课在思考词法分析器如何设计,于是很纠结。于是晚上回到宿舍,我把课本第四章仔细的看了两遍,感觉

7、有点头绪,整个的目标与方向有大概的了解,但是具体的数据结构还不是很清晰,这是遇到的第一个问题,于是我在想,要不直接把字符串到数组里,然后对数组进行挨个处理,方便简单,于是我就确定了大致的数据结构。后来就是处理空格和回车的问题,因为读到数组里面字符串包含空格和回车,于是我设置全局变量指针来定位数组,同时每判断一个字符就做是否为空处理,如果为空,全局变量加一后移,回车我当做一个字符处理,每碰到一个回车,全局变量加一后移,进行下一个分析。接下来我又碰到一个问题,就是如何保存识别出来的单词?我想了一下,结果是通过临时数组来存储结果,每识别一个单词就将单词的输出,临时数组在接着进行使用,可是,问题来了,

8、需要识别类别号呀,需要和识别出来的单词匹配出来呀?想了一下,这点好解决,提前设置类型号和单词的匹配,通过设置全局变量类型号来对应匹配,这样,每识别一个就输出一个,问题就解决了。 通过前期的一系列的工作,词法分析器写的还算顺利进行,关系运算符和算术运算符、标点符号、字符型常量、字符串常量顺利的写完了。这时候我就在写关键字和标示符的识别,我在想是要分开识别还是统一识别,最后我决定还是统一识别城标示符,然后设置一个关键字字符串数组对应匹配,若匹配成功,则是关键字,否则,就是标示符。于是问题就解决了。后来我感觉难一点的地方,就是各种类型数的识别,这可花了我好长的时间,每一个类型单个识别倒是简单,看着自

9、动机画的图,所以还是咬着牙用一个程序段搞定,一个大致简要的方向就是:先是预判断是否是十进制,然后如果存在点,就是小数,在判断是否存在e,存在就是科学计数法。十六进制写起来容易一点。眼看自己的程序就快搞定了,心理还是挺激动,但是问题还没有结束,数制要换成二进制,这有花费了好几个小时仔细思考,字符转数字,数字转二进制,又查找了几个简便的函数一点一点的解决了。 最后,到了程序的最后一部分,就是识别行号和错误类型,我想老师请教了好几次,通过老师的讲解,我有了大致的方向。行号问题我通过设置变量来标示,在扫描字符串时,每识别一个回车,变量加一,这样问题就解决了。最难的部分我感觉是识别错误,尤其是关键字拼写

10、错误,我想了好久不过还算是顺利解决了,重点就是关键字拼写错误,主要是大小写拼写错误,我通过识别出来的字符串,如果字符串与关键字数组匹配出现相同,就没有拼写错误,如果没有匹配相同,通过发字符串全部转换为小写,然后再次匹配,如果匹配了,就说明错在拼写错误。标示符字数超限问题,通过判断临时数组的长度就解决了。标示符中存在非法字符问题,如果是在标示符中出现的非法字符,现存起来,把它的类型设置为错误类型,这样就解决了。每一种错误设置一种对应的错误类型,这样问题就解决了。通过两个星期的词法分析设计,不仅仅是完成了任务,而且编程能力到提高,解决问题的能力得到了加强,所以以后还要再接再厉,提升自己。附录:#i

11、nclude<cstdio>#include<cstring>#include <fstream>#include<stdlib.h>#include<iostream>#include<cmath>using namespace std;char prog800,bring20;char ch;int hanghao=1;int Lei_Xing,p,m=0,n,sum=0;char *keyword8="begin","if","for","read

12、","do","end","next","write"void kexuejishufa_er() char abc10000; char abc110000; int i=0; int j=0; int k=0; for(j=0;bringj!='e'j+) abci+=bringj; for(j=j+1;j<m-1;j+) abc1k=bringj; k+; abci='0' abc1k='0' double small=atof(abc);/转换

13、成double型小数 double small2=atof(abc1); for(int jj=1;jj<=small2;jj+) small=small*10; cout<<" 十进制数:"<<small<<" " char zhengshubufen10000;/整数 double a; long value; value=(long)small; a=small-value; itoa(value, zhengshubufen, 2); / 将value 转为存成进制之字串 cout<<zhen

14、gshubufen; if(a>0.0) cout<<'.' while(a>0.0) a=a*2; cout<<(long)a; if(a>0.0) a=a-long(a); void xiaoshu_er() double small=atof(bring);/转换成double型小数 char zhengshubufen10000;/整数 double a; long value; value=(long)small; a=small-value; itoa(value, zhengshubufen, 2); / 将value 转

15、为存成进制之字串 cout<<zhengshubufen<<'.' while(a>0.0) a=a*2; cout<<(long)a; if(a>0.0) a=a-long(a); void shi_er(int x)/十进制转换为二进制 char a100000; itoa(x,a,2); printf("%s",a); void shiliu_er() for(int i=2;bringi!='0'i+) if(bringi='0') cout<<"0

16、000" else if(bringi='1') cout<<"0001" else if(bringi='2') cout<<"0010" else if(bringi='3') cout<<"0011" else if(bringi='4') cout<<"0100" else if(bringi='5') cout<<"0101" else

17、if(bringi='6') cout<<"0110" else if(bringi='7') cout<<"0111" else if(bringi='8') cout<<"1000" else if(bringi='9') cout<<"1001" else if(bringi='A') cout<<"1010" else if(bringi='

18、B') cout<<"1011" else if(bringi='C') cout<<"1100" else if(bringi='D') cout<<"1101" else if(bringi='E') cout<<"1110" else cout<<"1111" void Sao_Miao() for(n=0;n<9;n+) bringn=NULL; ch=progp;

19、p+; while(ch=' ') ch=progp; p+; if(ch='n') hanghao+; if(ch>='a'&&ch<='z')|(ch>='A'&&ch<='Z')|ch='_') /可能是标示符或者变量名 m=0; int flag3=0; while(ch>='0'&&ch<='9')|(ch>='a'&&c

20、h<='z')|(ch>='A'&&ch<='Z')|ch='_'|ch=''|ch='$'|ch=''|ch='&'|ch=''|ch='?') bringm=ch; m+; ch=progp; p+; if(ch=''|ch='$'|ch=''|ch='&'|ch=''|ch='?') f

21、lag3=1; bringm='0' p-; Lei_Xing=6002; if(flag3=1) Lei_Xing=3333;/非法字符 char temp20; for(n=0;n<8;n+) /将识别出来的字符和已定义的标示符作比较, if(strcmp(bring,keywordn)=0) Lei_Xing=6001; break; for(int i=0;i<=m;i+) if(bringi>='A'&&bringi<='Z') tempi=bringi+32; else tempi=bringi

22、; if(strcmp(temp,keywordn)=0) Lei_Xing=1111;/大小写拼写错误 break; int xx=m; if(xx>8)/判断是否超出8位字符 Lei_Xing=4444; else if(ch>='0'&&ch<='9') /数字,十六进制只能以数字开头, if(ch='0') m=0; bringm+=ch; ch=progp+; if(ch='X') /数字,识别十六进制 bringm+=ch; ch=progp+; while(ch>='0

23、'&&ch<='9')|(ch>='A'&&ch<='F') bringm+=ch; ch=progp+; bringm+='0' p-; Lei_Xing=1002; else int flag=0; m=0; while(ch>='0'&&ch<='9')|ch='.'|ch>='A'&&ch<='F'|ch='e')

24、bringm+=ch; ch=progp+; if(ch='.') flag=1; if(flag=1&&ch='e') flag=2; p-; bringm+='0' if(flag=1) Lei_Xing=1003;/小数 else if(flag=0) sum=0; int x=0; while(bringx!='0') sum=sum*10+bringx-'0' x+; Lei_Xing=1001;/整数 if(sum>32767) Lei_Xing=-1; else Lei_Xing

25、=1004;/科学技术法 else int flag=0; m=0; while(ch>='0'&&ch<='9')|ch='.'|ch>='A'&&ch<='F'|ch='e') bringm+=ch; ch=progp+; if(ch='.') flag=1; if(flag=1&&ch='e') flag=2; p-; bringm+='0' if(flag=1) Lei_X

26、ing=1003;/小数 else if(flag=0) sum=0; int x=0; while(bringx!='0') sum=sum*10+bringx-'0' x+; Lei_Xing=1001;/整数 else Lei_Xing=1004;/科学技术法 else switch(ch) /其他字符 case'"':m=0;bringm+=ch;/字符串不包括空格和“”号; ch=progp+; while(ch>='a'&&ch<='z')|(ch>='

27、;A'&&ch<='Z')|ch='"') if(ch='"') Lei_Xing=2002; bringm+=ch; break; else bringm+=ch; ch=progp+; break; case'<':m=0;bringm+=ch; ch=progp+; if(ch='>') Lei_Xing=6666; bringm+=ch; else if(ch='=') Lei_Xing=4005; bringm+=ch; els

28、e if(ch!='0'&&progp='>') Lei_Xing=2001; bringm+=ch; bringm+=progp; p+; else Lei_Xing=4004; p-; break; case'>':m=0;bringm+=ch; ch=progp+; if(ch='=') Lei_Xing=4003; bringm+=ch; else Lei_Xing=20; p-; break; case'!':m=0;bringm+=ch; ch=progp+; if(ch=&

29、#39;=') Lei_Xing=4006; bringm+=ch; else Lei_Xing=4007; p-; break; case'*':m=0;bringm+=ch; ch=progp+; if(ch='*') Lei_Xing=3005; bringm+=ch; else Lei_Xing=3003; p-; break; case'=':m=0;bringm+=ch; ch=progp+; if(ch='=') Lei_Xing=4001; bringm+=ch; else Lei_Xing=3006; p

30、-; break; case'+':Lei_Xing=3001;bring0=ch;break; case'-':Lei_Xing=3002;bring0=ch;break; case'/':Lei_Xing=3004;bring0=ch;break; case'':Lei_Xing=5001;bring0=ch;break; case',':Lei_Xing=5002;bring0=ch;break; case'(':Lei_Xing=5004;bring0=ch;break; case'

31、)':Lei_Xing=5005;bring0=ch;break; case'#':Lei_Xing=0;break; case'n':Lei_Xing=5555;break; default: m=0; bringm+=ch; ch=progp+; while(ch!='0'&&ch!='n'&&ch!='#'&&ch!=','&&ch!='') bringm+=ch; ch=progp+; m-; p-; L

32、ei_Xing=3333; void jie_mian() cout<<"-"<<endl; cout<<" 词法分析器 "<<endl; cout<<endl; cout<<"-"<<endl; cout<<" 单词符号输出形式 "<<endl; cout<<"-"<<endl; cout<<" 常量 关系运算符 算数运算符 其他符号 &qu

33、ot;<<endl; cout<<"-"<<endl; cout<<" 单词值 类别号 单词值 类别号 单词值 类别号 单词值 类别号 "<<endl; cout<<"-"<<endl; cout<<" 十进制整数 1001 = 4001 + 3001 关键字 6001 "<<endl; cout<<"-"<<endl; cout<<" 十六制

34、整数 1002 > 4002 - 3002 标示符 6002 "<<endl; cout<<"-"<<endl; cout<<" 定点小数 1003 >= 4003 * 3003 ; 5001 "<<endl; cout<<"-"<<endl; cout<<" 科学计数法 1004 < 4004 / 3004 , 5002 "<<endl; cout<<"-&

35、quot;<<endl; cout<<" 字符型常量 2001 <= 4005 * 3005 ( 5004 "<<endl; cout<<"-"<<endl; cout<<" 字符串常量 2002 != 4006 = 3006 ) 5005 "<<endl; cout<<"-"<<endl; cout<<" ! 4007 "<<endl; cout<&l

36、t;"-"<<endl;int main() p=0; jie_mian(); cout<<"请输入:"<<endl; FILE *fp; if(fp=fopen("ceshi.txt","r")!=NULL) while(fscanf(fp,"%c",&ch)!=EOF) progp+=ch; progp='#' else cout<<"打开文件失败!"<<endl; fclose(fp);

37、 for(int i=0;progi!='#'i+) cout<<progi; cout<<endl<<"词法分析结果如下:"<<endl<<endl; p=0; do Sao_Miao(); switch(Lei_Xing) case 1111:cout<<"错误:关键字拼写错误! ,位置行号:"<<hanghao<<endl;break; case 3333:cout<<"错误:标示符出现非法字符! ,位置行号:"<<hanghao<<endl;break; case 4444:cout<<"错误:标示符位数超出八位! ,位置行号:"<<hanghao<<endl;break; case 5555:break; case

温馨提示

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

评论

0/150

提交评论