词法分析器课程设计报告_第1页
词法分析器课程设计报告_第2页
词法分析器课程设计报告_第3页
词法分析器课程设计报告_第4页
词法分析器课程设计报告_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

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

文档简介

PAGEPAGE1目录摘要 11课程设计内容 22课程设计要求 33运行环境 44编译程序介绍 45各部分的功能介绍及分析 56算法实现及模拟 57设计思路及关键问题 67.1处理时机 67.2一个棘手问题 67.3解决方法 78结果及测试分析 78.1待分析程序源代码 78.2运行结果 109总结 119.1设计过程 119.2困难与收获 11参考文献 12

摘要通过课程设计实践,树立正确的设计思想,巩固所学编程语言基本知识,增进C语言编辑基本功;综合运用所学的理论知识,进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解;掌握课程设计的一般方法与步骤,深入掌握课程设计的基本理论、方法和步骤,提高自己的编程能力,培养好的程序设计风格。通过课程设计,真正掌握设计和构造编译程序的基本原理和常用的编译技术,具备系统软件调试能力和开发能力,培养分析问题和解决问题的能力。同时通过某种编程语言的应用,具备初步的Windows环境下的编程思想。完成本课程设计的项目——词法分析器,理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实现方法和技术,用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。关键词:词法分析器扫描器单词符号预处理1课程设计内容设计内容:完成下述文法所描述的单词符号的词法分析程序。<标识符>--><字母>|<标识符><字母>|<标识符><数字><无符号整数>--><数字>|<无符号整数><数字><分界符>-->+|-|*|/|;|(|)|{|}|<|<=|==|!=|>=|>|=|<空格><字母>-->a|…|z|A|…|Z<数字>-->0|…|9运用C语言设计词法分析器,由指定文件读入预分析的源程序,经过词法分析器的分析,将结果写入指定文件。本程序是在VisualStudio环境下,使用C语言作为开发工具。基于实验任务的内容及目的,实现初步的需求分析,具备词法分析器的基本功能和整体构架。逐步细化其功能,做到相应模块的具体化。画出未成熟的流程图,确定整体设计的走向,在一定范围内约束编程活动,确保没有大的问题及缺陷存在,然后通过将来的具体的编程设计完善流程图。程序设计的具体内容:在实际的设计中,预分析程序保存在文本文件sourcecode.txt中,该文件不能由执行程序自动创建,需要在程序执行前预先提供,程序拥有只读的权限。程序逐个字符的分析源程序,能够识别标识符,整数,分界符,并分别把分析得到的字符写入相应文档:keyword,words,digit,single,double;其它字符标示为无法识别,记录在error文档中。程序结束后,将最总结果写入文件Dualistic_formula,该文件的内容包括统计结果(排除重复出现的字符)和二元式。这七个文件会在程序执行时自动创建,程序结束时,关闭文件,但保留文件的内容,以供查看和检验,测试。不同类别的字符通过相应的函数模块来分析识别。普通标识符由函数intword(charch)来识别,并进一步由函数intkeyword(charkey[])来分离普通标识符和关键字;数字有函数intdigit(charch)来识别;分界符由函数intdelimiter(charch)来识别;其他字符即为非法字符。该程序中,全局变量共有两个intcharacters_exist=0和intcountoffinal=0。characters_exist用来判断是否是纯数字,countoffinal用来记录finalresult函数执行的次数。统计主函数在内,总共16个函数模块,除了前面说到得识别字符的函数外,还有对文件进行操作的函数,对数组操作的函数和实现显示功能的函数。主函数中有六个文件指针,十一个字符数组,十个实现不同功能的变量。在程序设计过程中及时注释,方便复读和检测。2课程设计要求必须运用C语言设计词法分析器,由指定文件读入预分析的源程序,从左至右描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。本程序规定输出用KeyWord代表关键字,Word代表普通标识符,Digit代表阿拉伯数字,SingleWord代表单分界符,DoubleWord代表双分界符,ERROR代表无法别的字符。了解和掌握词法分析的方法;编程实现给定源语言程序的词法分析器;利用该分析器扫描源语言程序的字符串,按照给定的词法规则,识别出单词符号作为输出,发现其中的词法错误。不同类别的字符通过相应的函数模块来分析识别。针对该程序设计的具体设计:编程实现一个简单的词法分析器,可以对一个文件进行词法分析处理。程序能够正确识别文法所规定的任何组织形式的字符组合。例如在连续的分界符中,如何分离出单分界符和双分界符;字符中间的空格如何处理,源程序中往往出现大量连续的空格,若是全部记录下来,没用实际意义,且又浪费时间和空间,这样又如何处理;普通标识符和关键字如何分离出来;数字如何判断,形如123,a123,123a,123=,=123,123#,#123的字符串中,哪些才是整数,其它的又如何舍去。这些功能都必须实现。标识符是被分界符分开的,只有在遇到分界符时才能判断前面的字符串是否是标识符;假若非法字符和字母或数字混杂在一起,则这些字母或数字不能形成标识符或整数;这个问题并不复杂,当出现连续的分界符时,棘手的问题才出现。形如!<==-a,这个分界符字符串该如何分析呢?第一个字符!是单分界符,那么是不是当读到!时就可以立即判断这是一个单分界符呢?不能,因为还有形如字符串!=的可能性,这样一来词法分析器必须拥有展望未来的能力;那么<是不能判断为单分界符的,因为,字符组合<=是双分界符;问题出现了,字符组合==是双分界符,还是单独的认为第二个=是单分界符,这就决定与规定了;既然在读到单分界时不能立即判断其具体归类,那么当读到字符–后,还需要进一步读字符a,然后才能判断字符–是否是单分界符,这样一来,就需要在遇到字母或数字时,进行对前面的分界符的判断,这时又需要退两步来分析,也就是需要分析字符a前面的两个字符才能判断字符a前面的一个字符是什么属性;这就是说,出现连续的分界符时,需要尾随的其他类的字符来辅助,以判断分界符的具体属性;可是,如果没有其他字符尾随呢,最好的一个分界符该如何处理?还有,如果标识符同样没有其他字符尾随,又该如何处理?分析得到的字符,需要写入文件,保存以供后用。重复出现的字符不能都作为最后结果存储。这些多余的字符是在分析时舍去还是在整个源程序被分析完毕后才进一步处理舍的去问题?可以把读到的所有合法字符(出去连续出现的大量空格)暂时保存到相关文件,待分析源程序完毕后,在处理这些文件中的合法字符,舍去重复的,把正确合适的数据写入到另一个文件,形成二元式,该文件才是最后结果。程序在实现基本功能的同时,以上提出的问题必须小心处理。在程序设计过程中需要及时注释。首先整体把握程序设计的架构和内涵,理清需求,得到雏形的流程图;完成程序编程,满足前述功能,实现数据的输入和正确输出。3运行环境此法分析器的设计和运行环境:MicrosoftWindowsXPProfessional/MicrosoftVisualStudio2005/VisualC++控制台应用程序。程序的不足本程序只能分析小型的源程序,否则将会出现空间分配不足;能够分析的字符串的长度有限,否则,也会出现空间问题。另外,变量反复使用,不利于阅读。反复出现“fopen”被声明为否决的这样的警告信息。程序冗长,未能充分利用C函数库的功能函数。4编译程序介绍本词法分析器,预分析程序保存在文本文件sourcecode.txt中,该文件不能由执行程序自动创建,需要在程序执行前预先提供,程序拥有只读的权限。程序逐个字符的分析源程序,能够识别标识符,整数,分界符,并分别把分析得到的字符写入相应文档:keyword,words,digit,single,double;其它字符标示为无法识别,记录在error文档中。程序结束后,将最总结果写入文件Dualistic_formula,该文件的内容包括统计结果(排除重复出现的字符)和二元式。这七个文件会在程序执行时自动创建,程序结束时,关闭文件,但保留文件的内容,以供查看和检验,测试。不同类别的字符通过相应的函数模块来分析识别。普通标识符由函数intword(charch)来识别,并进一步由函数intkeyword(charkey[])来分离普通标识符和关键字;数字有函数intdigit(charch)来识别;分界符由函数intdelimiter(charch)来识别;其他字符即为非法字符。该程序中,全局变量共有两个intcharacters_exist=0和intountoffinal=0。characters_exist用来判断是否是纯数字,countoffinal用来记录finalresult函数执行的次数。统计主函数在内,总共16个函数模块,除了前面说到得识别字符的函数外,还有对文件进行操作的函数,对数组操作的函数和实现显示功能的函数。主函数中有六个文件指针,十一个字符数组,十个实现不同功能的变量。在程序设计过程中及时注释,方便复读和检测。通过while循环和fgetc(FILE*fp)实现对字符的逐个读入。5各部分的功能介绍及分析各函数及功能说明intword(charch)/*判断是否为字母*/intdigit(charch)/*判断是否为数字*/intdelimiter(charch)/*判断是否是分界符*/intkeywordcompare(charkey[],charkeyword[])/*比较关键字*/intkeyword(charkey[])/*判断是否是关键字*/voidwritetofile(charcha[])/*将数组cha[]写入文件Dualistic_formula*/voidkeywordtofile(charcha[])/*将关键字写入文件keyword*/voidwordstofile(charcha[])/*将标识符写入文件words*/voiddigittofile(charcha[])/*将数字写入文件digit*/voidsingletofile(charcha[])/*将单分界符写入文件single*/voiddoubletofile(charcha[])/*将双分界符写入文件double*/voiderrortofile(charcha[])/*将非法字符写入文件error*/voiddisplayw(charch,charcha[])/*立即显示遇到的字符*/voidfinalresult(intdf,charfilen[],FILE*fpp,FILE*fpt)voidcleararray(intn,charcha[])/*清空数组*/6算法实现及模拟读入源文件有函数intfgetc(FILE*FILE)实现,文件是否结束及循环读入字符由while循环实现,while(!feof(fpr)),其中fpr=fopen("sourcecode.txt","r"),sourcecode.txt为存放源程序的文本文件。判断字符类别由五个函数实现:intword(charch)/*判断是否为字母*/intdigit(charch)/*判断是否为数字*/intdelimiter(charch)/*判断是否是分界符*/intkeywordcompare(charkey[],charkeyword[])/*比较关键字*/intkeyword(charkey[])/*判断是否是关键字*/存储或显示由八个函数实现:voidwritetofile(charcha[])voidkeywordtofile(charcha[])voiddigittofile(charcha[])voidsingletofile(charcha[])voiddoubletofile(charcha[])voiderrortofile(charcha[])voiddisplayw(charch,charcha[])voidfinalresult(intdf,charfilen[],FILE*fpp,FILE*fpt)7设计思路及关键问题7.1处理时机确定算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的种类,分别存储或显示。数字和标识符被分界符或非法字符分开,分界符同样被数字或标识符或非法字符分开,当非法字符与数字或标识符邻接或混杂时,数字或标识符则不能成为数字或标识符,而成为非法字符,这是非法字符的感染特性。但这个效果在遇到分界符时不起作用,既分界符遇到非法字符或者和非法字符混杂,分界符仍然为分界符。这就要求,如果要处理标识符,就必须在遇到后面的分界符时才能有所操作。7.2一个棘手问题数字同样如此。遇到数字或标识符同样需要处理前面的分界符,但并不是所有的分解都必须在遇到数字或标识符后才能处理的。例如出现连续的分界符时。当出现连续的分界符时,棘手的问题才出现。形如!<==-a,这个分界符字符串该如何分析呢?第一个字符!是单分界符,那么是不是当读到!时就可以立即判断这是一个单分界符呢?不能,因为还有形如字符串!=的可能性,这样一来词法分析器必须拥有展望未来的能力;那么<是不能判断为单分界符的,因为,字符组合<=是双分界符;问题出现了,字符组合==是双分界符,还是单独的认为第二个=是单分界符,这就决定与规定了;既然在读到单分界时不能立即判断其具体归类,那么当读到字符–后,还需要进一步读字符a,然后才能判断字符–是否是单分界符,这样一来,就需要在遇到字母或数字时,进行对前面的分界符的判断,这时又需要退两步来分析,也就是需要分析字符a前面的两个字符才能判断字符a前面的一个字符是什么属性;这就是说,出现连续的分界符时,需要尾随的其他类的字符来辅助,以判断分界符的具体属性;可是,如果没有其他字符尾随呢,最好的一个分界符该如何处理?还有,如果标识符同样没有其他字符尾随,又该如何处理?7.3解决方法可以用一个变量来标示前面是否出现双分界符。同样,用不同的变量实现不同的功能。下面是本程序的一些功能变量。charch;/*接受从文件中读出的单个字符*/intunknown=0;/*判断是否出现无法识别的字符*/intnumofword=0;/*字母数组中的字母个数*/intnumofdigit=0;/*数字数组中的数字个数*/intnumofsingle=0;/*连续出现的单分界符个数*/intcatchdoubleword=0;/*是否出现双分界符*/intenddelimit=10;/*末尾是否存在分界符*/intnumofspace=0;/*限制遇到过多的空格*/8结果及测试分析8.1待分析程序源代码#include<iostream>#include<string>usingnamespacestd;#defineMAX22charch='';stringkey[15]={"begin","end","if","then","else","while","write","read","do","call","const","char","until","procedure","repeat"};intIskey(stringc){//关键字判断inti;for(i=0;i<MAX;i++){if(key[i].compare(c)==0)return1;}return0;}intIsLetter(charc){//判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A')))return1;elsereturn0;}intIsDigit(charc){//判断是否为数字if(c>='0'&&c<='9')return1;elsereturn0;}voidanalyse(FILE*fpin){stringarr="";while((ch=fgetc(fpin))!=EOF){arr="";if(ch==''||ch=='\t'||ch=='\n'){}elseif(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)){if((ch<='Z')&&(ch>='A'))ch=ch+32;arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if(Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}elsecout<<arr<<"\t$普通标识符"<<endl;}elseif(IsDigit(ch)){while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t$无符号实数"<<endl;}elseswitch(ch){case'+':case'-':case'*':case'=':case'/':cout<<ch<<"\t$运算符"<<endl;break;case'(':case')':case'[':case']':case';':case'.':case',':case'{':case'}':cout<<ch<<"\t$界符"<<endl;break;case':':{ch=fgetc(fpin);if(ch=='=')cout<<":="<<"\t$运算符"<<endl;else{cout<<"="<<"\t$运算符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>':{ch=fgetc(fpin);if(ch=='=')cout<<">="<<"\t$运算符"<<endl;if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;else{cout<<">"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<':{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;elseif(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;elseif(ch=='>')cout<<"<>"<<"\t$运算符"<<endl;else{cout<<"<"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default:cout<<ch<<"\t$无法识别字符"<<endl;}}}voidmain(){charin_fn[30];FILE*fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL)break;elsecout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n********************分析如下*********************"<<endl;analyse(fpin);fclose(fpin);cout<<endl;cout<<"按任意键结束"<<endl;inta;cin>>a;} 8.2运行结果如图1,图2图1图2由此可见,程序运行及结果输出是完全正确的!9.总结通过课程设计,树立了正确的设计思想,巩固了所学编程语言基本知识,增进

温馨提示

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

评论

0/150

提交评论