Опитвам се да направя трансформация от дърво към дърво с antlr3.4
Става въпрос (за този въпрос) за булеви изрази, когато "И" и "ИЛИ" са разрешени да се свързват с n израза. Етапът на анализатора създава нещо подобно
(OR
(AND (expr1) (expr2) (expr3)
(OR (AND (expr4))
(AND (expr5))
(AND (expr6))
)
)
)
За съжаление има AST възли за "И" и "ИЛИ", които се свързват само с един израз. (Което е безполезно, но хей - правилата andExpr и orExpr се извикват)
Опитах се да ги изгоня (което означава, да ги заменя с техните подвъзли), но не успях да го направя в дървовидна граматика. (BTW: Използването на обхождане/модификация на първо дърво в дълбочина в чиста Java работи, но това не е моето намерение)
Опитах се да използвам предикати, но изглежда не мога да го разбера правилно.
Това е граматиката за анализиране на потока непроменен
start :
orExpr^ EOF!
;
orExpr :
^(OR r+=andExpr+ ) -> ^(OR $r)
;
andExpr :
^(AND unaryExpr+ )
;
notExpr:
^( NOT unaryExpr)
;
unaryExpr :
.+ // it gets more complicated below this
;
Опитах предикат, за да хвана случая с един подвъзел, но не успях да предам непроменен случай 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
;