Earley 剖析器(Earley parser)
/ ER-lee /
和 CYK 一樣,Earley 剖析器處理任何上下文無關文法,但它不要求特殊的正規形式,而是直接在照寫的文法上工作,包括歧義文法,並巧妙地讓速度隨文法實際的複雜度調整。把它想成一個剖析器,在輸入的每個位置都保留一份「此刻我可能正進行到一半的所有規則」的清單,並逐詞符推進這些猜測。
Earley 由左到右掃描輸入,並對每個位置維護一組狀態,每個狀態是一條文法規則,附一個點標示其右側已匹配到多遠,再加上該匹配是從哪裡開始的。三個操作驅動它。預測(Predict):當點位於某非終端符號之前時,為該非終端符號的所有規則加入狀態,猜我們可能在此開始其中一條。掃描(Scan):當點位於某終端符號之前且該符號匹配下一個輸入詞符時,把點往後移過它。完成(Complete):當某規則的點抵達末端時,該規則已完成,於是回到它開始之處,推進當初等著它的那些點。若在最後一個詞符之後,有一條完成的起始符號規則橫跨整個輸入,該字串便被接受。因為它只追求與目前所見輸入一致的猜測,它從不在不可能的剖析上浪費力氣。
Earley 的吸引力在於它通用卻常常很快:對任意文法最壞情況 O(n^3),但對無歧義文法 O(n^2),對良好(類 LL 或類 LR)的文法則為線性 O(n),因此只有在文法要求時你才付出複雜度的代價。它也優雅地處理左遞迴,並還原歧義輸入的所有剖析。這正是 Earley 成為自然語言剖析、以及必須接受真正任意文法之工具最愛的原因;代價是比起在馴良文法上的專用 LR 剖析器,它有更多記帳工作與較慢的常數。
對 S -> S + S | num 與輸入 num + num,Earley 在位置 0 預測 S 的規則,掃描 num,完成 S,在 + 之後預測,掃描第二個 num,完成內層 S,最後完成橫跨整個輸入的 S -> S + S。點記法 S -> num . 記錄在每條規則中的進度。
Earley:以預測/掃描/完成推進帶點的規則;最壞 O(n^3),在良好文法上為線性。
Earley 對任何 CFG 都有效、且無需正規形式轉換,這點不同於 CYK,並讓成本隨文法調整。但對真實語言所用的行為良好文法,專用 LR 剖析器在實務上仍更快,所以 Earley 主要在無法迴避任意或歧義文法之處發光。