遞歸下降的語法分析程序如何進行錯誤恢復?

以EBNF描述的PL0為例,使用遞歸下降的語法分析方法進行分析,在檢測到一個語法錯誤後,如何跳過儘可能少的代碼,繼續進行語法分析?具體的實現形式如何用程序設計語言組織?


手寫的遞歸下降程序恢復起來是很蛋疼的,因為你只有局部的信息,缺少全局的信息(主要體現在你不知道調用你現在這個函數的是誰,但這是很重要的)。所以你只能採取一些簡單的策略,譬如說一定要有分號但是輸入的token不是分號,那就假裝他有,等等。

如果是General-LR的話就簡單多了。首先你先得到一個最長的合法前綴(把其他提前發生錯誤的分支簡單的丟掉就可以),然後看一下下面的那個token,肯定是錯誤的token了。於是你就可以模擬跳過這個token,或者在token前面插入一些別的token(可以根據文法來插入,又可以產生多個分支,General-LR天生就支持這麼做,容易得很),如果插入的token超過了一定數量就放棄,然後看看哪種做法錯誤恢復的代價最小,然後就使用這個恢復的方法繼續往下分析。

雖然這個演算法是很健壯的,但是因為錯誤恢復的代價的計算仍然是局部的,他不會參考你後面輸入的一堆token的內容,所以在有限的情況下會導致你恢復了這個錯誤之後,後面接著產生大量的錯誤。所以如果你使用IDE來編輯代碼,你會發現前面一旦出現了一些離譜的錯誤,到後面整個智能提示都亂掉了。

所以我覺得體驗好的方法,應該是讓IDE在編寫代碼的時候不斷地編譯,然後提示你第一個錯誤出現在哪裡,就地修改。不要等到編譯的時候才來告訴你一大堆東西。Visual Studio 2013很好的實現了這個功能,可惜有些時候intellisense的錯誤跟cl.exe的錯誤不一樣。


簡單的處理,似乎可以在statement、block等函數中嘗試捕獲parse異常。如果發現異常的話,扔掉一系列token,直到遇到";"、"}"等synchronizing word,再返回一個無效的parse結果。


推薦閱讀:

模板編程如何引入類型是否存在條件???
能否通過對編譯器或者編譯環境的限制來應對木馬或者病毒呢?
如何構造上下文無關文法?
現代C++編譯器是否會根據debug期間運行所得的信息來進行優化?
有沒有介紹LLVM的書籍可以推薦?最好是中文的

TAG:計算機 | 編譯原理 | 編譯器 | 語法分析 |