即使不匹配,ANTLR词法分析器规则也会消耗字符吗?
问题描述:
我有一个antlr词法分析规则的一个奇怪的副作用,我创建了一个(几乎)最小的工作示例来演示它。 在这个例子中,我想匹配字符串[0..1]
例如。但是当我调试语法时,到达解析器的令牌流只包含[..1]
。第一个整数,无论它包含多少个数字总是被消耗,我不知道如何发生。如果我删除FLOAT
规则,一切都很好,所以我猜这个错误在某个地方。但由于它不应该匹配[0..1]
中的任何内容,所以我很困惑。即使不匹配,ANTLR词法分析器规则也会消耗字符吗?
我很乐意为任何可能出错的指针。这是我的例子:
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');
答
的'0'
词法分析器丢弃,下面的错误产生:
line 1:3 no viable alternative at character '.'
line 1:2 extraneous input '..' expecting INTEGER
这是因为当词法分析器遇到'0.'
,它试图创建一个FLOAT
令牌,但不能。并且由于没有其他规则可以回溯到匹配'0.'
,它会产生错误,丢弃'0'
并创建一个令牌DOT
。
这就是ANTLR的词法分析器的工作原理:它不会回溯匹配INTEGER
后跟DDOTS
(注意backtrack=true
仅适用于解析器规则!)。
在FLOAT
规则的内部,您必须确保当前面的双精度值为'.'
时,您会生成一个INTEGER
令牌。只有当单个'.'
后跟一个数字(('.' DIGIT)=>
部分)时,才可以通过添加句法谓词(('..')=>
部分)并生成FLOAT
令牌。看到下面的演示:
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');
现在,这是一个(至少对我而言)意想不到的行为。感谢这个全面的例子,我已经完成了并且正在运行:-) – Lichtblitz 2012-04-13 07:45:35
@Lichtblitz,不客气,是的,标记'..'(与INT-和FLOAT-令牌结合使用)很棘手! :) – 2012-04-13 08:54:33