簡體   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