0

ANTLRを理解するために、次の簡単な文法を使用しています。

grammar Example;
options {
language=Java;
}

ID  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT : '0'..'9'+
    ;
PLUS    :   '+';


ADDNUM  :   
    INT PLUS INT;

prog    :    ADDNUM;

入力に対してANTLRWorksで文法を実行しようとすると1+2、コンソールで次のエラーが発生します。

[16:54:08]解釈中...[16:54:08]2:0でのトークンのマッチングの問題
NoViableAltException('' @ [1:1:トークン:(ID | INT | PLUS | ADDNUM);])

誰かが私がどこで間違っているのか理解するのを手伝ってくれませんか?

4

1 に答える 1

1

progANTLRWorksの開始ルールとして指定しなかった可能性があります。そうすれば、それはすべて大丈夫です。

ただし、実際には、のように式に一致するレクサールールを作成するべきではありませんADDNUM。これはパーサールールである必要があります。

grammar Example;

prog    : addExpr EOF;
addExpr : INT PLUS INT;
ID      : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
INT     : '0'..'9'+;
PLUS    : '+';

ANTLRルール

パーサー、レクサー、またはフラグメントのルールを使用する場合の厳密なルールはありませんが、通常は次のように使用されます。

レクサールール

レクサールールは通常、言語の最小部分(文字列、数値、識別子、コメントなど)です。次のような入力からレクサールールを作成しようとすると、1+2問題が発生します。

  • そのトークンから何か意味のあるものを抽出したい場合(たとえば、それを評価する場合)、そのトークンから1つのトークンを作成した後、式全体のテキストが「接着」されるため、そのトークンの内容を分割する必要があります。
  • 間に空白があると、問題が発生します1 +   2

1+2は3つのトークンです:INTPLUSおよび別のINT

フラグメントルール

フラグメントルールは、「実際の」トークンのためにこのルールを使用したくない場合に使用されます。たとえば、次のレクサールールを使用します。

ID    : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
FLOAT : '0'..'9'+ '.' '0'..'9'+; 
INT   : '0'..'9'+;

上記のルールでは、'0'..'9'4回使用しているため、別のルールに配置できます

ID    : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+; 
INT   : DIGIT+;
DIGIT : '0'..'9';

DIGITただし、トークンを作成する必要はありませんDIGIT。他のレクサールールでのみ使用されるようにする必要があります。その場合、fragmentルールを作成できます。

ID    : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+; 
INT   : DIGIT+;
fragment DIGIT : '0'..'9';

これにより、トークンが存在しないことが保証さDIGITれます。したがって、パーサールールでこれを使用することはできません。

パーサールール

パーサールールはトークンを結合します。言語が構文的に有効であることを確認します(別名解析)。強調するために、パーサールールは他のパーサールールまたはレクサールールを使用できますが、フラグメントルールは使用できません。


ANTLR :簡単な例はありますか?

于 2012-02-13T22:11:22.110 に答える