先天歧義語言(inherently ambiguous language)
通常當一個文法歧義時你可以修補它——改寫規則,讓每個字串得到一種結構。但存在這樣的上下文無關語言,對它們而言這是徒勞的:無論你為它們寫什麼文法,「某個」字串總是會有不只一棵剖析樹。這種歧義不是你那個特定文法的瑕疵;它烤進了語言本身。這樣的語言稱為先天歧義語言。
形式上,若生成 L 的「每一個」上下文無關文法都是歧義的——根本不存在 L 的無歧義 CFG——則上下文無關語言 L 是先天歧義的。標準例子是 L = { a^i b^j c^k : i = j 或 j = k },即 a 的數量等於 b 的數量、或 b 的數量等於 c 的數量的那些字串。任何為它而寫的文法都必須以重疊的規則處理 i = j 的情形與 j = k 的情形,而 i = j = k 的字串(同時滿足兩者)無論文法怎麼寫,都被迫有兩個不同的推導。證明先天歧義確實很難,通常依賴細緻的計數論證(常透過 Ogden 引理)。
這之所以重要,是因為它標示了消除歧義所能達成之事的真實、永久的極限:對先天歧義語言,工程師慣用的「只要改寫文法以編碼優先序」這一招根本無法成功。所幸,真實程式語言的語法並非先天歧義的——語言設計者刻意保持它無歧義——所以這多半是理論邊界,而非日常障礙。別把「這個文法是歧義的」(往往可修補)與「這個語言是先天歧義的」(永不可修補)混為一談;它們是關於不同對象的不同陳述。
L = { a^i b^j c^k : i = j 或 j = k } 是先天歧義的:像 a^n b^n c^n 這樣的字串同時滿足兩個條件,任何 CFG 都被迫給它兩棵不同的剖析樹(一棵透過 i = j 看待,一棵透過 j = k 看待)。
先天歧義 = 該語言的「每一個」文法都歧義;任何改寫都永遠無法修補。
請區分單一文法的性質(歧義文法,往往可修補)與語言的性質(先天歧義,永不可修補)。真實程式語言的語法並非先天歧義的。