2013-08-31 54 views
1

我正在使用Antlr 4與c#target。 這裏是我的語法的一個子集:如何在Antlr 4/c中控制錯誤處理和同步#

/* 
* Parser Rules 
*/ 
text : term+ EOF; 
term : a1 a2 a3; 
a1: .... 
... 
... 

我想接受有效的數據塊的(長期)S,當存在錯誤時我要尋找下一個有效期,並打印出這引起了整個文本用戶手動分析錯誤。

如何將輸入同步到下一個有效期限? 以及如何獲得被忽略的文本?

回答

4

您需要爲此創建自己的IAntlrErrorStrategy實現,然後將Parser.ErrorHandler屬性設置爲您的錯誤策略的實例。 ANTLRErrorStrategy接口的Java版本和默認實現DefaultErrorStrategy的文檔可能爲實現錯誤策略提供了有用的信息,但是我必須警告您,創建自定義錯誤策略是一個有限文檔的高級功能。預計實施者已經是ANTLR 4實施Adaptive LL(*)解析算法的專家(我們正在討論研究人員級的理解)。

+0

謝謝哈威爾先生,(這是第二次你回答我的兩個類似的問題,所以非常感謝你,但是,在這兩個問題上,你給了我一個非常一般的答案,我仍然找不到解決方案。) 如果我只是想得到忽略發生錯誤時的文本我怎麼能找到它? – Lio

+0

這裏沒有簡單的解決方案,它不是「非常一般的」。 ach時間我需要一些關於錯誤處理的特別的東西,我推出了我自己定製的解決方案,這個解決方案特定於我正在解析的特定語言*和*我開發的應用程序。 –

+0

在'DefaultErrorStrategy'文檔中,有一些關於[recover]的內容(http://www.antlr.org/api/Java/org/antlr/v4/runtime/DefaultErrorStrategy.html#recover(org.antlr.v4.runtime .Parser,%20org.antlr.v4.runtime.RecognitionException))方法說,恢復方法會消耗令牌,直到重新同步,我們才能收集消耗的令牌嗎? (我試圖擴展'DefaultErrorStrategy')。 – Lio

0

對於第一個問題(如何將輸入同步到下一個有效的術語?)我發現了一些有用的信息,使我得到了可接受的解決方案。

的Antlr生成用於先前語法下一子碼:

public TextContext text() { 
    TextContext _localctx = new TextContext(_ctx, State); 
    EnterRule(_localctx, 0, RULE_text); 
    int _la; 
    try { 
     EnterOuterAlt(_localctx, 1); 
     State = 49; 
     _errHandler.Sync(this); 
     _la = _input.La(1); 
     do { 
      State = 48; term(); 
      State = 51; 
      _errHandler.Sync(this); 
      _la = _input.La(1); 
     } while (_la==KEYWORD); 
     State = 53; Match(EOF); 
    } 
    catch (RecognitionException re) { 
     _localctx.exception = re; 
     _errHandler.ReportError(this, re); 
     _errHandler.Recover(this, re); 
    } 
    finally { 
     ExitRule(); 
    } 
    return _localctx; 
} 

呼叫 '_errHandler.Sync(本);'使解析器在輸入流中前進,試圖找到下一個有效的轉向(由於「term +」組件)。 要停止同步解析器在其他子規則接受「術語」規則」,我擴展DefaultErrorStrategy類爲下一個:

public class MyErrorStrategy : Antlr4.Runtime.DefaultErrorStrategy 
{ 
    public EventErrorStrategy() : base() 
    { } 

    public override void Sync(Antlr4.Runtime.Parser recognizer) 
    { 
     if(recognizer.Context is Dict.TextAnalyzer.DictionaryParser.TextContext) 
      base.Sync(recognizer); 
    } 
} 

然後將其提供給解析器:

parser.ErrorHandler = new MyErrorStrategy();