私は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
;