(1 )不改變文法中原有的語法規則,僅加進一些語法的非形式規定。
例如,對於上例文法 g [ e ],不改變已有的 4 條規則,僅加進運算子的優先順序和結合規則,即 * 優先於 + ; + , * 服從左結合。這樣,對於文法 g [ e ]中的句子 i * i + i 只有唯一的一棵語法樹(見圖 2.6 ),從而避免了文法的二義性.
(2 )構造乙個等價的無二義性文法,即把排除二義性的規則合併到原有文法中,改寫原有的文法。
例如,對於上例文法 g [ e ],將運算子的優先順序和結合規則( * 優先於 + ; + , * 左結合)加到原有文法中,可構造出無二義性文法 g』 [ e ]如下:
e → e + t | t
t → t * f | f
f → ( e ) | i
則句子 i * i + i 只有唯一一棵語法樹,見圖 2.8 。
可見,改寫後的文法與原文法等價且為無二義性文法。此例告訴我們,對於由二義性文法描述的語言,有時可以找到等價的無二義性文法來描述它。
【例 2.15 】
定義某程式語言條件語句的文法 g 為
s →if b s
| if b s else s
| a (其他語句)
試證明該文法是二義性的,並消除它的二義性。
分析 該文法的句子 if b if b a else a 對應圖 2.9 中兩棵不同的語法樹。
圖 2.8 g』 的句子 i * i + i 的語法樹
圖 2.9 復合 if 語句的兩棵語法樹
所以該文法是二義性的。消除文法的二義性可採用下面兩種方法。
(1 )不改變已有規則,僅加進一項非形式的語法規定: else 與前面最接近的不帶 else 的 if相對應。這樣,文法 g 的句子 if b if b a else a 只對應唯一的一棵語法樹(見圖 2.9 ( a )),由此消除了二義性。
(2 )改寫文法 g 為 g』 :
s → s1 | s2
s 1 →if b s1 else s1 | a
s 2 →if b s |if b s1 else s2
這是因為,通過分析得知引起二義性的原因是 if-else 語句的 if 後可以是 if 型,因此改寫文法時規定 if 和 else 之間只能是 if-else 語句或其他語句。這樣,對改寫後的文法,句子 if b if ba
else a 只對應唯一的一棵語法樹,如圖 2.10 所示。
圖 2.10 g』 的復合 if 語句的語法樹
應該指出的是,文法的二義性和語言的二義性是兩個不同的概念。通常我們只說文法的二義性,而不說語言的二義性,這是因為可能有兩個不同的文法 g 和 g』 ,而且其中乙個是二義性的,另乙個是無二義性的,但卻有l ( g ) = l ( g』 ),即這兩個文法所產生的語言是相同的。而將乙個語言說成是二義性的,是指對它不存在無二義性的文法,這樣的語言稱為先天二義性的語言,例如 l = 便是這種語言。
人們已經證明,不存在乙個演算法,它能在有限步驟內確切地判定任給的乙個上下文無關文法是否為二義性文法,或它是否產生乙個先天二義性的上下文無關語言。
二義性 消除左遞迴
書是龍書 編譯器中常用的方法可以分為自頂向下和自底向上的。乙個是從語法分析樹的頂部開始向底部構造語法分析樹,乙個則是從葉子節點開始,逐漸向根結點構造,這兩種分析方法中,語法分析器的輸入總是照著從左向右。二義性 如果乙個文法可以為某個句子生成多棵語法分析樹,那麼他就是二義性的。例如例子id id id...
編譯原理 文法及其二義性(判定及消除)
學編譯原理時,會學到文法,老師在介紹完文法的相關定義後又介紹了文法的二義性,但是沒說到底是如何避免文法的二義性的。這篇博文就是我的學習結果 文法的二義性 如果文法g中的某個句子存在不只一棵語法樹,則稱該句子是二義性的。如果文法含有二義性的句子,則稱該文法是二義性的。我舉個例子,來說明文法的二義性及其...
多重繼承中二義性的消除
類a派生b和c,類d從b,c派生,如何將乙個類a的指標指向乙個類d的例項?解析 這道題實際上考查的是如何消除多重繼承引起的向上繼承二義性問題。程式 如下所示 class a class b public a class c public a class d public b,public c int...