一:什么是左遞歸
在計算機科學里面,左遞歸是一種遞歸的特殊狀況。
在上下文無關文法內里的說法,若一個非終端符號(non-terminal)r有任何直接的文法規則或者通過多個文法規則,
推導出的句型(sentential form)其中最左邊的符號又會出現r,則我們說這個非終端符號r是左遞歸的。
即形如:r->rj像這樣的式子。
二:左遞歸的類型
1:直接左遞歸:經過一次推導就能看出文法存在左遞歸的產生式
形如:s->sb|ε
2:間接左遞歸:經過多次推導才能看出文法存在左遞歸的產生式
形如:S->ASb|ε
A->aA|ε
當A->ε時,第一個產生式就是直接左遞歸了。
三:左遞歸的解法
直接左遞歸的解法:
1、把所有產生式寫成候選式形式。如A→Aa1|Aa2……|Aan|b1|b2……|bm。其中每個a都不等於ε,而每個b都不以A開頭。
2、變換候選式成如下形式:
A→b1A’|b2A’……|bmA’
A’ →a1A’|a2A’……|anA’|ε
例子:考慮文法G: S->Sb,|a
一次推導: s->sb,
兩次推導: s->sb,b,
三次推導: s->sb,b,b,
....
n次推導: s->ab,b,b,b,.....
觀察上面的推導式子,該產生式子最后產生的字符串是以a開頭的字符串。
所以 s->sb,|a可以替換為
s->as'
s'->b,s'|ε
間接左遞歸的解法:將間接轉換為直接。
要求:文法不存在環和ε產生式
步湊:
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所得到的文法。
例子:S->Ab|a
A->Bc|t
B->Sb|l|d
1:非終結符號排序:B,A,S
2: 用B->Sb|l|d中的 Sb|l|d 代替 A->Bc|t中的B得到:
A->Sbc|lc|dc|t
用A->Sbc|lc|dc|t中的Sbc|lc|dc|t 代替 S->Ab|a中的A得到:
S->Sbcb|lcb|dcb|tb|a
消除直接左遞歸:
S->lcbs'|dcbs'|tbs'|as'
s'->bcbs'|ε
所以最終的結果:
S->lcbs'|dcbs'|tbs'|as'
s'->bcbs'|ε
A->Sbc|lc|dc|t
B->Sb|l|d
才疏學淺,若有不對之處,歡迎留言批評指正