2016-08-12 58 views
0

我創建了以下語法(請參閱它波紋管),當我分析以下字符串ANTLR4語法不承認20號

「計劃;的cron(\」 */3 * * * * 美國/紐約\「);'TestFile'yyyy-M-DD-HH-毫米;美國/紐約; 20"

避難所的錯誤消息

「行1:89:錯配的輸入'20'期待NUMBER「

。 奇怪的是,正如我的觀點NUMBER:[0-9] +;將允許「20」。我錯在哪裏?

問候, 弗拉基米爾

lexer grammar FileTriggerLexer; 

@header { 
} 

STEP 
: 
    '/' INTEGER 
; 

SCHEDULE 
: 
    'Schedule' 
; 

SEMICOLON 
: 
    ';' 
; 

ASTERISK 
: 
    '*' 
; 

CRON 
: 
    'cron' 
; 

MARKET_CRON 
: 
    'marketCron' 
; 

COMBINED 
: 
    'combined' 
; 

FILE_FEED 
: 
    'FileFeed' 
; 

LBRACKET 
: 
    '(' 
; 

RBRACKET 
: 
    ')' 
; 

PERCENT 
: 
    '%' 
; 

INTEGER 
: 
    [0-9]+ 
; 

MINUTES_INTERVAL 
: 
    [1-59] 
; 

HOURS_INTERVAL 
: 
    [0-23] 
; 

WEEK_DAYS_INTERVAL 
: 
    [1-7] 
; 

MONTH_INTERVAL 
: 
    [1-12] 
; 

DAYS_OF_MONTH_INTERVAL 
: 
    [1-31] 
; 

DASH 
: 
    '-' 
; 

NUMBER 
: 
    [0-9]+ 
; 



DOUBLE_QUOTE 
: 
    '"' 
; 

QUOTE 
: 
    '\'' 
; 

SLASH 
: 
    '/' 
; 

DOT 
: 
    '.' 
; 

COMMA 
: 
    ',' 
; 

UNDERSCORE 
: 
    '_' 
; 

ID 
: 
    [a-zA-Z] [a-zA-Z0-9]* 
; 



REGEX 
: 
    (
     ID 
     | DOT 
     | ASTERISK 
     | NUMBER 
     |PERCENT 
    )+ 
; 

WS 
: 
    [ \t\r\n]+ -> skip 
; // skip spaces, tabs, newlines 

/** 
* Define a grammar called Hello 
*/ 
grammar FileTriggerValidator; 

options 
    { 
    tokenVocab = FileTriggerLexer; 
} 

r 
: 
    (schedule 
    | file_feed)+ 
; 

expression 
: 
    schedule 
    | file_feed 
; 

file_feed 
: 
    file_feed_name SEMICOLON source_file SEMICOLON source_host SEMICOLON 
    source_host SEMICOLON regEx SEMICOLON regEx 
    (
     SEMICOLON source_host 
    )* 
; 

formatString 
: 
    source_host 
    (
     '%' source_host? 
    )* DOT source_host 
; 

regEx 
: 
    REGEX 
; 

source_host 
: 
    ID 
    (
     DASH ID 
    )* 
; 

file_feed_name 
: 
    FILE_FEED 
; 

source_file 
: 
    (
     ID 
     | DASH 
     | UNDERSCORE 
    )+ 
; 

schedule 
: 
    SCHEDULE SEMICOLON schedule_defining SEMICOLON file_name SEMICOLON timezone 

    (
     SEMICOLON NUMBER 
    )? 
; 

schedule_defining 
: 
    cron 
    | market_cron 
    | combined_cron 
; 

cron 
: 
    CRON LBRACKET DOUBLE_QUOTE cron_part timezone DOUBLE_QUOTE RBRACKET 
; 

market_cron 
: 
    MARKET_CRON LBRACKET DOUBLE_QUOTE cron_part timezone DOUBLE_QUOTE COMMA 
    DOUBLE_QUOTE ID DOUBLE_QUOTE RBRACKET 
; 

combined_cron 
: 
    COMBINED LBRACKET cron_list_element 
    (
     COMMA cron_list_element 
    )* RBRACKET 
; 

mic_defining 
: 
    ID 
; 

file_name 
: 
    (
     ID 
     | DOT 
     | QUOTE 
     | DASH 
    )+ 
; 

cron_list_element 
: 
    cron 
    | market_cron 
; 
// 

schedule_defined_string 
: 
    cron 
; 
// 

cron_part 
: 
    minutes hours days_of_month month week_days 
; 
// 

minutes 
: 
    MINUTES_INTERVAL 
    | with_step_value 
; 
// 

hours 
: 
    HOURS_INTERVAL 
    | with_step_value 
; 
// 

int_list 
: 
    INTEGER 
    (
     COMMA INTEGER 
    )* 
; 

interval 
: 
    INTEGER DASH INTEGER 
; 
// 

days_of_month 
: 
    DAYS_OF_MONTH_INTERVAL 
    | with_step_value 
; 
// 

month 
: 
    MONTH_INTERVAL 
    | with_step_value 
; 
// 

week_days 
: 
    WEEK_DAYS_INTERVAL 
    | with_step_value 
; 
// 

timezone 
: 
    timezone_part 
    (
     SLASH timezone_part 
    )? 
; 
// 

timezone_part 
: 
    ID 
    (
     UNDERSCORE ID 
    )? 
; 
// 

with_step_value 
: 
    (
     int_list 
     | interval 
     | ASTERISK 
    ) STEP? 
; 
// 

回答

1

你基本上取得了#1詞法錯誤。

Lexer規則已定義priority rules,在您的情況下,INTEGER規則優先於NUMBER。兩者具有相同的定義,因此您可以簡單地用INTEGER替換所有NUMBER事件。

請注意,您的*_INTERVAL規則定義並不意味着您的想法。例如,DAYS_OF_MONTH_INTERVAL(定義爲[1-31])將匹配1-31範圍內的一個數字,這意味着它將與1,23中的任何一個匹配,而沒有其他任何內容。 它受INTEGER規則的影響,就像您的NUMBER規則。

放棄所有這些*_INTERVAL規則,並保留只有規則INTEGER。記住lexing是一個獨立的過程,解析器對它沒有影響。不要試圖在語法中驗證你的cron表達式,你將有一段非常艱難的時刻。首先,解析你的文件,然後執行一個單獨的驗證通過結果。