首先先進行一下總結:
上面就是通用形勢,遇見左遞歸文法,需要消除的時候,提取出和
用下面的文法直接進行替換,就可以了
一個文法含有下列形式的產生式之一時:
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'|ε
與上面文法是等價的。