2016-09-28 132 views
1

這裏Antlr4不遵循備用路徑是我的代碼:當第二斷言失敗

@parser::members { 

public boolean twoDigitDay(String text) { 
    try { 
     int day = Integer.parseInt(text); 
     if (day >= 1 && day <= 31) 
     { 
      return true; 
     } 
    } 
    catch (Exception e) 
    { 

    } 
    return false; 
} 
public boolean twoDigitMonth(String text) { 
    try { 
     int day = Integer.parseInt(text); 
     if (day >= 1 && day <= 12) 
     { 
      return true; 
     } 
    } 
    catch (Exception e) 
    { 
    } 
    return false; 
} 

}

date  : day seperator month 
     | month seperator day 
     ; 

day    : dayTwoDigits ; 
month   : monthTwoDigit; 
monthTwoDigit : {twoDigitMonth(getCurrentToken().getText())}? TWO_DIGITS; 
dayTwoDigits : {twoDigitDay(getCurrentToken().getText())}? TWO_DIGITS; 
seperator : ('/'); 
ONE_DIGIT : [0-9]; 
TWO_DIGIT : ONE_DIGIT ONE_DIGIT 

這裏的問題: 輸入 - 12/29(它應該去一個月分隔符天因爲首先是失敗)。解析器在29處拋出No Viable Input ...因爲29不符合@member中定義的月份標準。在這種情況下,在29要進行月份檢查(1-12)之後,根據日期方法(1-31)通過12並且失敗。它應該回溯到根目錄並遵循第二條路徑,而不是在29例外情況下給出無可行輸入。

回答

0

讓我們將語義謂詞直接移動到date語法規則。

TWO_DIGIT : [0-9][0-9]; 

date 
    : {twoDigitDay(getCurrentToken().getText()) && twoDigitMonth(_input.LT(3).getText())}? 
     TWO_DIGIT '/' TWO_DIGIT # dayAndMonth 
    | {twoDigitMonth(getCurrentToken().getText()) && twoDigitDay(_input.LT(3).getText())}? 
     TWO_DIGIT '/' TWO_DIGIT # monthAndDay 
    ; 

當我們開始匹配規則date我們首先檢查dayAndMonth命名方案。只有第一位數字是正確的日期,第二位數字是正確的月份時,我們才匹配dayAndMonth(用_input.LT(3)標記表示)。否則,我們將匹配monthAndDay命名替代。

+0

嗨Quepas,這只是我日期語法的代碼片段。有很多其他案件可以處理大約100種日期。您提出的解決方案可能太複雜而無法實施。我主要關心的是如果沒有可行的替代例外,ANTLR爲什麼不去下一個規則並檢查?有什麼辦法可以強迫Antlr4檢查下一個規則嗎? – Shiva

+0

@Shiva嗨,知道我沒有任何好的解決方案。也許我會想出更多的東西:) – Quepas