5

antlr lexerルールの奇妙な副作用があり、それを示すために(ほぼ)最小限の作業例を作成しました。この例では、たとえば文字列と一致させたいと思い[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');
4

1 に答える 1

6

'0'レクサーによって破棄され、次のエラーが生成されます。

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

これは、レクサーが に遭遇すると、トークン'0.'を作成しようとしますが、作成できないためです。FLOATまた、 match にフォールバックするルールが他にないため、エラーが発生し、トークンが'0.'破棄'0'されて作成されます。DOT

これは単純に ANTLR の字句解析器がどのように機能するかです: a にINTEGER続く aに一致するようにバックトラックしません (パーサー規則にのみ適用されることに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');
于 2012-04-13T07:18:08.600 に答える