Greibach 正規形式(Greibach normal form)
/ Greibach: GRY-bahk /
想像有條規定:你說的每個句子都必須以一個真正的詞開頭,絕不能以待會兒再填的佔位符開頭。這樣每次你一開口,就有具體的東西出來,聽者理解你時就有真實進展。Greibach 正規形式(Greibach normal form, GNF)對文法施加這種紀律:每條規則都必須以產生一個真正的終端符號開頭,使每個推導步驟都消耗一個輸出符號。
若文法每條規則都具有形式 A -> a alpha,其中 a 是單一終端符號、alpha 是一個(可能為空的)僅含變數的字串,則該文法處於 GNF。所以右側總是以一個終端符號開頭,後接零個或多個非終端符號——中間絕無另一個終端符號,開頭絕無變數。每個不含空字串的上下文無關語言都有一個 GNF 文法;轉換通常先經過 CNF,再移除左遞迴並代入規則,使每個右側都以終端符號領頭。因為最左推導的每一步現在恰好輸出一個終端符號,長度為 n 的字串恰好在 n 步內被推導出來。
GNF 的重要性在於它是通往由上而下剖析與一個簡潔下推自動機構造的橋樑。「每步一個終端符號」的性質保證每一步都消耗一個終端符號,這避免了左遞迴造成的無限空轉,並讓 PDA 在展開最左變數的同時讀取下一個輸入符號——這本質上就是預測式、由上而下的剖析。誠實的告誡:轉換成 GNF 可能讓文法大幅膨脹(移除左遞迴與規則代入可能讓規則數乘上很大的倍數,通常比 CNF 更糟),而且如同所有正規形式轉換,它會重寫剖析樹,所以附帶的語意必須重新接上。
S -> aSb | ab 不在 GNF 中,因為 aSb 以終端符號 b 結尾。一個 GNF 版本引入變數 B -> b,並寫成 S -> a S B | a B,其中每個右側都以終端符號 a 開頭、其餘只有變數。推導 aabb:S => a S B => a a B B => a a b b,每步發出一個終端符號。
每條規則以一個終端符號領頭、其後只有變數——所以每個推導步驟恰好發出一個輸出符號。
GNF 與 CNF 描述相同的上下文無關語言;兩者都不更強大。它們是不同的工具:CNF 適合由下而上的表格剖析(CYK),GNF 適合由上而下的預測式剖析。GNF 轉換在文法大小上可能比 CNF 更昂貴。