编译原理课设—正规式r与正规文法G相互转换的程序设计_第1页
编译原理课设—正规式r与正规文法G相互转换的程序设计_第2页
编译原理课设—正规式r与正规文法G相互转换的程序设计_第3页
编译原理课设—正规式r与正规文法G相互转换的程序设计_第4页
编译原理课设—正规式r与正规文法G相互转换的程序设计_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

1、目录1、 引言12、 设计原理12.1、正规文法的定义12.2、正规式的定义22.3、正规文法和正规式的等价性22.3.1、将正规式转换成正规文法22.3.2、将正规文法转换成正规式33、 总体算法设计33.1、正规式转化为正规文法的算法33.2、正规文法转化为正规式的算法44、 详细设计54.1、算法涉及到的各个结构体54.1.1、每个文法规则右部非终结符前面的终结符串54.1.2、每个文法规则右部结构体64.1.3、每条文法规则结构体64.1.4、文法规则结合64.2、主要函数74.2.1、创建文法的一条规则74.2.2、合并规则右部相同非终结符的项84.2.3、规则的替换95、调试与运行

2、结果105.1、 调试方法记录105.2 、实验结果记录105.2.1、第一组测试数据105.2.2、第二组测试数据115.2.3、第三组测试数据126、 课程设计总结与心得体会137、参考文献13正规式r与正规文法G相互转换的程序设计摘要:在计算机编译理论中,正规式、正规文法、自动机的理论以及它们之间的 等价性问题是编译理论的等价基础,其中正规式和自动机,正规文法和自动机之间的等价性问题,已经得到了比较圆满的解决。本文主要讨论正规式和正规文法之间相互转换的方法。关键字:编译原理 正规式 正规文法 相互转换1、 引言程序设计语言中的单词是基本语法符号。单词符号的语法可以用有效的工具加以描述,并

3、且基于这类描述工具,可以建立词法分析技术,进而可以建立词法分析程序的自动构造方法。多数程序设计语言的单词的语法都能用正规文法或3型文法来描述。正规式也称正则表达式,是表示正规集的工具,也是我们用以描述单词符号的方便工具。因此,熟练掌握正规文法、正规式以及它们之间的相互转化是非常必要的。2、 设计原理2.1、正规文法的定义正规文法是左线性文法和右线性文法的统称。它们都是Chomsky分类下的3型文法。由正规文法产生的语言称为正规集。2.1.1、右线性文法设GS=(VN,VT,P,S),若P中的产生或均有如下的形式:AaB或Aa(AVN,aVT),则称G为右线性文法。例如,文法G1S=(S,A,B

4、,a,b,P1,S)其中P1=SaA,AaA,AbB,Ab,BbB,Bb,由定义可知该文法为一右线性文法。2.1.2、左线性文法若一个文法GS=(VN,VT,P,S)中的产生式均有如下的形式:ABa或Aa(A,BVN,aVT),则称G为左线性文法。例如,文法G2S=(S,A,a,b,P2,S)其中P2=SSb,SAb,AAa,Aa,由定义可知该文法为一左线性文法。 注:由于左线性文法和右线性文法是等价的,本次课程设计为简化需要,只考虑右线性文法和正规式之间的转换。2.2、正规式的定义正规式是描述程序语言单词的表达式,对于字母,其上的正规式及其表示的正规集可以递归定义如下: 是一个正规式,它表示

