如何構造上下文無關文法?

L3 = {w1cw2cw3|w1,w2,w3 ∈ {a, b} and the number of a』s in w1 is equal to the

number of b』s in w2}.

求L3的上下文無關文法。不需要答案,求大神指導一下解題方法。


先明確一下題意:應該是w_1,w_2,w_3 in {a,b}^*吧,要是{a,b}的話枚舉一下語言L_3的所有串就行了……

顯然w_3在這裡沒什麼用,我們只需構造出w_1cw_2,然後接上cw_3就行,也即:

S 
ightarrow S_1cS_2

其中S_1用於生成生成語言L_1 = {w_1cw_2 | 	ext{# of aS_2用於生成w_3,也即Sigma^* = {a, b}^*。然後分別構造S_1S_2

先說S_2(因為它簡單):S_2其實是個正則文法,對應的正則表達式是(0|1)^*,既然我們想要一個上下文無關文法,那就給它轉成左線性文法好了:S_2  
ightarrow  S_2a|S_2b|a|b。這一步構造是顯而易見的。

然後構造S_1。首先要明確的一點是CFG的能力:可以對兩項進行計數和比較。這說明CFG是有能力構造出語言L_1的。可是到底怎麼計數呢?方法就是給兩邊對稱地添加元素。先看三個例子:

(1)迴文串:X 
ightarrow aXa|bXb|epsilon|a|b

(2)括弧配對:P 
ightarrow (P) | PP|epsilon

(3){a^nb^n|nin mathbb{N}}T 
ightarrow aTb | epsilon

這下明白了吧?要讓w_1中的a和w_2中的b個數相等,就要:每次給S_1左邊添加一個a,就右邊添加一個b。不過考慮到w_1中的b和w_2中的a是不算數的,上面那句話可以改成:每次給S_1左邊添加一個僅包含一個a的串,就在右邊添加一個僅包含一個b的串

形式化地寫下來,就是:S_1 
ightarrow A_1S_1B_1|c,其中A_1是僅包含一個a的串,B_1是僅包含一個b的串。

至於A_1, B_1怎麼構造就不講了吧,非常簡單,它們都是正則文法而已。

當然,上面那個文法是有歧義的,要改成無歧義的好像還挺難=。=不過不要緊,它又沒讓你構造無歧義文法或者證明這個語言是固有歧義的【攤手】


S1-&>A1S1B1|c

A1-&>A1a|A1ab|A1ba|E

B1-&>B1b|B1ba|B1ab|E

(E為空集)

S1是不是這樣構造的?

S2-&>S2a|S2b|E 我覺得S2應該可以生成空集吧


推薦閱讀:

現代C++編譯器是否會根據debug期間運行所得的信息來進行優化?
有沒有介紹LLVM的書籍可以推薦?最好是中文的
計算機是怎麼區分int類型和float類型的數據的?
編譯器為什麼在一次編譯過程中要儘可能的發現所有錯誤?
你覺得編譯程序中使用的關鍵技術都有哪些應用方向?請詳細說明。

TAG:編程語言 | 編程 | 計算理論 | 編譯原理 | 編譯器 |