2016-08-12 48 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表达式,你将有一段非常艰难的时刻。首先,解析你的文件,然后执行一个单独的验证通过结果。