字符串中的ANTLR匹配DateTIme

时间:2020-09-13 09:15:25

标签: c# antlr

我写了以下语法,用于从给定的字符串中解析DateTime

datetime:  INT SEPARATOR month SEPARATOR INT4 
        | INT SEPARATOR month SEPARATOR INT4;

month:
    JAN
    | FEB
    | MAR
    | APR
    | MAY
    | JUN
    | JUL
    | AUG
    | SEP
    | OCT
    | NOV
    | DEC;


STRING: [a-zA-Z][a-zA-Z]+;

NUMBER: [0-9]+;

INT4: DIGIT DIGIT DIGIT DIGIT;
INT: DIGIT+;
DIGIT: ['0'-'9'];
DQUOTE  : '"';
JAN: [Jj][Aa][Nn];
FEB: [Ff][Ee][Bb];
MAR: [Mm][Aa][Rr];
APR: [Aa][Pp][Rr];
MAY: [Mm][Aa][Yy];
JUN: [Jj][Uu][Nn];
JUL: [Jj][Uu][Ll];
AUG: [Aa][Uu][Gg];
SEP: [Ss][Ee][Pp];
OCT: [Oo][Cc][Tt];
NOV: [Nn][Oo][Vv];
DEC: [Dd][Ee][Cc];

SEPARATOR: '-';
WS: [ \n\t\r]+ -> skip;

当我尝试匹配以下字符串

new teatime at 23-SEP-2013 for Santosh Singh and 3 guests

我在ANTLR输出中收到以下错误

line 1:15 mismatched input '23' expecting INT

1 个答案:

答案 0 :(得分:2)

首先,DIGIT: ['0'-'9'];规则不正确,应为:DIGIT: [0-9];

每当您获得意外结果时,请先转储词法分析器正在创建的令牌,以查看它们是否是您希望解析器使用的令牌。对于您的语法,这将是以下标记:

STRING                    `new`
STRING                    `teatime`
STRING                    `at`
NUMBER                    `23`
SEPARATOR                 `-`
STRING                    `SEP`
SEPARATOR                 `-`
NUMBER                    `2013`
STRING                    `for`
STRING                    `Santosh`
STRING                    `Singh`
STRING                    `and`
NUMBER                    `3`
STRING                    `guests`

如您所见,有几处错误:

  1. 从未创建过INT个令牌,而您的解析器需要这样的令牌。这是因为以下规则(及其顺序):
NUMBER : [0-9]+;
INT4   : DIGIT DIGIT DIGIT DIGIT;
INT    : DIGIT+;
DIGIT  : [0-9];

对于输入3,规则NUMBERINTDIGIT可以匹配。只要ANTLR的词法分析器可以构造多个标记,该标记(词法分析器规则)首先定义“获胜”。因此,一个数字令牌或任何数量的数字令牌将始终成为NUMBER令牌。无论解析器是否尝试匹配任何这些标记,都将不会创建INT4INTDIGIT。词法分析器独立于解析器工作。您无能为力。

  1. 月份从未匹配,它们都是STRING令牌。与上述问题相同:"SEP"可以通过STRING规则和SEP规则进行匹配,但是由于STRING是在SEP之前定义的,首先定义为“胜利”的人。

将语法重新排序如下:

grammar T;

parse
 : (datetime | text)+ EOF
 ;

text
 : STRING
 | month
 | INT
 ;

datetime
 : INT SEPARATOR month SEPARATOR INT4
 | INT SEPARATOR month SEPARATOR INT4
 ;

month
 : JAN
 | FEB
 | MAR
 | APR
 | MAY
 | JUN
 | JUL
 | AUG
 | SEP
 | OCT
 | NOV
 | DEC
 ;

JAN : [Jj][Aa][Nn];
FEB : [Ff][Ee][Bb];
MAR : [Mm][Aa][Rr];
APR : [Aa][Pp][Rr];
MAY : [Mm][Aa][Yy];
JUN : [Jj][Uu][Nn];
JUL : [Jj][Uu][Ll];
AUG : [Aa][Uu][Gg];
SEP : [Ss][Ee][Pp];
OCT : [Oo][Cc][Tt];
NOV : [Nn][Oo][Vv];
DEC : [Dd][Ee][Cc];

STRING    : [a-zA-Z][a-zA-Z]+;
INT4      : DIGIT DIGIT DIGIT DIGIT;
INT       : DIGIT+;
DQUOTE    : '"';
SEPARATOR : '-';

WS: [ \n\t\r]+ -> skip;

fragment DIGIT : [0-9];

应该正确匹配您的输入。