学习《编译原理》- 消除左递归笔记

目录

消除左递归

消除直接左递归

消除间接左递归

结语


消除左递归

在进行语法分析时,一个文法要能产生无限个不同的句子,必须具有递归产生式。

但是在语法分析中,左递归会导致语法分析的回溯,会导致较大的时间和空间开销,所以,我们需要消除左递归,将其转化为右递归。从而消除两义性,使得我们能够适应确定的自上而下的语法分析器分析语法。

在学习数据结构与算法时,我们便知道,递归分为两种,既直接递归与间接递归。同样,左递归也分为直接左递归与间接左递归。

直接左递归文法示例如下:

A -> Aa

间接左递归示例如下:

S -> Aa
A -> Sb|c

接下来,我们演示如何正确消除这些左递归。

消除直接左递归

消除直接左递归的方法是,将左递归的产生式改写成等价的右递归产生式。

具体操作方法为(该方法为博主总结,为初学时所用,博主才疏学浅,若有错漏之处,欢迎批评指正):

1、引入新的非终结符A'(假设存在左递归的非终结符为A,写为A'易于标识与理解)

2、将不含原非终结符的其他产生式引出为α(若该非终结符不含其他产生式,则α为ε)

3、将含左递归的原非终结符的产生式的其他符号引出为η1 | η2 |...| ηn

4、将α与A'结合为新的、非终结符A的产生式 A - >αA'

5、增加A'的产生式为η1 A’ | η2 A’ |...| ηn A’

6、为A'增加一条产生式为ε

例如,文法的产生式为:

A -> Aγ|w

则消除左递归后的文法产生式为:

A -> wA'
A' -> yA'|ε

容易发现,上述两个文法产生式等价。

再比如,文法的产生式为:

I -> IL | ID | L

则消除左递归后的文法产生式为:

I -> LI'
I' -> LI' | DI' | ε

容易发现,上述两个文法产生式也是等价的。

又一例,原文法的产生式为:

S -> Sabc|abc|bc|c

则消除左递归后的文法产生式为:

S -> abcS'|bcS'|cS'
S' -> abcS'|ε

容易发现,上述两个文法产生式也是等价的。

一般而言:

一般地,设文法G含有直接左递归的产生式为

A → Aa1 | Aaz |···| Aan | β

其中,β为不含左递归的候选式。引入文法G',相应于A的产生式为

A -> βA'
A'-> a1 A' | a2 A' |···| an A' |ε

显然第二条文法不含左递归且与第一条文法等价。

消除间接左递归

设间接左递归文法为G,消除文法G的间接左递归的算法如下:

(1)将文法G的所有非终结符按任一给定的顺序排列,设为A1,A2,···,An;

(2)消除可能的左递归;

for (i = 1; i <= n ; i++) {
    for (j = 1; J <= i-1; j++){
        把一个形如Ai -> Aja的产生式改写为A1 -> δ1a|δa|···|δka;
        (其中,A -> δ1|δ2|···|δx是A,的所有产生式)
    }
    消除A1产生式的直接左递归;
}

(3)化简。删除多余产生式,即在从文法开始符开始的任何推导中都不出现的非终结符的产生式。

以上方法来自于王晓斌老师主编的《程序设计语言与编译——语言的设计与实现》一书。 

博主理解如下(博主才疏学浅,若有错漏之处,欢迎批评指正):两次For循环是为了尽可能将存在间接递归的产生式结合,生成一个正确、完备、唯一的直接左递归产生式,再利用消除直接左递归的方法消除左递归。

举例如下:

设文法G为:

S -> Qc|c
Q -> Rb|b
R -> Sa|a

将文法按照R、Q、S排序,则可以将关于Q的产生式改写为:

Q -> Sab|ab|b

之后,可以进一步将关于S的产生式改写为:

S -> Sabc|abc|bc|c

于是,上述的间接左递归被改写为了直接左递归,容易发现,上述两组文法产生式也是等价的。

消除左递归得到:

S -> abcS'|bcS'|cS'
S' -> abcS'|ε

分析发现,在这个产生式集合中,关于Q的产生式和关于R的产生式为多余产生式,可删除。

于是我们得到了不含左递归且与原文法等价的文法:

S -> abcS'|bcS'|cS'
S' -> abcS'|ε

算法并未对非终结符的排序加以规定,排序不同,结果可能不同,但彼此还是等价的。

通过上述变换已将文法变换成无公共左因子、无左递归的等价文法。

结语

消除左递归笔记至此结束,若有其他编译原理的相关问题,可参考博主的其他博客。

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值