5

同じ開始を持つレクサールールを使用するにはどうすればよいですか?

私は2つの類似したレクサールール(同じ開始を持つ)を使用しようとしています:

TIMECONSTANT: ('0'..'9')+ ':' ('0'..'9')+;
INTEGER     : ('0'..'9')+;
COLON       : ':';

これが私のサンプル文法です:

grammar TestTime;

text      : (timeexpr | caseblock)*;

timeexpr  : TIME;
caseblock : INT COLON ID;

TIME      : ('0'..'9')+ ':' ('0'..'9')+;
INT       : ('0'..'9')+;
COLON     : ':';
ID        : ('a'..'z')+;

WS        : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};

テキストを解析しようとすると:

12:44
123 : abc
123: abc

最初の2行は正しく解析され、3行目はエラーを生成します。何らかの理由で、 '123:' ANTLRはTIMEとして解析します(そうではありません)。..

それで、そのような語彙素で文法を作ることは可能ですか?

私の言語では、大文字と小文字のブロックと日時定数の両方を使用するために、このようなルールを設定する必要があります。たとえば、私の言語では次のように書くことができます。

case MyInt of
  1: a := 01.01.2012;
  2: b := 12:44;
  3: ....
end;
4

2 に答える 2

6

一致するとすぐDIGIT+ ':'に、レクサーはこれの後に別のDIGITが一致することを期待しますTIMECONSTANT。これが発生しない場合、一致する別のレクサールールにフォールバックすることはできず、レクサーは、に一致するようDIGIT+ ':'に既に一致したものをあきらめることはありません。':'INTEGER

考えられる解決策は、オプションでルール':' DIGIT+の最後に一致し、一致したINTEGER場合はトークンのタイプを変更することです。

grammar T;  

parse
 : (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
 ;

INTEGER      : DIGIT+ ((':' DIGIT)=> ':' DIGIT+ {$type=TIMECONSTANT;})?;
COLON        : ':';
SPACE        : ' ' {skip();};

fragment DIGIT : '0'..'9';
fragment TIMECONSTANT : ;

入力を解析する場合:

11: 12:13 : 14

以下が印刷されます。

INTEGER         '11'
COLON           ':'
TIMECONSTANT    '12:13'
COLON           ':'
INTEGER         '14'

編集

あまり良くありませんが、動作します...

本当です。ただし、これはANTLRの欠点ではありません。私が知っているほとんどのレクサージェネレーターでは、そのようなTIMECONSTANTINTEGERおよびCOLONが存在する場合)を適切にトークン化する際に問題が発生します。ANTLRは少なくともレクサーでそれを処理する方法を容易にします:)

これをレクサーの代わりにパーサーで処理させることもできます。

time_const : INTEGER COLON INTEGER;
INTEGER    : '0'..'9'+;
COLON      : ':';
SPACE      : ' ' {skip();};

ただし、言語のレクサーが空白を無視する場合は、次のように入力します。

12 :    34

time_constもちろん、ルールにも一致します。

于 2012-04-05T17:18:27.767 に答える
1

ANTLRレクサーはバックトラックできません。つまり、TIMECONSTANTルールの「:」に達すると、ルールを完了する必要があります。そうしないと、例外がスローされます。述語を使用してコロンに続く数字の存在をテストすることにより、文法を機能させることができます。

TIMECONSTANT: ('0'..'9')+ (':' '0'..'9')=> ':' ('0'..'9')+;
INTEGER     : ('0'..'9')+;
COLON       : ':';

これにより、ANTLRは、TIMECONSTANTルールに含まれていると判断する前に、コロンの先を見るように強制されます。

于 2012-04-05T16:16:21.573 に答える