消除左递归-编译原理实验_第1页
消除左递归-编译原理实验_第2页
消除左递归-编译原理实验_第3页
消除左递归-编译原理实验_第4页
消除左递归-编译原理实验_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

1、精选优质文档-倾情为你奉上编译原理实验报告实验名称:消除左递归_实验时间:2015-05-27_院 系:管理信息工程学院_班 级:12级计算机科学技术_学 号:2_姓 名:王博一_1、 实验目的:理解LL(1)文法中消除左递归的原理2、 实验原理:1直接左递归的消除消除产生式中的直接左递归是比较容易的。例如假设非终结符P的规则为:PP / 其中,是不以P开头的符号串。那么,我们可以把P的规则改写为如下的非直接左递归形式: PP PP / 这两条规则和原来的规则是等价的,即两种形式从P推出的符号串是相同的。 设有简单表达式文法GE: EE+T/ T TT*F/ F F(E)/ I经消除直接左递归

2、后得到如下文法: ETE E +TE/ TFTT *FT/ F(E)/ I考虑更一般的情况,假定关于非终结符P的规则为PP1 / P2 / Pn / 1 / 2 /m其中,i(I1,2,n)都不为,而每个j(j1,2,m)都不以P开头,将上述规则改写为如下形式即可消除P的直接左递归:P1 P / 2 P /m PP 1P / 2 P / n P /2间接左递归的消除直接左递归见诸于表面,利用以上的方法可以很容易将其消除,即把直接左递归改写成直接右递归。然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。有些文法虽然表面上不存在左递归,但却隐藏着左递归。例如,设有文法GS:SQc/ cQ

3、Rb/ bRSa/ a虽不具有左递归,但S、Q、R都是左递归的,因为经过若干次推导有SQcRbcSabcQRbSabQcabRSaQcaRbca就显现出其左递归性了,这就是间接左递归文法。消除间接左递归的方法是,把间接左递归文法改写为直接左递归文法,然后用消除直接左递归的方法改写文法。如果一个文法不含有回路,即形如PP的推导,也不含有以为右部的产生式,那么就可以采用下述算法消除文法的所有左递归。消除左递归算法:(1) 把文法G的所有非终结符按任一顺序排列,例如,A1,A2,An。(2) for (i1;i<=n;i+)for (j1;j<=i1;j+)把形如AiAj的产生式改写成A

4、i1 /2 /k 其中Aj1 /2 /k是关于的Aj全部规则; 消除Ai规则中的直接左递归; (3) 化简由(2)所得到的文法,即去掉多余的规则。利用此算法可以将上述文法进行改写,来消除左递归。首先,令非终结符的排序为R、Q、S。对于R,不存在直接左递归。把R代入到Q中的相关规则中,则Q的规则变为QSab/ ab/ b。代换后的Q不含有直接左递归,将其代入S,S的规则变为SSabc/ abc/ bc/ c。此时,S存在直接左递归。在消除了S的直接左递归后,得到整个文法为:SabcS/ bcS'/ cS'S abcS'/ QSab/ ab/ bRSa/ a可以看到从文法开

5、始符号S出发,永远无法达到Q和R,所以关于Q和R的规则是多余的,将其删除并化简,最后得到文法GS为:SabcS'/ bcS/ cS'S' abcS'/ 当然如果对文法非终结符排序的不同,最后得到的文法在形式上可能不一样,但它们都是等价的。例如,如果对上述非终结符排序选为S、Q、R,那么最后得到的文法GR为: RbcaR'/ caR'/ aRR' bcaR'/ 容易证明上述两个文法是等价的。3、 实验内容:分析见下图图(a)变量说明图(b)直接左递归分析图图(c)间接左递归分析图用C语言实现定义四个函数int direct(char

6、 PNN); /直接左递归函数int indirect(char PNN); /间接左递归函数void directRemove(char PNN); /消除直接左递归函数void indirectRemove(char PNN); /消除间接左递归函数并在main函数中依次调用4、 代码实现#include "stdafx.h"#include<stdio.h>#include<string.h>#define N 20char PNN; /规则集char QN; /规则集,存放间接左递归消除后的部分规则char RNN; /用来存放规则的初始值i

