1

レクサーを考えると

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

文法を考えると

var_def: type=ID vname=ID ASSIGN expr       
   -> ^(VARDEF $type $vname expr) 
   ; 

オプション付き

options
{
  language=CSharp3; 
  output=AST;
}

とコードを与えられた

int i = 0

すべてが正常に動作します。

ただし、割り当てでのNAMEの使用を許可したい場合(別のオブジェクトを参照)

var_def
  : type=(NAME|ID) vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

実行時にRewriteEmptyStreamExceptionが発生します

Antlr.Runtime.Tree.RewriteEmptyStreamException:トークンタイプ

Antlr.Runtime.Tree.RewriteRuleElementStream.NextCore()のc:\ dev \ stringtemplate_main \ antlr \ antlr3-main \ runtime \ CSharp3 \ Sources \ Antlr3.Runtime \ Tree \ RewriteRuleElementStream.cs:行200

Antlr.Runtime.Tree.RewriteRuleTokenStream.NextNode()のc:\ dev \ stringtemplate_main \ antlr \ antlr3-main \ runtime \ CSharp3 \ Sources \ Antlr3.Runtime \ Tree \ RewriteRuleTokenStream.cs:62行目

文法を使って、もう少し調査を行う

var_def
  : type=NAME vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

私は

Antlr.Runtime.Tree.RewriteEarlyExitException:タイプ'Antlr.Runtime.Tree.RewriteEarlyExitException'の例外がスローされました。

4

1 に答える 1

1

'i'

int i = 0

常にIDトークンになります。IDとは両方ともNAME単一FRAGIDのに一致し、IDはの前に定義されてNAMEいるため、トークンは存在しませんNAME(単一の場合FRAGID)。常にIDトークンになります。

これが機能しないのはそのためです。

var_def
  : type=NAME vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

パーサーが特定の時間に一致させようとしているトークンに応じて、レクサーがトークンを作成しないことを理解する必要があります。レクサーはパーサーとは独立して機能します。

括弧で囲まれたトークン/ルールのグループへのラベルの割り当ては避けてください。それ以外の:

var_def
  : type=(NAME|ID) vname=ID ASSIGN expr -> ^(VARDEF $type $vname expr) 
  ;

これを行う:

var_def
 : type ID ASSIGN expr -> ^(VARDEF type ID expr) 
 ;

type
 : NAME
 | ID
 ;
于 2012-08-28T08:11:30.990 に答える