繁体   English   中英

ANTLR词法分析器规则即使不匹配也会消耗字符?

[英]ANTLR lexer rule consumes characters even if not matched?

我有一个反语言词典规则的奇怪副作用,并且我创建了一个(几乎)最小的工作示例来演示它。 在此示例中,我想匹配字符串[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');

词法分析器丢弃'0' ,并产生以下错误:

line 1:3 no viable alternative at character '.'
line 1:2 extraneous input '..' expecting INTEGER

这是因为当词法分析器遇到'0.' ,它将尝试创建FLOAT令牌,但不能。 而且由于没有其他规则可以重新匹配'0.' ,则会产生错误,并丢弃'0'并创建DOT令牌。

这就是ANTLR的词法分析器的工作原理:它不会回溯以匹配INTEGERDDOTS (请注意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');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM