[英]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的詞法分析器的工作原理:它不會回溯以匹配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');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.