ANTLR 语法未按预期工作。我究竟做错了什么?

ANTLR grammar not working as expected. What am I doing wrong?

我在下面有这个语法,用于实现 IN 运算符获取数字或字符串列表。

grammar listFilterExpr;

listFilterExpr: entityIdNumberListFilter | entityIdStringListFilter;

entityIdNumberProperty
    : 'a.Id'
    | 'c.Id'
    | 'e.Id'
    ;
    
entityIdStringProperty
    : 'f.phone'
    ;

listFilterExpr
    : entityIdNumberListFilter
    | entityIdStringListFilter
    ;

listOperator
    : '$in:'
    ;

entityIdNumberListFilter
 :  entityIdNumberProperty listOperator numberList
 ;

 entityIdStringListFilter
 : entityIdStringProperty listOperator stringList
 ;

 numberList: '[' ID (',' ID)* ']';

 fragment ID: [1-9][0-9]*;

 stringList: '[' STRING (',' STRING)* ']';
 
 STRING
: '"'(ESC | SAFECODEPOINT)*'"'
;

fragment ESC
   : '\' (["\/bfnrt] | UNICODE)
   ;
   
fragment SAFECODEPOINT
   : ~ ["\\u0000-\u001F]
   ;

如果我尝试解析以下输入:

c.Id $in: [1,1]

然后我在解析器中得到以下错误:

mismatched input '1' expecting ID

请帮我改正语法。

Update

我在我的项目的巨大语法文件中发现了下面的规则方式,它可能在匹配到 ID:

之前匹配 '1'
NUMBER
   : '-'? INT ('.' [0-9] +)?
   ;
fragment INT
   : '0' | [1-9] [0-9]*
   ;

但是,如果我在 NUMBER 之前写下我的 ID 规则,那么其他事情就会失败,因为它们已经匹配了 ID 而应该匹配 NUMBER

我该怎么办?

如 rici 所述:ID 不应该是 fragment。片段只能由其他词法分析器规则使用,它们永远不会自己成为标记(因此不能在解析器规则中使用)。

只需从中删除 fragment 关键字:ID: [1-9][0-9]*;

请注意,您还必须考虑空格。您可能想跳过它们:

SPACES : [ \t\r\n] -> skip;

... mismatched input '1' expecting ID ...

除了 ID 之外,似乎还有另一个词法分析器也匹配输入 1 并且定义在 ID 之前。在那种情况下,看看这个问答:

编辑

因为您的规则是这样排序的:

NUMBER
   : '-'? INT ('.' [0-9] +)?
   ;

fragment INT
   : '0' | [1-9] [0-9]*
   ;

ID
   : [1-9][0-9]*
   ;

词法分析器永远不会创建 ID 标记(只会创建 NUMBER 标记)。这就是 ANTLR 的工作原理:如果 2 个或更多词法分析器规则匹配相同数量的字符,则第一个定义的规则“获胜”。

首先,我认为 ID 规则只匹配数字是很奇怪的,但是,如果那是您要解析的语言,那没问题。在你的情况下,你可以这样做:

id     : POS_NUMBER;
number : POS_NUMBER | NEG_NUMBER;

POS_NUMBER : INT ('.' [0-9] +)?;
NEG_NUMBER : '-' POS_NUMBER;

fragment INT
   : '0' | [1-9] [0-9]*
   ;

然后在解析器规则中使用 id 而不是 ID。以及使用 number 而不是您现在使用的 NUMBER