ANTLR4:如何用相同的规则匹配 kv 表达式
ANTLR4: how to match kv expression with same rule
我想解析以下语句:
键=值
- 键:[a-zA-Z] ([a-zA-Z0-9_-])*
- 值:[a-zA-Z] ([a-zA-Z0-9_-])*
解析器总是混淆,因为键和值具有相同的规则。
我的错误语法:
grammar MatchExpr;
prog: stat ;
stat: expr
;
expr : kv JOINER kv #joiner
| kv #condition
;
kv: KEY OP VALUE;
JOINER: '&';
KEY : [a-zA-Z] ([a-zA-Z0-9])*;
OP : '=';
VALUE : [a-zA-Z0-9];
WS : [ \t]+ -> skip ; // toss out whitespace
但另一种语法可以 运行 :
grammar MatchExpr;
prog: stat ;
stat: expr
;
expr : kv JOINER kv #joiner
| kv #condition
; kv: KV;
KV: [a-zA-Z] ([a-zA-Z0-9_-])* '=' [a-zA-Z0-9] ([a-zA-Z0-9._-])*;
JOINER: '&';
WS : [ \t]+ -> skip ; // toss out whitespace
为什么?
ANTLR 将始终为输入 foo
创建一个 KEY
标记。无论输入是否为 mu = foo
,也会创建 2 个 KEY
令牌(中间有一个 OP
令牌)。
这就是 ANTLR 词法分析器的工作原理。词法分析器不是由解析器“驱动”的。解析器是否尝试匹配 VALUE
标记并不重要,输入 foo
将始终是 KEY
标记。
这些是词法分析器创建标记的 2 条规则:
- 创建尽可能长的匹配项
- 如果有 2 个或更多的词法分析器规则匹配相同的字符,让第一个定义的“赢”
由于规则 2,您可以看到为什么 KEY
将为 foo
而不是 VALUE
创建。
要解决此问题,请执行以下操作:
kv : KEY OP value;
value : KEY | VALUE;
JOINER : '&';
KEY : [a-zA-Z] [a-zA-Z0-9]*;
VALUE : [a-zA-Z0-9]+ // matches an ID starting with a digit
OP : '=';
我想解析以下语句:
键=值
- 键:[a-zA-Z] ([a-zA-Z0-9_-])*
- 值:[a-zA-Z] ([a-zA-Z0-9_-])*
解析器总是混淆,因为键和值具有相同的规则。
我的错误语法:
grammar MatchExpr;
prog: stat ;
stat: expr
;
expr : kv JOINER kv #joiner
| kv #condition
;
kv: KEY OP VALUE;
JOINER: '&';
KEY : [a-zA-Z] ([a-zA-Z0-9])*;
OP : '=';
VALUE : [a-zA-Z0-9];
WS : [ \t]+ -> skip ; // toss out whitespace
但另一种语法可以 运行 :
grammar MatchExpr;
prog: stat ;
stat: expr
;
expr : kv JOINER kv #joiner
| kv #condition
; kv: KV;
KV: [a-zA-Z] ([a-zA-Z0-9_-])* '=' [a-zA-Z0-9] ([a-zA-Z0-9._-])*;
JOINER: '&';
WS : [ \t]+ -> skip ; // toss out whitespace
为什么?
ANTLR 将始终为输入 foo
创建一个 KEY
标记。无论输入是否为 mu = foo
,也会创建 2 个 KEY
令牌(中间有一个 OP
令牌)。
这就是 ANTLR 词法分析器的工作原理。词法分析器不是由解析器“驱动”的。解析器是否尝试匹配 VALUE
标记并不重要,输入 foo
将始终是 KEY
标记。
这些是词法分析器创建标记的 2 条规则:
- 创建尽可能长的匹配项
- 如果有 2 个或更多的词法分析器规则匹配相同的字符,让第一个定义的“赢”
由于规则 2,您可以看到为什么 KEY
将为 foo
而不是 VALUE
创建。
要解决此问题,请执行以下操作:
kv : KEY OP value;
value : KEY | VALUE;
JOINER : '&';
KEY : [a-zA-Z] [a-zA-Z0-9]*;
VALUE : [a-zA-Z0-9]+ // matches an ID starting with a digit
OP : '=';