




已阅读5页,还剩25页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目 录1 课程设计的目的和要求21.1 课程设计的目的21.2 课程设计的要求22 系统描述22.1 自底向上分析方法的描述:22.2 算符优先文法的描述:23)输入符号串,进行移进-规约分析。33 概要设计33.1 设计思路33.2 系统功能结构43.3 技术路线或实现方法53.4 开发环境54 详细设计54.1 模块划分54.2主要算法的流程图74.3 数据分析与定义84.4 系统界面设计85 测试方法和测试结果95.1 测试用例195.2 测试用例2105.3测试用例3115.4 测试用例4126 结论和展望13结论13展望13学习编译技术课程的体会和对本门课程的评价137 参考文献138 源代码141 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。1.2 课程设计的要求1、文法使用产生式来定义;2、用大写字母和小写字母分别表示非终结符和终结符;产生式使用-;3、文法中的空字符串统一使用表示;4、分别给出每一个非终结符的firstvt集和lastvt集;5、画出算符优先关系表6、判定给定的文法是否是算符优先文法;7、给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。2 系统描述本次实验使用windows vista操作系统下visual c+6.0平台,使用c语言,利用读文件方式将待分析的文法读入到程序中,通过定义数组和结构体作为具有一定意义或关系的表或栈,存放firstvt、lastvt、算符优先关系表的元素。系统能够对由文件读入的文法进行分析,构造出firstvt表和lastvt表以及算符优先关系表。可以根据构造的优先关系表对输入的任意符号串进行分析,判断是否为本文法的句子,若是则打印规约过程。结果显示到dos界面上。2.1 自底向上分析方法的描述:对输入的符号串自左向右进行扫描,并将输入符逐个移入栈中,边移入边分析,一旦栈顶符号串形成某个句型的句柄时(该句柄对应某个产生式的右部),就用该产生式的左部非终结符代替相应右部的文法符号串,这一过程称为规约。重复这一过程,直到栈中只剩下文法的开始符则分析成功。2.2 算符优先文法的描述:只规定算符之间的优先关系,也就是说只考虑终结符之间的优先关系。由于算富有先分析不考虑非终结符之间的优先关系,在规约过程中只要找到最左素短语就可以规约。如给定一个文法gs:s-#e#e-e+te-tt-t*ft-ff-p/ff-pp-(e)p-i利用算符优先文法分析过程处理如下:1)计算给定文法中任意两个终结符对(a,b)之间的优先关系,首先计算两个集合firstvt(b)=b|b-b或b-cblastvt(b)=a|b-a或b-ac表2-1firstvt集和lastvt集 setfpfirstvt#+*/i(*/i(/i(i(lastvt#+*/i)*/i)/i)i)2)计算三种优先关系,求出算符优先关系表:表2-2算符优先关系表+*/i()#+*/i()#3)输入符号串,进行移进-规约分析。3 概要设计3.1 设计思路1)首先在源程序相同的目录下创建一个txt文档,并在文档中输入待分析的文法。然后定义一个输入流文件,调用这个流文件中的open函数打开该txt文件,再定义一个二维数组通过循环接收读入的产生式。2)接着开始构造firstvt、lastvt、算符优先关系表。在构造表的时候首先定义了两个重要的结构体。一个结构体作为存放具有一定关系的一对非终结符和终结符,另一个结构体作为存放上述元素的栈,包括栈顶指针、栈底指针、栈的长度。既然定义了栈,就存在对栈的初始化、栈是否为空的判断、入栈、出栈操作,利用循环和指针的操作来定义这些函数,以完成元素的进栈和弹出。定义了这两个结构体,就可以用来构造firstvt、lastvt、算符优先关系表。在构造firstvt表时,通过循环找出每条产生式中的非终结符的firstvt集,并把该非终结符和终结符压栈,设置标志位,标志一对非终结符和终结符具有对应关系。lastvt表的构造则是将求firstvt的过程翻转过来,可以仅仅将函数中的参数稍作修改就能够完成。3)构造算符优先关系表。算符优先关系表是一个二维数组,用来存放任意两个终结符之间的优先关系。首先构造表头,通过扫描所有产生式将终结符不重复的存放在一个一维数组中并置为优先关系表的行和列,并将优先关系表其他内容全部初始化为空。接着遍历所有产生式,找出任意两个终结符之间存在的关系(可以没有关系),并判断任意两终结符是否至多存在一种优先关系,如发现优先关系表不为空,则证明该文法不是算符优先文法,否则,将相应的关系填入到相应的行列对应的单元中。4)输入串分析过程的设计。首先将大于、小于、等于和无关系分别定义成一种类型的数据表示,通过查询符号栈栈顶以及当前符号之间的优先关系来判断移进和规约的操作。3.2 系统功能结构图3-1 系统功能结构图函数功能:main()函数:调用主函数,运行程序;firstvt()函数:构造firstvt表;lastvt()函数:构造lastvt表;oppriotable()函数:构造算符优先关系表;inputanalyse()函数:分析输入串是否为文法中的句子,并给出规约过程。3.3 技术路线或实现方法算符优先分析法的具体过程如下:1、首先先输入文件的路径,在readfile(char sencol)函数中,将需要分析的文法通过输入流文件打开函数open()复制到senrowcol中。2、然后利用firstvt( )构造产生式senrowcol的firstvt表。先找出形如a-a(a为第一个终结符)的产生式,把(a,a)压入operator栈中。从operator栈顶抛出项(a,a),填入first表相应位置。在找出形如b-a的产生式,把(b,a)压入operator栈中。循环直到operator栈为空,此时firstvt表构造完毕。3、然后把产生式右部翻转,调用firstvt函数求出lastvt表。4、接着调用oppriotable()构造算符优先关系表optable。先把产生式中所有终结符填入optable表第一行和第一列,然后利用产生式和firstvt表lastvt表分别找出满足=关系、关系的算符填表。若相应位已有关系,说明两个终结符之间至少有两种优先关系,该文法不是算符优先文法。5、最后调用inputanalyse()对输入串进行分析。初始化分析栈s,依次判断当前输入符a和分析栈中离栈顶最近的终结符s j 的关系,若s j a ,则往前找到第一个s j a,将s j -1到栈顶s k 规约,若s j = a ,如果s j =#,则接受,如果s j !=#,则移进。直到接受或者出错,算符优先分析结束。3.4 开发环境实验使用windows vista操作系统下的microsoft visual c+ 6.0平台,用c语言完成。4 详细设计4.1 模块划分实验分为五个模块,分别是:1、文件的导入:readfile(sen);2、firstvt、lastvt集的构造:firstvt(sen,first,sen_len,frist_len);lastvt(sen,last,sen_len,frist_len);3、 算符优先关系表oppriotable的构造:oppriotable(sen,first,last,optable,sen_len,first_len,&optable_len);4、算符优先分析过程的实现:inputanalyse(optablecol,stringcol,optable_len);5、主函数:main()。4.2 主要算法的流程图图4-1 算符优先分析法程序流程图4.3 数据分析与定义1、文法(产生式):文法使用产生式来定义char senrowcol:用二维数组表示产生式;int sen_len:产生式的个数;2、firstvt集:char firstrowcol:用二维数组构造firstvt表int first_len: firstvt表的行数;3、lastvt集:char lastrowcol:用二维数组构造lastvt表;int frist_len:lastvt表的行数;4、算符优先关系表:char optablerowcol:用二维数组表示算符优先关系表;int optable_len:算符优先关系表的行数和列数;5、算符优先分析表char stringcol:用一维数组记录输入串;char ssize:用一维数组表示分析栈 ;char a:当前输入字符;6、其他数据结构:typedef structchar nonterm; /非终结符char term; /终结符stackelement;firstvt表或lastvt表中一个表项(a,a);7、typedef struct stackelement *top;stackelement *bottom;int stacksize;stack;以形如表项(a,a)为元素的栈,在构造firstvt集的过程中用到;4.4 系统界面设计本实验没有考虑界面设计,将结果直接打印输出在dos界面下。5 测试方法和测试结果5.1 测试用例1测试目的:使用算符优先分析法对一个算符文法中的句子进行分析。读入一个算符优先文法进行分析,给出文件路径d:coursesc_source_file成品算符优先文法1.txt。结果如下:图5-1 测试用例1运行截图1输入一个字符串,使得该字符串是该文法的一个句子。则输入字符串i+i*i/(i+i)#时运行结果为:图5-2 测试用例1运行截图25.2 测试用例2测试目的:使用算符优先分析法,分析一个字符串不是该文法的句子,并输出出错信息。输入一个字符串,使得该字符串不是文法的句子。图5-3 测试用例2运行截图5.3 测试用例3测试目的:读入一个文法,判断该文法不是算符优先文法。读入一个非算符优先文法进行分析,给出文件路径:d:coursesc_source_file成品非算符优先文法1.txt。运行结果如下:图5-4 测试用例3运行截图5.4 测试用例4测试目的:输入一个非算符文法,判断该文法不是算符文法。读入一个非算符文法,给出路径:d:coursesc_source_file成品非算符文法.txt。运行结果如下:图5-5 测试用例4运行截图11 课程设计报告6 结论和展望结论本次实验我们基本完成了实验题目的要求。求出了一个文法中每一个非终结符的firstvt集和lastvt集,画出算符优先关系表,并判定出给定的文法是否是算符优先文法。当给定一个符号串时,能够判定是否是文法中的句子,并能够将分析过程打印出来。通过算符优先分析方法,可以对任意一个文法进行自底向上的分析。同时,算符优先分析法也存在不足之处,由于忽略文法中的非终结符,会将本不属于文法的句子正确规约,从而引起错误。展望本次实验完成了题目的要求,准确把握了将文法通过读文件形式、手动输入分析字符串的题目要求,并在满足要求的基础上进行了创新,添加了对算符文法的判断功能。实验中,小组成员的分工与合作充分体现了软件工程的思想。需求分析理解准确,小组成员任务明确,统一函数头、参数,各自完成分内工作,整合工作快速、高效。同时,实验中还存在很多不足。调试程序中的错误占用了大部分时间,以至于没有考虑使用界面展示结果。虽然使用c+开发工具,但实质上还是在使用c编代码。在今后的实践中还需注意。学习编译技术课程的体会和对本门课程的评价在上编译课的时候,小组成员都觉得自己对算符优先文法已经掌握了,但等真正用程序去实现时,才发现有很多细节我当时没有注意到。也正以为没有注意到这些细节,导致成员们编程时会出现各种错误,大部分都是在循环时下标或者循环次数的控制上出错。在进行到一定阶段后发现犯的低级错误越来越少了,对算符优先文法也愈发的吃透了,编程水平也有了进一步的提高。编译原理如果要深入研究,那会是一门非常深奥的学问,对于现阶段只有60多学时的本科生来说,只能涉及到它一些最基本的原理,和最宏观的方法,要想微观的去研究,还需要在以后的时间里去钻研。在这次实验中,小组成员也只是用高级语言模拟了编译的一个小方法,在完成实验的过程中,小组成员对编译原理有了进一步的了解,更提高了动手编程能力,是一次经验和知识的积累。7 参考文献 1 张素琴编译原理(第2版)m. 北京:清华大学出版社,2005.6,102-121.2 陈维兴c+面向对象程序设计教程m. 北京:清华大学出版社,2004.8,258-272.8 源代码#include#include#include #define row 50#define col 50#define size 50/两个重要结构体的定义/firstvt表或lastvt表中一个表项(a,a)结构体的初始化typedef structchar nonterm; /非终结符char term; /终结符stackelement;/存放(a,a)的栈的初始化typedef struct stackelement *top;stackelement *bottom;int stacksize;stack;/初始化(a,a)栈void initstack(stack &s) s.bottom = new stackelementsize; if(!s.bottom) cout存储空间分配失败!=s.stacksize)cout栈已满,无法插入!nonterm=e.nonterm;s.top-term=e.term;s.top+;/弹出栈顶(a,a)元素stackelement pop(stack &s)stackelement e;e.nonterm = 0;e.term = 0;if(s.top=s.bottom)cout栈为空,无法进行删除操作!nonterm;e.term=s.top-term;return e;/终结符与非终结符的判断函数(布尔类型)bool terminaljud(char c)if(c=a&c=z)return false; /非终结符返回falseelse return true; /终结符返回true/判断非终结符在first表中是否已存在bool itemjud(char firstcol,int frist_len,char c)for(int i=0;ifrist_len;i+)if(firsti0=c) return true; /如果first表中已存在此非终结符,则返回true return false;/读文件函数int readfile(char sencol)char addr50;cout请输入要读文件的地址(用表示):addr;ifstream fin;fin.open(addr,ios:in);if(!fin)coutcannot open file!nseni;coutseniendl;return i;/firstvt表和lastvt表中表项(非终结符)的初始化void iteminit(char sencol,char firstcol,char lastcol,int sen_len,int &frist_len)int i;frist_len=1;first00=sen00;last00=sen00;for(i=1;isen_len;i+)if(terminaljud(seni0)=false & itemjud(first,frist_len,seni0)=false) /k是当前first和last表的长度firstfrist_len0=seni0;lastfrist_len0=seni0;frist_len+;void firstvt(char sencol,char firstcol,int sen_len,int frist_len) / frist_len 是 first 表的行数 sen_len是产生式的个数stackelement dfs,recordsize;stack operator; /创建存放(a,a)的栈initstack(operator); int i,j,r=0;for(i=0;isen_len;i+) /第一次扫描,将能直接得出的first(a,a)放进栈中for(j=3;senij!=0;j+)if(terminaljud(senij)=true) /遇到的第一个终结符压入int exist=0;dfs.nonterm=seni0;dfs.term=senij;for(int i1=0;ir;i+)if(recordi1.nonterm=seni0&recordi1.term=senij)exist=1;break;recordr.nonterm=seni0;recordr.term=senij;if(exist=0)insert(operator,dfs);/a-ab a-ac (a,a)压栈两次?recordr.nonterm=seni0;recordr.term=senij;r+;break;int locationcol; /辅助数组,用来记录first表中放入终结符的位置for(i=0;ifrist_len;i+) locationi=1;while(!ifempty(operator)int exist=0; /标志位,记录即将入栈的元素是否已经存在stackelement idelement,delement;delement=pop(operator); /弹出栈顶元素for(i=0;ifrist_len;i+)if(firsti0=delement.nonterm)int n=locationi;firstin=delement.term; /将终结符填入相应的first表中locationi+;break;for(j=0;jsen_len;j+) if(senj3=delement.nonterm) /找出能推出当前非终结符的产生式的左部 idelement.nonterm=senj0;idelement.term=delement.term;/判断将要放进栈里的元素曾经是否出现过,若没有,才压入栈for(int r0=0;r0r;r0+) /r记录record数组中的元素个数if(recordr0.nonterm=idelement.nonterm & recordr0.term=idelement.term) exist=1;break; if(exist=0)insert(operator,idelement);recordr.nonterm=idelement.nonterm;recordr.term=idelement.term;r+;/if/for/whilevoid lastvt(char sencol,char lastcol,int sen_len,int frist_len) /firstvt表与lastvt表行数一样 first_len表示last 表的行数int i,j,i1,j1;char c,recordrowcol=0;for(i=0;isen_len;i+) for(j=0;senij!=0;j+)recordij=senij;j=j-1; for(i1=3,j1=j;i1j1;i1+,j1-) /做翻转,就可以用求first的方法求lastc=recordii1;recordii1=recordij1;recordij1=c;/forfirstvt(record,last,sen_len,frist_len);/判断非终结符在term表中是否已存在bool termtablejud(char termcol,int term_len,char c) for(int i=0;iterm_len;i+)if(termi=c) return true; /如果first表中已存在此非终结符,则返回1 return false;/构造算符优先关系表bool oppriotable(char sencol,char firstcol,char lastcol,char optablecol,int sen_len,int first_len,int &optable_len) int i,j,term_len=0;int i2,i3,opr,opc;char c1,c2,c3;char termsize=0;for(i=0;isen_len;i+) /一维数组term记录关系表中存在的所有终结符for(j=3;senij!=0;j+)if(terminaljud(senij)=true) if(termtablejud(term,term_len,senij)=false) /term_len记录term表的长度 termterm_len=senij; term_len+; /得到终结符表 for(i=0;iterm_len+1;i+) /给优先关系表赋初值,都等于空for(j=0;jterm_len+1;j+)optableij= ;for(i=1;iterm_len+1;i+) /设置优先关系表的表头optablei0=termi-1; optable0i=termi-1; for(i=0;isen_len;i+) /找等于关系for(j=5;senij!=0;j+)if(terminaljud(senij-2)=true&terminaljud(senij-1)=false&terminaljud(senij)=true)c1=senij-2; c2=senij; for(opr=1;oprterm_len+1;opr+) /在optable表中找到该存入的行标oprif(optableopr0=c1)break;for(opc=1;opcterm_len+1;opc+) /在optable表中找到该存入的列标opcif(optable0opc=c2)break;if(optableopropc!= )cout不是算符优先文法!endl;return false;elseoptableopropc=;/if/for(j)for(j=4;senij!=0;j+)if(terminaljud(senij-1)=true&terminaljud(senij)=true)c1=senij-1;c2=senij;for(opr=1;oprterm_len+1;opr+) /在optable表中找到该存入的行标oprif(optableopr0=c1)break;for(opc=1;opcterm_len+1;opc+) /在optable表中找到该存入的列标j2if(optable0opc=c2)break;if(optableopropc!= )cout不是算符优先文法!endl;return false;elseoptableopropc=;/for(i)for(i=0;isen_len;i+) /找小于关系for(j=3;senij!=0;j+)if(terminaljud(senij)=true&terminaljud(senij+1)=false)c1=senij; /c1记录终结符c2=senij+1; /c2记录非终结符 for(opr=1;oprterm_len+1;opr+) /在optable表中找到该存入的行标oprif(optableopr0=c1)break;for(opc=0;opcfirst_len;opc+) /找出非终结符在first表中的列标opcif(firstopc0=c2)break;for(i2=1;firstopci2!=0;i2+)c3=firstopci2;for(i3=1;i3term_len+1;i3+)if(optable0i3=c3)if(optableopri3!= )cout不是算符优先文法!endl;return false;elseoptableopri3=;break;/if/for(j)/for(i)for(i=0;isen_len;i+) /找大于关系for(j=3;senij!=0;j+)if(terminaljud(senij)=false&senij+1!=0&terminaljud(senij+1)=true)c1=senij; /c1记录非终结符c2=senij+1; /c2记录终结符 for(opr=1;oprterm_len+1;opr+) /在optable表中找到该存入的列标j1if(optable0opr=c2)break;for(opc=0;opcfirst_len;opc+) /找出非终结符在last表中的行标j2if(lastopc0=c1)break;for(i2=1;lastopci2!=0;i2+)c3=lastopci2;for(i3=1;i3term_len+1;i3+)if(optablei30=c3)if(optablei3opr!= )cout不是算符优先文法!;break;/if/for(j)/for(i)optable_len=term_len+1;return true;/判断两算符优先关系并给出类型供构造分析表int relationshipjud(char c1,char c2,char optablecol,int optable_len)int i,j;for(i=1;ioptable_len;i+)if(optablei0=c1)break;for(j=1;joptable_len;j+)if(optable0j=c2)break;if(optableij=) return 3;else return 4;/判断输入串是不是优先文法bool priogramjud(char sencol,int sen_len)int i,j;for(i=0;isen_len;i+)for(j=4;senij!=0;j+)if(terminaljud(senij-1)=false&terminaljud(senij)=false)cout输入的不是算符文法!endl;return false;return true;/开始分析输入串void inputanalyse(char optablecol,char stringcol,int optable_len) /optable_len是optable表的长度char a,q,ssize=0; /s是分析栈 char cho1,cho2;int i,j,relation;int k=0;sk=#;cho2=y;couttttt分析过程如下:endl;cout-endl;/cout 栈t当前字符t优先关系t移进或规约endl;/cout分析过程如下:endl;cout.width(10);cout栈;cout.width(15);cout当前字符;cout.width(20);cout剩余符号串;cout.width(15);cout优先关系;cout.width(15);cout移进或规约a/cout st att;cout.setf(ios:left);cout.width(10);couts;cout.unsetf(ios:left);cout.width(15);couta;cout.width(20);coutp;cout.width(15);cou
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河北劳务分包合同
- 门业配送安装合同协议
- 非农土地清理合同协议
- 露天蔬菜种植合同协议
- 纺织机械自动化与智能控制考核试卷
- 磷肥生产设备操作规程与故障预防考考核试卷
- 肉牛饲养与生长发育监测试题考核试卷
- 碳酸饮料行业新技术应用考核试卷
- 中药材种植基础知识考核试卷
- 畜牧养殖场环境治理技术考核试卷
- 新闻记者职业资格2024年笔试考试必做题有答案
- 私人公司用人合同协议
- 江苏南京历年中考作文题与审题指导(2002-2020)
- 2025江苏省环保集团(筹)招聘92人易考易错模拟试题(共500题)试卷后附参考答案
- 湖北省武汉市2025届高三下学期四月调研考试(二模)数学试题 含解析
- 广东省2025年普通高等学校招生全国统一考试模拟测试(英语试题及答案)(广东二模)
- 浙江省绍兴市2025年高考二模数学试题(含答案)
- DeepSeek1小时快速入门教程学习
- 第7单元 第1课 《自动行驶保出行》 课件【湘科2024版】信息科技 六年级下册
- 脑卒中多学科会诊制度
- 企业资产管理(EAM)系统实施作业指导书
评论
0/150
提交评论