2013-07-24 51 views
2

我在ANTLR 4中遇到了語義謂詞問題。我的語法在語法上是模棱兩可的,需要向前看一個標記來解決歧義。作爲一個例子,我想解析「2012年1月19日至晚上9點」作爲日期「2012年1月19日」,將解析器的下一個標記留在「直到」處。我想在解析器的下一個標記「7」處解析「1月19日,7日至9日」作爲日期「1月19日」。ANTLR4謂詞失敗忽略以下替代?

所以我需要看看第三個令牌,並採取或離開它。

我的語法片段是:

date 
    : month d=INTEGER { isYear(getCurrentToken().getText())}? y=INTEGER 
            {//handle date, use $y for year} 
    | month d=INTEGER   {//handle date, use 2013 for year} 
    ;            

當分析器上或者樣品輸入運行時,我得到這個消息:

line 1:9 rule date failed predicate: { isYear(getCurrentToken().getText())}? 

它永遠不會到第二規則的選擇,因爲(我」猜測)它已經讀取了一個額外的令牌。

有人可以告訴我如何做到這一點?

+0

一個解決方案是使用兩個解析器,第一個解析器沒有謂詞。它爲第一次輸入打印出「$ DATE(2012-1-19)直到晚上9點」,第二次輸入「$ DATE(2013-1-19),7到9:00」。但是如果出現這樣的其他歧義,這將成爲一個n分析器解決方案。 –

回答

3

在語法規則,ANTLR 4只在做決定左邊緣時使用謂詞。內聯謂詞,例如上面顯示的謂詞只有已驗證

以下修改會導致ANTLR在做出決定時評估謂詞,但顯然您需要修改它以使用正確的lookahead標記,而不是調用getCurrentToken()

date 
    : {isYear(getCurrentToken().getText())}? month d=INTEGER y=INTEGER 
           {//handle date, use $y for year} 
    | month d=INTEGER    {//handle date, use 2013 for year} 
    ; 

PS:如果month始終只有一個令牌長,然後_input.LT(3)應該提供你想要的令牌。

+0

謝謝。我認爲你的意思是LT(3),LA(3)給了我一個語法錯誤。這解決了我的問題。 –