ANTLR4语法不识别20作为NUMBER

时间:2016-08-12 11:36:46

标签: error-handling antlr4

我创建了以下语法(请查看下面的内容)当我解析后面的字符串

  

“Schedule; 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 个答案:

答案 0 :(得分:1)

你基本上犯了#1 lexer错误。

Lexer规则定义了priority rules,在您的情况下,INTEGER规则优先于NUMBER。两者都有相同的定义,因此您无论如何都可以简单地用NUMBER替换所有INTEGER出现。

请注意,您的*_INTERVAL规则定义并不代表您的想法。例如,DAYS_OF_MONTH_INTERVAL(定义为[1-31])将匹配范围1-31中的一位数,这意味着它将匹配1,{ {1}}或2,没有别的。 它被3规则遮蔽,就像您的INTEGER规则一样。

删除所有这些NUMBER规则,并仅保留 *_INTERVAL规则。请记住,lexing是一个独立的传递,解析器对它没有影响。不要试图在语法中验证你的cron表达式,你将度过一段非常艰难的时期。首先,解析您的文件,然后对结果执行单独的验证传递。