2013-08-06 57 views
2

在使用ANTLR4時,我一直回到同樣的問題 - 如何在解析器中實現算法規則驗證。ANTLR4:通常可以驗證解析器規則的各個部分嗎?

例如,我需要解析器在匹配規則之前驗證寫入「月日年」的日期的「年」部分。我已經學會了,我可以用這個謂詞如下操作:

date : 
    {isYear(_input.LT(3).getText())}? 
     month day=INTEGER year=INTEGER  { ... } 

但是這種解決方案是不一般,因爲它取決於規則month始終是一個令牌長。

我想我發現瞭解決這個問題的方法,通過改變規則,以這樣的:

date : month day=INTEGER yearInt  { ... } ; 

yearInt returns [int i] 
    : {isYear(_input.LT(1).getText())}? 
      yr=INTEGER     { $i = $yr.int; } 
    ; 

不幸的是,這個語法通過「7月11日6」作爲一個日期,即使isYear("6")失敗。當我通過XXParser.java的ANTLR生成的代碼追查yearInt(),我把它稱之爲

throw new FailedPredicateException(this, "isYear(_input.LT(1).getText())"); 

但隨後的代碼進行,並接受yearInt()反正。

這是一個ANTLR錯誤還是我的錯誤?是否有一種「適當」的方式來編寫需要驗證規則部分的語法?

回答

1

嘗試

date : 
    month day=INTEGER year=INTEGER {isYear($year)}?<fail="A sensible error msg"> { ... } 
; 

date : 
    month day=INTEGER year=INTEGER {if (! isYear($year)) 
             notifyErrorListeners("A sensible error msg"); 
            }  
    { ... } 
; 

其中之一將產生更多的有意義的錯誤消息。 notifyErrorListeners()建立錯誤,但讓解析「成功」,直到正在進行的解析。 {isYear($一年)}?將會失敗,並且會更多地尋找比賽。

我承認我沒有真正嘗試過這段代碼。也許你需要$ year.text,我不確定失敗選項和notifyErrorListeners()在C#版本和Java版本中是否有效。

George

相關問題