ANTLR 匹配字符串中的 DateTIme

ANTLR Match DateTIme in String

我编写了以下用于从给定字符串解析 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

首先,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 的词法分析器可以构造超过 1 个标记时,首先定义的标记(词法分析器规则)“获胜”。因此,单个数字令牌或任意数量的数字令牌将始终成为 NUMBER 令牌。 INT4INTDIGIT 将永远不会被创建,无论解析器是否试图匹配这些标记中的任何一个。词法分析器独立于解析器工作。你对此无能为力。

  1. 月份永远不会匹配,它们都是 STRING 标记。与上面的问题相同:"SEP" 可以通过 STRING 规则和 SEP 规则匹配,但是由于 STRINGSEP 之前定义,定义第一个“获胜”的人。

像这样重新排序语法:

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];

应该正确匹配您的输入。