我有一个 antlr 词法分析器规则的奇怪副作用,并且我创建了一个(几乎)最小的工作示例来演示它。
在这个例子中我想匹配字符串[0..1]
例如。但是当我调试语法时,到达解析器的令牌流仅包含[..1]
。第一个整数,无论它包含多少位数字,总是会被消耗,我不知道这是如何发生的。如果我删除FLOAT
规则一切都很好,所以我猜错误就在该规则的某个地方。但因为它不应该匹配任何内容[0..1]
我很困惑。
我很乐意为我可能出错的地方提供任何指示。这是我的例子:
grammar min;
options{
language = Java;
output = AST;
ASTLabelType=CommonTree;
backtrack = true;
}
tokens {
DECLARATION;
}
declaration : LBRACEVAR a=INTEGER DDOTS b=INTEGER RBRACEVAR -> ^(DECLARATION $a $b);
EXP : 'e' | 'E';
LBRACEVAR: '[';
RBRACEVAR: ']';
DOT: '.';
DDOTS: '..';
FLOAT
: INTEGER DOT POS_INTEGER
| INTEGER DOT POS_INTEGER EXP INTEGER
| INTEGER EXP INTEGER
;
INTEGER : POS_INTEGER | NEG_INTEGER;
fragment NEG_INTEGER : ('-') POS_INTEGER;
fragment POS_INTEGER : NUMBER+;
fragment NUMBER: ('0'..'9');
The '0'
被词法分析器丢弃并产生以下错误:
line 1:3 no viable alternative at character '.'
line 1:2 extraneous input '..' expecting INTEGER
这是因为当词法分析器遇到'0.'
,它试图创建一个FLOAT
令牌,但不能。由于没有其他规则可以依靠来匹配'0.'
,它产生错误,丢弃'0'
并创建一个DOT
token.
这就是 ANTLR 词法分析器的工作原理:它不会回溯来匹配INTEGER
随后是一个DDOTS
(注意backtrack=true
仅适用于解析器规则!)。
在 - 的里面FLOAT
规则,你必须确保当双'.'
领先,你产生一个INTEGER
代币。您可以通过添加语法谓词(('..')=>
部分)并生产FLOAT
仅当单个令牌'.'
后面跟着一个数字(('.' DIGIT)=>
部分)。请参阅以下演示:
declaration
: LBRACEVAR INTEGER DDOTS INTEGER RBRACEVAR
;
LBRACEVAR : '[';
RBRACEVAR : ']';
DOT : '.';
DDOTS : '..';
INTEGER
: DIGIT+
;
FLOAT
: DIGIT+ ( ('.' DIGIT)=> '.' DIGIT+ EXP?
| ('..')=> {$type=INTEGER;} // change the token here
| EXP
)
;
fragment EXP : ('e' | 'E') DIGIT+;
fragment DIGIT : ('0'..'9');
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)