5、集合L()=。 若a是上的字符,则a是一个正则式,它所表示的正规集L(a)=a。 若正规式r和s分别表示正规集L(r)=L(s),则(a)r|s是正规式,表示集合L(r)L(s);(b)r·s是正规式,表示集合L(r)L(s);(c)r*是正规式,表示集合(L(r)*;(d)(r)是正规式,表示集合L(r)。仅由有限次地使用上述三个步骤定义的表达式才是上的正规式。运算符“|”、“·”、“*”分别称为“或”、“连接”和“闭包”。在正规式的书写中,连接运算符“·”可省略。运算符的优先级从高到低顺序排列为:“*”、“·”、“|”。2.3、正规文法和正规式的等价

6、性一个正规语言可以由正规文法定义,也可以由正规式定义,对任意一个正规文法,存在一个定义同一个语言的正规式;反之,对每个正规式,存在一个生成同一语言的正规文法,有些正规语言很容易用文法定义,有些语言更容易用正规式定义,这里两者间的转换,从结构上建立它们的等价性。2.3.1、将正规式转换成正规文法将上的一个正规式r转换成文法G=(VN,VT,S,P)。令VT =,确定产生式和VN 的元素用如下办法。选择一个非终结符S生成类似产生式的形式Sr,并将S定位G的识别符号。为表述方便,我们将Sr称作正规式产生式,因为在“”的右部含有:“*”、“·”或“|”等正规式符号。不是V中的符号。若x和y都

7、是正规式,对形如Axy的正规式产生式,重写成:AxB,By两产生式,其中B是新选择的非终结符,即BVN。对形如Ax*y的正规式产生式,重写为:AxBAyBxBBy 其中B为一新非终结符。 对形如Ax|y的正规式产生式,重写为:Ax Ay不断利用上述规则做变换,直到每个产生式都符合正规文法的形式。2.3.2、将正规文法转换成正规式将正规文法装换成正规式。基本上是上述过程的逆过程,最后只剩下一个开始符号定义的正规式。其转化规则列于下表:文法产生式正规式规则1AxB ByA=xy规则2AxA|yA=x*y规则3Ax AyA=x|y 3、 总体算法设计3.1、正规式转化为正规文法的算法利用编译原理中的

8、算符优先分析方法对正规式进行分析,可以得到将正规式转化为正规文法的算法。为了顺利实现转化算法,使用了两个工作栈,一个是OPTR,用以寄存运算符,另一个是OPND,用以寄存操作数、中间结果或最后结果,算法如下:说明:函数comp(x,y)的作用是:根据算符优先关系表,返回x和y的优先关系。函数operate(T,X,Y)的作用是:将文法符号X,Y所对应的文法(若X,Y是非终结符,则它们代表已知文法的开始符)按运算符T拼接成新的文法。operate返回新文法的开始符。3.2、正规文法转化为正规式的算法正规式与正规文法等价性的另一个方面即正规文法转换为正规式的问题,下面给出的转化算法可以将任意一个正

9、规文法转化为与其等价的正规式。在使用该算法的过程中,应注意随时利用正规式的运算律对所得结果进行化简。4、 详细设计4.1、算法涉及到的各个结构体4.1.1、每个文法规则右部非终结符前面的终结符串struct Nodeachar a20;Nodea * nexta;例如右部产生式为:SabA|cdA|efB 可归为:S(ab|cd)A|efB 此时终结符A前面的终结符串ab存在Nodea结构体中char型数组中,指针指向下一个Nodea型结构体,其char型数组中存放cd。4.1.2、每个文法规则右部结构体struct NodeG /文法每一条规则右部结构体Nodea *VTa;char VNA

10、;NodeG *nextg;4.1.3、每条文法规则结构体struct HeadG char VNA; /文法每一条规则左部非终结符NodeG *nextg; /文法规则右部产生式;4.1.4、文法规则结合struct Paragraph/文法规则集合结构体HeadG *Head;/本条规则的指针Paragraph *nextH; /下一条规则指针Paragraph *preH; /前一条规则指针,用于规则逆序查找,便于规则的逆序/替换。;4.2、主要函数4.2.1、创建文法的一条规则该函数可以实现文法规则的输入及存储。可以输入规则形式为:SaA|bA|cdB|!|e#; 其中!表示空串,#表

11、示没有非终结符,e#表示该规则产生式为e.void creatG(HeadG *head)/给出该条规则首部,创建规则char temp20;char cont='y'NodeG *nodeg;Nodea *nodea;NodeG *tail;nodeg=new(NodeG);nodea=new(Nodea);cout<<"输入规则右部终结符:"cin>>temp;strcpy(nodea->a,temp);nodea->nexta=NULL;nodeg->VTa=nodea;nodeg->VTa->ne

12、xta=NULL;/用!表示空串if(temp0!='!')cout<<"输入规则右部非终结符:"cin>>nodeg->VNA;elsenodeg->VNA=''nodeg->nextg=NULL;head->nextg=nodeg;tail=nodeg;docout<<"该条规则结束了吗(y/n)?"cin>>cont;while(cont!='y'&&cont!='n');while(cont=&#

13、39;n')/该部分代码省略,和上面相同,可参见源代码while(cont!='y'&&cont!='n');4.2.2、合并规则右部相同非终结符的项该函数可以实现文法规则右部相同项的合并。对于如SaA|bA|cdB|!|e#; 改写后为S(a+b)A|cdB|!|e#;HeadG* changG(HeadG *head) while(n2!=NULL)/n2,n1为规则右部的一个产生式,当n2和n1非终结符相同时候合并if(n2->VNA=n1->VNA)/合并Nodea *na=ht->VTa;while(na-&g

14、t;nexta!=NULL) na=na->nexta;na->nexta=n2->VTa;n2=n2->nextg;4.2.3、规则的替换用AaB|cD 替换SabA|cdC 中的A,替换后为SabaB|abcD|cdCHeadG * replaceG(HeadG *head1,HeadG *head2)/用head2规则替换head1中含有head2左部的项 while(th1!=NULL && th1->VNA!=head2->VNA)/找到head1中有head2左部得项if (th1!=head1->nextg) preth1

15、=preth1->nextg;th1=th1->nextg; if(th1!=NULL)/找到了之后串接起来while(ta1!=NULL)/串接起来while(ta2!=NULL)ss2->nexta=new(Nodea);ss2=ss2->nexta;strcpy(ss2->a,ta1->a);strcat(ss2->a,ta2->a);ss2->nexta=NULL;ta2=ta2->nexta;ta2=th2->VTa;/cout<<"ta1:"<<ta1->a<&

16、lt;endl;ta1=ta1->nexta;5、调试与运行结果5.1、 调试方法记录编辑好源程序,编译,出现多处错误,但多数是语法方面的错误,一一改正后。重新编译链接后运行,输入数据测试,经常出现指针错误提示。通过debug调试器,查看内存单元,一一分析比较,找出问题所在,返回源程序,修改,重新编译链接。这个过程是艰难和费时的,有时候多次检查不出问题原因。调试还通过设置输出语句查看数据实现。例如不清楚a的值,可以通过cout<<”a=”<<a;查看a的值,分析其是否与理论值相等,若正确,则错误的原因很有可能在此句之后,否则在这句之前定有错误。经过多次修正,终于使

17、得程序正确。5.2 、实验结果记录5.2.1、第一组测试数据对于正规文法Z0A;A0A|0B;B1A|;其正规式应为Z=0(0|01)*0.实验为Z=0(0)*0|0(01)*0可以化为0(0|01)*0。故实验结果正确。5.2.2、第二组测试数据对于正规文法SaA;AaA|bB|b;BbA|b;其正规式应为S=aa*(bb*b|b).实验为S=aa*bb*b|aa*b可以化为aa*(bb*b|b)。故实验结果正确。5.2.3、第三组测试数据对于正规文法SaB;BbA|bB;Ac|cA;其正规式应为S=abb*c*c.实验为S= abb*c*c.故实验结果正确。6、 课程设计总结与心得体会本课程设计主要是让我们掌握正规文法和正规式的转换算法,加深对正规文法和正规式的理解,正规文法和正规式是构造有穷自动机的前提,有穷自动机又是进行词法分析的工具,因此掌握转换方法对于编译很重要。总体来说通过这次的编译原理的课程设计,我学到了很多东西。平时的实验课程使我已经掌握了编译原理词法分析、语法分析、语义分析的方法。这些是我这次顺利做出课程设计的基础。课程设计过程中,我学会很重要的调试方法,可以设计输出语句,查看内存单元是否正确,这在今后的学习工作中是很有用的,同时我还深刻体会到了耐心很重要,没有耐心,是很难把事情做成功的。课设中我也感觉到自

温馨提示

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

评论

0/150

提交评论