7、nt r; /实际输入的规则的个数int direct(char PNN); /直接左递归函数int indirect(char PNN); /间接左递归函数void directRemove(char PNN); /消除直接左递归函数void indirectRemove(char PNN); /消除间接左递归函数int direct(char PNN) /定义直接左递归函数 int flag=0; for(int i=0;i<r;i+) if(Pi3=Pi0) /右部字符中有与左部相同的符号 flag+; break; if(flag>0)printf("经判断该文法

8、含有直接左递归!n");return 1; /属于直接接左递归 else return 0; /不属于直接左递归int indirect(char PNN) /定义间接左递归函数 int flag=0; for(int i=0;i<r;i+)for(int k=1;k<r;k+)if(Pi+k0=Pi3) flag+; break; if(flag>0) break; if(flag>0) printf("经判断该文法含有间接左递归!n");return 2; /属于间接左递归 else return 0; /不属于间接左递归void di

9、rectRemove(char PNN) /定义消除直接左递归的函数int j=4;for(int i=0;i<r;i+)if(Pi3=Pi0) Pi3=Pi2; Pi2=Pi1; Pi1=''' while(Pij!=0) j+;Pij=Pi0;Pij+1='''for(int k=0;k<4;k+) /包含空的一条规则 Prk=Pik;Prk='*'elsej=3;while(Pij!=0) j+;Pij=Pi0;Pij+1=''' printf("n消除直接左递归后的文法为:n&

10、quot;);printf("n");printf("(*代表)n");printf("n");for(int t=0;t<r+1;t+) printf("%sn",Pt);void indirectRemove(char PNN) /定义消除间接左递归的函数 int flag,flag1=0,copy=r;int e=0; Qe=Pe0; /统计规则中不同的左部 for(int i=1;i<r;i+)flag=0;for(int k=0;k<=e;k+)if(Pi0!=Qk)flag+;if(f

11、lag=(e+1)e+;Qe=Pi0; int g=0;for(int j=0;j<e;j+)int number=0;for(int z=0;z<r;z+)if(Pz0=Qj)number+; /统计相同左部的规则个数 if(number>1) copy+; /如果有相同左部则规则总数加一 for(i=0;i<r;i+) for(int k=1;k<r;k+) if(Pi0=Pi+k3)&&(flag1=0) for(int y=0;Pi+ky!=0;y+)Rgy=Pi+ky; /把原值保留flag1=1; int m=3;while(Pim!=

12、0) /统计替换字符的个数为m-1-2m+;int t=m-3;int n=4;while(Pi+kn!=0) /统计被替换规则中非终结符的个数为n-4n+;for(int s=n-1;s>=4;s-)Pi+ks+t-1=Pi+ks;for(int u=3;u<3+t;u+)Pi+ku=Piu;break;else if(Pi0=Rg3)&&(flag1=1) for(int y=0;Rgy!=0;y+) Pcopy-1y=Rgy;int m=3;while(Pim!=0) /统计替换字符的个数为m-1-2m+;int t=m-3;int n=4;while(Pco

13、py-1n!=0) /统计被替换规则中非终结符的个数为n-4n+;for(int s=n-1;s>=4;s-)Pcopy-1s+t-1=Pcopy-1s;for(int u=3;u<3+t;u+)Pcopy-1u=Piu;break; flag1=0;g+;printf("首次消除间接左递归后的直接左递归文法为:n");for(int t=0;t<copy;t+) printf("%sn",Pt);printf("n"); for(i=0;i<copy;i+)if(Pi0=Qe)if(Pi3=Pi0) Pi3=

14、Pi2;Pi2=Pi1;Pi1='''while(Pij!=0)j+;Pij=Pi0;Pij+1='''for(int k=0;k<4;k+) /包含空的一条规则Pcopyk=Pik;Pcopyk='*'elsej=3;while(Pij!=0) j+;Pij=Pi0;Pij+1=''' printf("再次消除直接左递归后的文法为:n");printf("n");printf("(*代表)n");printf("n");

15、for(t=0;t<=copy;t+) printf("%sn",Pt);void main() printf("请输入上下文无关的文法规则P的个数: "); scanf("%d/n",&r); printf("n"); printf("请输入各条规则,规则的左部跟右部用->连接,规则间用空格隔开"); printf("n"); for(int k=0;k<r;k+)scanf("%s",Pk); printf("n");printf("即输入的文法规则为:n&qu

温馨提示

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

评论

0/150

提交评论