《c实现消除文法左递归.doc》由会员分享,可在线阅读,更多相关《c实现消除文法左递归.doc(9页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、编译原理实验报告实验名称 消除文法的左递归 实验时间 2010.11.1 院系 计算机科学与技术 班级 2008 学号 JB084193 姓名 潘亚飞 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/ cQRb/ bRSa
3、/ a虽不具有左递归,但S、Q、R都是左递归的,因为经过若干次推导有SQcRbcSabcQRbSabQcabRSaQcaRbca就显现出其左递归性了,这就是间接左递归文法。消除间接左递归的方法是,把间接左递归文法改写为直接左递归文法,然后用消除直接左递归的方法改写文法。如果一个文法不含有回路,即形如PP的推导,也不含有以为右部的产生式,那么就可以采用下述算法消除文法的所有左递归。消除左递归算法:(1) 把文法G的所有非终结符按任一顺序排列,例如,A1,A2,An。(2) for (i1;i=n;i+)for (j1;j=i1;j+)把形如AiAj的产生式改写成Ai1 /2 /k 其中Aj1 /
4、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/ cSS abcS/ QSab/ ab/ bRSa/ a可以看到从文法开始符号S出发,永远无法达到Q和R,所以关于Q和R的规则是多余的
5、,将其删除并化简,最后得到文法GS为:SabcS/ bcS/ cSS abcS/ 当然如果对文法非终结符排序的不同,最后得到的文法在形式上可能不一样,但它们都是等价的。例如,如果对上述非终结符排序选为S、Q、R,那么最后得到的文法GR为: RbcaR/ caR/ aRR bcaR/ 容易证明上述两个文法是等价的。3.实验内容 消除左递归算法:(1)把文法G的所有非终结符按任一顺序排列,例如,A1,A2,An。(2)for (i1;i=n;i+)for (j1;j=i1;j+)把形如AiAj的产生式改写成Ai1 /2 /k 其中Aj1 /2 /k是关于的Aj全部规则; 消除Ai规则中的直接左递归
6、; (3)化简由(2)所得到的文法,即去掉多余的规则。利用此算法可以将上述文法进行改写,来消除左递归。4.实验代码/#include stdafx.h#include#includeusing namespace std;struct WF /定义一个产生式结构体string left; /定义产生式的左部string right; /定义产生式的右部;void Removing(WF *p,char *q,int n,int count)int count1=n;int flag=0;for(int i=0;i n;i+)/判断第一个非终结符是否存在直接左递归 if(pi.left0=q0)
7、 if(pi.left0=pi.right0) flag+;if(flag!=0)/如果存在直接左递归则消除直接左递归 for(int i=0;i n;i+) if(pi.left0=q0) if(pi.left0=pi.right0) string str; str=pi.right.substr(1,int (pi.right.length(); string temp=pi.left; string temp1=; pi.left=temp+temp1; pi.right=str+pi.left; else string temp=pi.left; string temp1=; temp
8、=temp+temp1; pi.right=pi.right+temp; string str=; pcount1.left=p0.left0+str; pcount1.right=;for( i=0;i = count;i+) for(int j=0;j i;j+) for(int g=0;g n;g+) if(qi=pg.left0) if(pg.right0=qj) for(int h=0;h n*n;h+) if(ph.left0=qj&int (ph.left.length()=1) string str; str=pg.right.substr(1,int (pg.right.le
9、ngth(); p+count1.left=pg.left; pcount1.right=ph.right+str; pg.left=; pg.right=; for( i=0;i = count;i+) flag=0; for(int j=0;j n*n;j+) if(pj.left0=qi) if(pj.left0=pj.right0) flag+; if(flag!=0) for(int j=0;j = n*n;j+) if(pj.left0=qi) if(pj.left0=pj.right0) string str; str=pj.right.substr(1,int (pj.righ
10、t.length(); string temp=pj.left; string temp1=; pj.left=temp+temp1; pj.right=str+pj.left; else string temp=pj.left; string temp1=; temp=temp+temp1; pj.right=pj.right+temp; string str=; p+count1.left=qi+str; pcount1.right=; int Delete(WF *p,int n)return 0;int main()int i,j,flag=0,count=1,n;cout请输入文法产
11、生式个数n:n;WF *p=new WF50;cout请输入文法的个产生式:endl;for(i=0;ipi.left; coutpi.right; coutendl;coutendl;cout即输入的文法产生式为:endl;for(i=0;i n;i+) coutpi.leftpi.rightendl;cout*endl;char q20;/对产生式的非终结符排序并存取在字符数组q q0=p0.left0;/把产生式的第一个非终结符存入q中for(i=1;in;i+)/对非终结符排序并存取 flag=0; for(j=0;ji;j+) if(pi.left=pj.left) flag+; i
12、f(flag=0) qcount+=pi.left0; count-; Removing(p,q,n,count);/调用消除递归子函数 Delete(p,n);/删除无用产生式 cout消除递归后的文法产生式为:endl; for(i=0;i = count;i+) for(int j=0;j = n*n;j+) if( (pj.left0=qi) & int (pj.left.length()=1 ) coutpj.leftpj.rightendl; else continue; for( j=0;j = n*n;j+) if( (pj.left0=qi) & int (pj.left.l
13、ength()=2 ) coutpj.leftpj.rightendl; else continue; return 0;5.实验结果消除直接左递归:消除间接左递归:6.实验心得一个文法是含有左递归的,如果存在非终结符P ,PP含有左递归的文法将使上述的自上而下的分析过程陷入无限循环,即当试图用P去匹配输入串时,就会出现在没有吃进任何输入符号的情况下,又得重新要求P去进行新的匹配。因此,使用自上而下分析法必须消除文法的左递归性。对文法中一切左递归的消除要求文法中不含回路即无AA的推导。满足这个要求的充分条件是:文法中不包含形如AA和A的空产生式。根据消除左递归的算法步骤我们可以得出整个程序思路
14、。对于产生式的存储问题,采用定义产生式的结构体,再用表的形式来存储所有的产生式。再输入存储时就将产生式的左部和右部分开存储于产生式结构体中,方便后面的操作。在消除左递归的过程中,对于直接左递归,可将其改为直接右递归;对于间接左递归(也称文法左递归),则应按照算法给出非终结符不同排列的等价的消除左递归后的文法。 9 法法递除价列符终法按则)文(左于归接为将递直对程递除作面方中结于开部和生将存再生有存式用体的产用采储式于思个得以步算左式产和如中:件的个满推 即含法除消递性性法消必下自用。匹进求重,况的何进在会时输匹图试环入过的上述将的 终果的左有心心归归归左结结0 -. =) &)= ( +* 0
15、( .- =)( &)= + = 0 ( + :产法归 生用无;, 函子消用) , ( - + 0= ( + = ( + 0( 0 存序结对/ 存终非的把/0 0 组符取并结的式/; * + = 产的入 -生入/+;= :产法入 * :式产输 0 ( 0 , ( = . + + += . = ) . , .= . =0 = . (+ *= 0 ( 0! + 0 =0 = . + ;= ( 0 + = . = . + ) . , . .= =( .( = ( + * 0 =0 0 ( + = + ; ( + .= . + + = = ) . ( . = + ; = ( 递接直归直果/= + =0
16、 . = . 递左存符终一断) ;= (0 = * 右式义/; 左式产/ 构式产一 代验归归来改法上以则的多,文所 化 归递的规 则部 关 中 / / 写式的如+= (+= , ,列顺一终有 法归左内实的等法个明 : 文得么 、 符终对如例等们但不能式法后同序符法对 为法到后化其,多规 以 到无永 符文到 / / / 为文个后左的 。递直 为 ,将,左含的 / / 变的则关相到把递直存于 为的终归递除改行上可则规掉即文得( 归递接则除 则部 于/ /其/ 写产 形+ (+ , 如列顺任结有法归递归左所文法用以那式部右含,推如即有法法法法归左用,归接为文递间是的接法归接间这归其 导导过经的是 、
17、,递 文,。左隐,递不面法文。左就法着并递不法文归接写左把除将容可上用表于递消归接/ / / 归左直消式如改则将 都, 个,不 / / / 则规 终假况般 ) / 法下得递直 /( / / 文达简的相号出推种,等规原规 式递非下为的把我那号头 /则的符非假。比递接式消的接原验法价归了消法关下的目验 飞 与机计 . 递法 报验报报法 机 飞 验的法了验的接。的/头我为递 规等种的文 / 直下 / 假则, 都将如左 / /消表可将左文不法左面,左 ,是过 其这法是文归左法法即右式法左归法顺 ( +/于除递(即规行除归为存到关变/含, 。左文 / 符无 规后 序同不等如终么文 明等实归终顺 + +的写 关规递所多以改归 式 产 / =)终 =/归( + ( ) = + . ; 0= + ( = . + = . 0(=+.= 0 !( *+. 0. ) = =+ . ( 0( 产: 入法 ;+ - 产 *的并组0/的 存 ( (= +( - ,用子,无 法 =+ ) - 0 +& = .- 结归心的终的上入图时在况求。下必性除 推:产左以于采的式生将生开面递直将于文按符列递