我尝试使用antlr3.4进行一些树到树的转换
(对于这个问题)关于布尔表达式是“AND”和“OR”允许绑定到n个表达式。 解析器阶段创建类似这样的东西
(OR
(AND (expr1) (expr2) (expr3)
(OR (AND (expr4))
(AND (expr5))
(AND (expr6))
)
)
)
不幸的是,“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
;
我尝试了一个谓词来捕获一个子节点案例,但未能通过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
;
答案 0 :(得分: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
;