手寫編譯器-左遞歸消除

手寫編譯器

左遞歸消除

左遞歸語法是指表達式左側包含有和表達式開始符號一致的非終結符號S->Sa (該生成式中包含和表達式開始符號的非終結符號S); 結果及時S->Sa生成式可以解析成S->Saa… … (a個數不限),同理生成式 S->Sa|ß 也有左遞歸問題(

此處列舉消除左遞歸的2個方法


//1,直接消除左遞歸

S->Sa|ß ==> S->Sa1||San|ß1||ßn 可從重寫成 S->ß1S’||ßnS’ S’-> a1S’|a2S’||anS’ (通過引入S’);

因爲S->Sa|ß ==> S->Sa1||San|ß1||ßn解析結束的時候ß肯定是第一個。


2, 間接消除左遞歸

// 原則

// 1) 若消除過程中出現了直接左遞歸,就按照直接左遞歸的方法,來消除

// 2) 若產生式右部最左的符號是非終結符,且這個非終結符序號大於等於左部非終結符, 則暫不處理(後面會處理到)

// 3) 若序號小於左部的非終結符,則用之前求到的式子的右部來替換



// arrange the nonterminals in some order AI , A2, .•• , An. 這裏將所有的產生式的非終結符號列出,排序比如

// 1)S → Qc | c

// 2)Q → Rb | b

// 3)R → Sa | a

//則這裏的A1,A2,A3就是S,Q,R,並嚴格按此順序執行,下表分別是1,2,3




for ( each i from 1 to n ) {

for ( each j from 1 to i-I ) {

replace each production of the form Ai -> Aj’Y by the productions Ai -> (1‘Y I ∂2’Y I . . . I ∂k‘Y, where Aj ->1 I ∂2 I . . . I ∂k are all current Ai productions

//這裏j<i , Aj是每條比Ai標號小的產生式,如A1,A2 ,當i==2的時候 則找到生產式右側爲A1-> ∂1的並將其用Ak (K>1) 來替換 Aj ,這裏的語義就是非終結符號 Ai 的產生式, 如果右側有非終結符號 Aj出現 j<i (如果等於i,可以用上述方法1說明的方法引入S’ 將產生式有直接左遞歸的先消除) 就用 非終結符號Aj的產生式將 Aj 替換 Ak∂ ,直到 k>1

}

}

//上述算法最終得到的結果就是 Ai->Ak∂ , 其中k>1 (Ak 只能被比Ak編號更高的非終結符號產生式表示,所以最終會將4說明中提到的間接左遞歸集合2,3 說明中的方法來間接消除間接左遞歸)




// 接着上面的例子

S,S->→ Qc | c (Q的下標大於S,不動)

Q,Q → Rb | b (R的下標大於Q,不動)

R,R → Sa | a (S的下標比R小)

==> R → Qca | ca | a (Q比R小)

==> R-> Rbca | bca |ca |a (採用原則1,採用直接消除原則,最終肯定會出現bca,ca,aq其中一個)

==> R-> bcaR‘ | caR’ | aR‘ , R’ = bcaR‘|£ (最終的結果消除不可到達的非終結Q,S,如若讀者想先出R,Q,方法一樣)



發佈了24 篇原創文章 · 獲贊 20 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章