编译原理 消除左递归

一个文法含有下列形式的产生式之一时:

1)AAβ,AVN,β∈V*

2)ABβ,BAα,ABVN,α、β∈V*

则称该文法是左递归的。

一个文法G,若存在P经过一次或多次推导得到Pa(即能推导出以P开头的式子), 则称G是左递归的。


然而,一个文法是左递归时,不能采取自顶向下分析法。

 

左递归分为直接左递归和间接左递归。

直接左递归经过一次推导就可以看出文法存在左递归,如PPab

间接左递归侧需多次推导才可以看出文法存在左递归,如文法:SQccQRbbRSaaS =>Qc =>Rbc =>Sabc

 

消除左递归方法有:

a)把直接左递归改写为右递归:

设有文法产生式:AAβ|γ。其中β非空,γ不以A打头。

可写为:A→γA'

A'→βA'|ε

一般情况下,假定关于A的产生式是:

AAα1| Aα2 |… |Aαm|β1|β2 ||βn

其中,αi(1im)均不为空,βj(1jn)均不以A打头。

则消除直接左递归后改写为:

A→ β1A'| β2 A' |βnA'

A'→ α1A' | α2A' |αmA' |ε

 

例:有文法G(E)

EE +T |T

TT*F | F

F (E)|i

消除该文法的直接左递归。

解:按转换规则,可得:

ETE'

E'+TE'|ε

TFT '

T'*FT'|ε

F(E)|i


b)消除间接左递归:

对于间接左递归的消除需要先将间接左递归变为直接左递归,然后再按a)清除左递归。

例:以文法G6为例消除左递归:

(1)AaB

(2)ABb

(3)BAc

(4)Bd

解:用产生式(1)(2)的右部代替产生式(3)中的非终结A得到左部为B的产生式:

(1)BaBc

(2)BBbc

(3)Bd

消除左递归后得到:

BaBcB' |dB'

B'bcB' |ε

再把原来其余的产生式AaB,ABb加入,最终得到等价文法为:

(1) AaB

(2) ABb

(3) B(aBc|d)B'

(4) B'bcB'|ε

 

c)消除文法中一切左递归的算法

要求文法不存在经过一次或多次能推导出A和不存在ε产生式(形如A→ε)。 

  1、以某种顺序排列非终结符A1A2,……,An

  2for i = 1 to n do

    {for j = 1 to i - l do

     用产生式Aia1ba2b|……|akb代替每个开如AiAjb的产生式,其中,Aja1a2|……|ak是所有的当前Aj产生式;}

    消除关于Ai产生式中的直接左递归性}

   }

  3、化简由步骤2所得到的文法。

 

  例2:有文法SQcc

QRbb

RSaa

消除文法的左递归。

  以非终结符号排序为RQS

  把R的产生式代入Q中有:

  → (Saabb

  → Sa babb

  把Q的产生式代入S中有:

  → (Sa babbc  

  → Sa bcabcbcc

  消除直接左递归得到结果:

  → abcS’|bc S’|cS’ 

  S’→ abcS’|ε

  → Sa bab

  → Sa

  和 R的产生式是多余的删除,得到最终结果:

  → abcS’|bc S’|cS’ 

        S’→ abcS’|ε

注意,由于对非终结符排序的不同,最后所得的文法在形式上可能不一样。但不难证明,它们都是等价的。

例如对上述文法的非终结符排序选为S,Q,R,那么,所得的无左递归文法是:

把Q的产生式代入S中有:

S->Qc|c

S->(Rb|b)c|c

S->Rbc|bc|c

把S的产生式代入R中有:

R->Sa|a

R->(Rbc|bc|c)a|a

R->Rbca|bca|ca|a

 消除直接左递归得到结果:

R->bcaR'|caR'|aR'

R'->bcaR'|ε

与上面文法是等价的。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页