形式語言與編譯 九 CFG到CNF再到GNF 左遞歸消除


先找出\(N_A簇,N_B簇,N_C簇\),先對\(N_A簇\):是單產生式的 將來會因為替換而消除;不是單產生式的 直接放進新的集合

同理對\(N_B簇,N_C簇\)也是一樣(這樣一般得到三個"堆")

確實沒了單產生式。

CFG的化簡

建議做的過程:

  1. 消除\(\epsilon\) 產生式
  2. 消除單產生式
  3. 消除無用符號

按這個順序做

這樣化簡后的CFG G1 與原來的CFG G相比,有\(L(G_1)=L(G)-\{\epsilon\}\)

對上面簡化后的CFG進行標准化——Chomsky范式

本來我們的CFG文法它的形式是 \(A->\alpha,其中\alpha\in(V_N \cup V_T)^*\) 也就是這個串有終結符和非終結符組成的串即可,要求並不嚴

現在我們進行喬姆斯基范式的正規化。目的就是讓我們上面的定義受到一些約束,形成這種\(A->BC,A->a ,a\in V_T\) 類型(\(A->變元變元,A->終結符\))的。

(這里與我們的正則文法,可以類比,正則文法的形式是:\(A->\alpha , A->\alpha B,\alpha\in (V_T)^*\),也就是終結符組成的字符串 或者 終結符組成的字符串+變量)

注意:若語言\(\epsilon \in L(G)\) 就會有\(S->\epsilon\)這樣一條產生式加入產生式集合 這里很好理解,但是要求\(S\)只能當做開始符號,不能在到別的產生式的產生式體中,要是迫不得已,則就是我們引進$S_1->S與S_1->\epsilon $

對每一個CFG 都有喬姆斯基范式CNF,也就是都可以化成\(A->BC,A->a ,a\in V_T\) 這種形式

從上下文無關文發(CFG)到CNF(喬姆斯基范式)的算法

說明:

掃描原來產生式,如果是終結符,就把這個終結符拎出來,形成產生式 【新變量->終結符】 的形式,再把原來產生式中的終結符替換成新變量

如果是非終結符(變量),把這個長的變量組成的串 想辦法縮短成多個小短串(小短串的產生式體只包含不超過2個變量)

Greibach范式(GNF)

為什么要提出Greibach范式???

因為自上而下的推導中會產生回溯,回溯導致分析效率降低

產生回溯的原因:

  • 存在\(A->Ab\) 左遞歸的非終結符
  • 同一個非終結符的候選式們 有公共左因子 (產生體左邊有一部分一樣的)

如何避免回溯?? 消除左遞歸!

Greibach范式的定義 :

把所有產生式定義成:\(A->a\beta,A\in V_N ,a\in V_T,\beta\in (V_N)^*\) 且G不含\(\epsilon\) 產生式 模式:變量——>常量+純變量串 和CNF范式一樣的是:每一個CFG也都有對應的GNF

這里的多步推導 隱含意思(直接+間接)就是文法中幾乎可以說 不能含有\(A=>^*A\beta,A=>^*\alpha A \beta, …\) 這種文法。一旦含有則直接被判定為遞歸文法

步驟:

  • 生成式的替換(替換的目的是為 后面找到間接左遞歸做准備)

(截止這里,還沒有正真的進行消除左遞歸,只是將所有可能隱含的左遞歸,通過替換算法給"發掘"出來)

  • 消除直接左遞歸

