1

私はantlr3.4でツリーからツリーへの変換をしようとしています

それは(この質問のために)ブール式が「AND」と「OR」がn個の式にバインドできることについてです。パーサーステージはこのようなものを作成します

 (OR 
   (AND (expr1) (expr2) (expr3) 
     (OR (AND (expr4))
         (AND (expr5))
         (AND (expr6))
     )
   )
 )

残念ながら、1 つの式だけにバインドする「AND」と「OR」の AST ノードがあります。(これは役に立ちませんが、ちょっと - ルール andExpr と orExpr が呼び出されます)

私はそれらを追い出そうとしました (つまり、それらをサブノードに置き換えます) が、ツリー文法ではそうできませんでした。(ところで:純粋なJavaで深さ優先のツリートラバーサル/変更を使用することはできますが、それは私の意図ではありません)

述語を使用しようとしましたが、正しく取得できないようです。

これは、変更されていないストリームを解析するための文法です

 start  :  
   orExpr^   EOF!  
   ;

 orExpr       :  
   ^(OR  r+=andExpr+ )   -> ^(OR $r)
   ;

 andExpr  : 
   ^(AND unaryExpr+ )
   ; 

 notExpr:
   ^( NOT unaryExpr)    
   ;

 unaryExpr : 
   .+  // it gets more complicated below this
   ;

one-subnode-case をキャッチする述語を試みましたが、変更されていない n>1 ケースを渡すことができませんでした

 orExpr @init { int N = 0; }
   :  
   ( ^(OR  (r+=andExpr {N++;})+ )  {N==1}? -> $r) 
   ;

それを正しく行う方法はありますか?

編集:ほとんど同じパーサー文法が添付されています...

 start 
   :  '('! orExpr^  ')'! EOF!        ;
 orExpr
   : a+=andExpr (  OR_T a+=andExpr )*  -> ^(OR  $a+ )  // 'AND' and 'OR' are multivalent
   ;

 andExpr
   : u+=unaryExpr ( AND_T u+=unaryExpr )* -> ^(AND $u+ )
   ; 

 notExpr
   : NOT_T unaryExpr -> ^( NOT unaryExpr)   
   ;

 unaryExpr
   : '('!  orExpr ')'! // -> ^( BRACE orExpr), brace not needed in the ast (but needed for propper parsing)
   |   notExpr
   |   internal^  // internal is very complex in itself
   ;
4

1 に答える 1

1

これは、パーサーで直接行うことができます。書き換えルールでANTLRを混同しないように、さらにいくつかのパーサールールを作成する必要があります(インラインコメントを参照)。

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

start 
 : orExpr EOF! {System.out.println($orExpr.tree.toStringTree());}
 ;

orExpr
 : (andExpr2 -> andExpr2) ((OR andExpr)+ -> ^(OR andExpr2 andExpr+))?
 ;

// You can't use `andExpr` directly in the `orExpr` rule otherwise the rewrite
// rule `-> ^(OR ... )` gets confused.
andExpr2 : andExpr;

andExpr
 : (notExpr2 -> notExpr2) ((AND notExpr)+ -> ^(AND notExpr2 notExpr+))?
 ; 

notExpr2 : notExpr;

notExpr
 : NOT^ notExpr
 | atom  
 ;

atom
 : '(' orExpr ')' -> orExpr
 | ID
 ;

OR    : '||';
AND   : '&&';
NOT   : '!';
ID    : 'a'..'z'+;
SPACE : ' ' {skip();};

のように入力を解析"a && b && c || d || f || g"すると、次のASTが生成されます。

ここに画像の説明を入力してください

編集

ツリーの文法は次のようになります。

tree grammar TWalker;

options {
  tokenVocab=T;
  ASTLabelType=CommonTree;
}

start 
 : expr
 ;

expr
 : ^(OR expr+)
 | ^(AND expr+)
 | ^(NOT expr)
 | ID
 ;
于 2012-10-18T19:06:21.770 に答える