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
。
我在下面有这个语法,用于实现 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
:
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
。