先把不是左遞歸的部分copy過來;再給這些剛搞過來的產生式后面引入我們的新變量\(A'\) ;再以新的\(A'\)引出產生式,這些產生式的產生式體部分要么是原來遞歸產生式體的非遞歸部分 ,要么是原來遞歸產生式體的非遞歸部分 +\(A'\) 進行右遞歸!

先把剎車部分和新引入的寫出來;再由新引入的寫出 原來遞歸中的重復部分,以及遞歸重復部分連接新引入的

消除左遞歸的宏觀思路:

消除左遞歸之前,上圖中的\(\beta\)是一直到最后,才因替換而出現;消除左遞歸之后,上圖中的\(\beta\) 一開始很早就出現。

  • 消除間接左遞歸

替換的過程就是類似於解方程組代入法。通常第一條作為核心方程式,第二條用第一條表示;第三條用第二條和第一條表示。

上面最后一部分 是不完整的,因為只用了\(A_1\)代入,沒把\(A_2\)代入

我們代入的目的是形成直接左遞歸(暴露出原來隱含的左遞歸,而且是把已經知道的產生式代入(換句話說,序號小的產生式代入序號大的產生式),比如

  • 上面的 我們先看到\(A_1\) ,單個\(A_1\)形不成左遞歸;

    再看\(A_2\) ,我們的目的就是把\(A_1\) 代入到\(A_2\) 並且還要形成直接左遞歸的才帶入,於是有\(A_2->A_3A_1|A_2A_3b|ab\) 注意到此時有了直接左遞歸;我們用消除左遞歸的方式產生右遞歸:有 \(A_2->A_3A_1|ab|A_3A_1A_2'|abA_2',,, ,,A_2'->A_3b|A_3bA_2'\)

  • \(A_3\)發現 我們可能要代入兩次(由上面已知的\(A_1,A_2,A_2'\)) 先將\(A_1\)代入\(A_3\) \(A_3->A_2A_3A_2|aA_2|A_3A_3|a\) 再把\(A_2\)代入\(A_3\) 得到直接左遞歸形式:\(A_3->A_3A_1A_3A_2|A_3A_1A_2'A_3A_2|abA_3A_2|abA_2'A_3A_2|aA_2|A_3A_3|a\) 然后把這個暴露出直接左遞歸形式的產生式進行消除左遞歸。得到 \(A_3->abA_3A_2|abA_2'A_3A_2|aA_2|A_3A_3|abA_3A_2A_3'|abA_2'A_3A_2A_3'|aA_2A_3'|A_3A_3A_3',A_3'->A_1A_3A_2|A_1A_2'A_3A_2|A_1A_3A_2A_3'|A_1A_2'A_3A_2A_3'\)

正確的應該是:

\(A_3->A_2A_3A_2|aA_2|A_3A_3|a=\) 再把 遞歸部分產生式 可以替換的(本例是\(A_2\)) 用產生式再次替換,得:

\(A_3->A_3A_1A_3A_2|abA_3A_2|A_3A_1A_2'A_3A_2|abA_2'A_3A_2|aA_2|A_3A_3|a\)

經過這樣,就把所有的隱含左遞歸產生式 就給顯現出來了!

然后按照正常的 把直接左遞歸變右遞歸就行了。


CFG的化簡注意事項:

消除\(\epsilon\) 產生式 消除單產生式 消除無用符號

  1. 首先判斷原始CFG產生的語言中,有沒有\(\epsilon\) 因為我們有一條 【消除\(\epsilon\) 產生式】

也就是說我們化簡完了的CFG G,如果原來的產生式有\(\epsilon\) ,那么那化簡完由於沒有 \(\epsilon\) 產生式 ,所以得∪上\(\epsilon\) 句子(引入新的開始符號\(S'\));如果原來語言中就不含$\epsilon $ ,那按步驟化簡完即可。

  1. 判斷 變量 是否是可致空的,所謂 消除\(\epsilon\) 產生式 ,就是\(\epsilon\) 產生式代入這些變量,每一個變量都有兩種可能:是\(\epsilon\) ,不是\(\epsilon\) 。比如$A->aBc,B->\epsilon $ ,我們判斷B是可以為\(\epsilon\) 的,那么這兩條產生式就可以變為\(A->ac|aBc\)

    \(A->aBC,B->\epsilon,C->\epsilon\) 就可以變為\(A->aBC|aB|aC|a\) 這就是***消除\(\epsilon\) 產生式 *** [消\(\epsilon\) 產生式]

  2. 先識別哪些不是單位產生式,找到它!所謂消除單位產生式就是\(A->B,B->\alpha串\) ,直接替代 入B,B實際上沒用,得到\(A->\alpha串\)

    \(B->A,A->\alpha_1|\alpha_2|\alpha_3\) 變為 \(B->\alpha_1|\alpha_2|\alpha_3\) [消單產生式]

  3. 先判定變量是不是可生成的(每一個變量能夠推推推到終結符);再判定變量是可到達的(S變量能夠推推推到目前變量) [消無用符號]

  4. 化成喬姆斯基形式 我們的目的是把所有的產生式化成 \(A->BC,A->a\) 所以第一步,面對產生式體長度大於等於2的,能化成的,盡可能化成這種形式。比如:\(A->aAS,B->BbB\) 面對這種可以化成的,我們引進\(C->a,D->b\) 這樣就可以化成\(A->CAS,B->BDB\) (把常量、變量混雜的換成全部變量形式) 這樣換了以后,要么右部全部是變量,要么右部只有一個常量

    現在 把變量長度大於等於3的變量串 拆成變量長度是2的。比如:\(S->ASB\) 就可以拆成\(S->AE,E->SB\) ;\(B->SDS\)拆成\(B->SG,G->DS\) 完成! [化成喬姆斯基范式]

化成喬姆斯基范式CNF 接下來我們拿着CNF將其化為GNF,GNF用處還是相當大的,這由GNF的形式所決定 \(A->a\beta\) ,根據終結符\(a\) 我們可以消除不確定性,可以唯一的替換,避免回溯。

替換的目的是由已知推未知(低序號推高序號) 最終會是\(Z->Z\beta\) 這種形式

然后消除直接左遞歸算法。

上面搞完后,會有一個符合要求的GNF范式,我們從這個符合要求的GNF要求進行入手,進行回填,會發現一步步都會產生符合要求的\(GNF\) ,直到所有的GNF都完成!


免責聲明!

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



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