編譯原理 消除左遞歸


首先先進行一下總結:

 

 上面就是通用形勢,遇見左遞歸文法,需要消除的時候,提取出

 

 用下面的文法直接進行替換,就可以了

 

一個文法含有下列形式的產生式之一時:

1)A→Aβ,A∈VN,β∈V*

2)A→Bβ,B→Aα,A、B∈VN,α、β∈V*

則稱該文法是左遞歸的。

一個文法G,若存在P經過一次或多次推導得到Pa(即能推導出以P開頭的式子), 則稱G是左遞歸的。


然而,一個文法是左遞歸時,不能采取自頂向下分析法。

 

左遞歸分為直接左遞歸和間接左遞歸。

直接左遞歸經過一次推導就可以看出文法存在左遞歸,如P→Pa|b。

間接左遞歸側需多次推導才可以看出文法存在左遞歸,如文法:S→Qc|c,Q→Rb|b,R→Sa|a有S =>Qc =>Rbc =>Sabc

 

消除左遞歸方法有:

a)把直接左遞歸改寫為右遞歸:

設有文法產生式:A→Aβ|γ。其中β非空,γ不以A打頭。

可寫為:A→γA'

A'→βA'|ε

一般情況下,假定關於A的產生式是:

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

其中,αi(1≤i≤m)均不為空,βj(1≤j≤n)均不以A打頭。

則消除直接左遞歸后改寫為:

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

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

 

例:有文法G(E):

E→E +T |T

T→T*F | F

F→ (E)|i

消除該文法的直接左遞歸。

解:按轉換規則,可得:

E→TE'

E'→+TE'|ε

T→FT '

T'→*FT'|ε

F→(E)|i


b)消除間接左遞歸:

對於間接左遞歸的消除需要先將間接左遞歸變為直接左遞歸,然后再按a)清除左遞歸。

例:以文法G6為例消除左遞歸:

(1)A→aB

(2)A→Bb

(3)B→Ac

(4)B→d

解:用產生式(1),(2)的右部代替產生式(3)中的非終結A得到左部為B的產生式:

(1)B→aBc

(2)B→Bbc

(3)B→d

消除左遞歸后得到:

B→aBcB' |dB'

B'→bcB' |ε

再把原來其余的產生式A→aB,A→Bb加入,最終得到等價文法為:

(1) A→aB

(2) A→Bb

(3) B→(aBc|d)B'

(4) B'→bcB'|ε

 

c)消除文法中一切左遞歸的算法

要求文法不存在A 經過一次或多次能推導出A和不存在ε產生式(形如A→ε)。

  1、以某種順序排列非終結符A1,A2,……,An;

  2、for i = 1 to n do

    {for j = 1 to i - l do

     { 用產生式Ai→a1b|a2b|……|akb代替每個開如Ai→Ajb的產生式,其中,Aj→a1|a2|……|ak是所有的當前Aj產生式;}

    消除關於Ai產生式中的直接左遞歸性}

   }

  3、化簡由步驟2所得到的文法。

 

  例2:有文法S→Qc|c,

Q→Rb|b,

R→Sa|a,

消除文法的左遞歸。

  以非終結符號排序為R,Q,S

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

  Q → (Sa|a)b|b

  Q → Sa b|ab|b

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

  S → (Sa b|ab|b)c|c  

  S → Sa bc|abc|bc|c

  消除直接左遞歸得到結果:

  S → abcS’|bc S’|cS’

  S’→ abcS’|ε

  Q → Sa b|ab|b

  R → Sa|a

  Q 和 R的產生式是多余的刪除,得到最終結果:

  S → 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'|ε

與上面文法是等價的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM