匹配错误标记的 ParserRule

ParserRule matching the wrong token

我正在尝试学习一点 ANTLR4 并为某些 4GL 语言定义语法。

这是我得到的:

compileUnit
:
    typedeclaration EOF
;

typedeclaration
:
    ID LPAREN DATATYPE INT RPAREN
;

DATATYPE
:
    DATATYPE_ALPHANUMERIC
    | DATATYPE_NUMERIC
;

DATATYPE_ALPHANUMERIC
:
    'A'
;

DATATYPE_NUMERIC
:
    'N'
;

fragment
DIGIT
:
    [0-9]
;

fragment
LETTER
:
    [a-zA-Z]
;

INT
:
    DIGIT+
;

ID
:
    LETTER
    (
        LETTER
        | DIGIT
    )*
;

LPAREN
:
    '('
;

RPAREN
:
    ')'
;

WS
:
    [ \t\f]+ -> skip
;

我希望能够解析的内容:

测试 (A10)

我得到的:

typedeclaration:1:6: mismatched input 'A10' expecting DATATYPE

不过我可以写:

测试(A 10)

为什么我要在这里放一个白色space? LPAREN DATATYPE 本身就可以工作,所以中间不需要 space。 INT RPAREN 也在工作。 为什么在 DATATYPE 和 INT 之间需要 space?我对此有点困惑。 我猜它是匹配 ID,因为它是 "longest" 匹配,但必须有某种方法可以强制在这里变得更懒惰,对吧?

您应该忽略 ID 第一个位置的 'A' 和 'N' 聊天。正如@CoronA 注意到的那样,ANTLR 会尽可能长时间地匹配令牌(ID 'A10' 的长度超过 DATATYPE_ALPHANUMERIC 'A' 的长度)。另请阅读:。尝试使用以下语法:

grammar expr;

compileUnit
    : typedeclaration EOF
    ;

typedeclaration
    : ID LPAREN datatype INT RPAREN
    ;

datatype
    : DATATYPE_ALPHANUMERIC
    | DATATYPE_NUMERIC
    ;

DATATYPE_ALPHANUMERIC
    : 'A'
    ;

DATATYPE_NUMERIC
    : 'N'
    ;

INT
    : DIGIT+
    ;

ID
    : [b-mo-zB-MO-Z] (LETTER | DIGIT)*
;

LPAREN
    : '('
    ;

RPAREN
    : ')'
    ;

WS
    : [ \t\f]+ -> skip
    ;

fragment
DIGIT
    : [0-9]
    ;

fragment
LETTER
    : [a-zA-Z]
    ;

您也可以不受id限制地使用下面的语法。数据类型将比字母更早被识别。也不清楚:

grammar expr;

compileUnit
    : typedeclaration EOF
    ;

typedeclaration
    : id LPAREN datatype DIGIT+ RPAREN
    ;

id
    : (datatype | LETTER) (datatype | LETTER | DIGIT)*
    ;

datatype
    : DATATYPE_ALPHANUMERIC
    | DATATYPE_NUMERIC
    ;

DATATYPE_ALPHANUMERIC: 'A';
DATATYPE_NUMERIC:      'N';
// List with another Data types.
LETTER:                [a-zA-Z];

LPAREN
    : '('
    ;

RPAREN
    : ')'
    ;

WS
    : [ \t\f]+ -> skip
    ;

DIGIT
    : [0-9]
    ;