2015-09-03 45 views
2

我爲布爾表達式創建了一個語法,現在我試圖實現訪問者來評估它。如何報告來自ANTLR 4訪客的錯誤?

有人告訴我們,不需要用語義分析來過度複雜語法詞法分析器和分析器規則,因爲從訪問者提供有意義的錯誤消息要好得多。

所以我試圖檢查訪問者的類型一致性,日期正確性等。我得到的驚喜是,除了拋出異常外,沒有辦法(至少我沒有看到它)報告訪問者的錯誤。如果我拋出異常,我將無法繼續進行表達式驗證並一次檢測到所有錯誤。另外,我必須捕捉所有解析異常類型(我應該如何知道它們?)。總而言之,異常拋出似乎不是正確的解決方案。

您可以給我一個方向如何計劃在訪問者遍歷期間報告表達式語義錯誤?

回答

5

由於您定義了訪問者,您可以創建並向其傳遞一個對象,它將向其報告錯誤。

簡單的例子:

public interface IErrorReporter 
{ 
    void ReportError(ParserRuleContext context, string error); 
} 
public class ValidationVisitor : YourLanguageBaseVisitor<Whatever> 
{ 
    private readonly IErrorReporter _errorReporter; 

    public ValidationVisitor(IErrorReporter errorReporter) 
    { 
     _errorReporter = errorReporter; 
    } 

    public override Whatever VisitSomeNode(YourLanguageParser.SomeNodeContext context) 
    { 
     if (context.GetText() != "expected") 
      _errorReporter.ReportError(context, "Invalid text"); 

     return Visit(context.someSubNode()); 
    } 
} 

然後驗證這樣的:

var parseTree = DoTheParsingStuff(); 

// Implement that one, store the errors in a list 
var errorReporter = new SimpleErrorReporter(); 

new ValidationVisitor(errorReporter).Visit(parseTree); 

if (errorReporter.Errors.Count > 0) 
{ 
    // Display errors 
} 

ParserRuleContext可能是有用的定位發生錯誤(行/列等),但否則你可以實現任何適合你的錯誤報告需求的東西


旁註:如果您計劃有許多遊客,然後building an AST然後基於在校驗可能是從長遠來看是有利的。你需要決定它是否值得。

+0

謝謝你的回答。這是一個選項。你知道這是否是正確的做法或只是一種解決方法?正如我所看到的,Lexer和Parser具有用於報告錯誤的通用錯誤監聽器機制。我很驚訝訪客不。 –

+0

這是我所做的簡化版本,它工作得很好。沒有*標準*方式,因爲您可以隨意在訪客/聽衆中做任何你想做的事情。詞庫/解析器需要錯誤報告機制,但訪問者和聽衆在一般情況下不需要這種機制。 –

+1

另外值得注意的是,Lexer和Parser只報告語法錯誤。聽衆和訪問者可以通過檢查當前上下文,以前的值等來檢查語法正確的輸入是否在語義上有效 - 例如,國家代碼有兩個字母,但是「XX」是有效的國家代碼?這是一個我們開展業務的國家嗎?等等 –