antlr3删除带有子树的treenode [英] antlr3 remove treenode with subtree

查看:120
本文介绍了antlr3删除带有子树的treenode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用antlr3.4进行一些树到树的转换

i try to do some tree to tree transform with antlr3.4

(对于这个问题)关于布尔表达式的是"AND"和"OR"被允许绑定到n个表达式. 解析器阶段会创建类似这样的内容

It's (for this question) about boolean expressions were "AND" and "OR" are allowed to bind to n expressions. The parser stage creates something like this

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

不幸的是,存在"AND"和"OR"的AST节点仅绑定到一个表达式. (这没用,但是-规则,expr和orexpr被调用)

Unfortunately there are AST nodes for "AND" and "OR" that bind just to one expression. (Which is useless, but hey - rules andExpr and orExpr are invoked)

我试图将它们踢出(意思是,用它们的子节点替换它们),但是在树语法中却没有这样做. (顺便说一句:在纯Java中使用深度优先树遍历/修改,但这不是我的意图)

I tried to kick them out (mean, replace them by their subnodes) but fail to do so in a tree grammar. (BTW: Using a depth first tree traversal/modification in pure java works, but that's not my intention)

我尝试使用谓词,但似乎无法正确理解.

I tried to use predicates but i can't seem to get it right.

这是解析未经修改的流的语法

This is the grammar to parse the stream unmodified

 start  :  
   orExpr^   EOF!  
   ;

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

 andExpr  : 
   ^(AND unaryExpr+ )
   ; 

 notExpr:
   ^( NOT unaryExpr)    
   ;

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

我尝试了一个谓词来捕获一个子节点的情况,但是未能通过n> 1个未修改的情况

I tried a predicate to catch the one-subnode-case but fail to pass the n>1 case unmodified

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

任何想法如何正确执行?

Any Ideas how to do it right?

附带的是语法分析器语法,它几乎是相同的...

edit: Attached is the parser grammar which is pretty much the same...

 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
   ;

推荐答案

您可以直接在解析器中执行此操作.您确实需要创建更多解析器规则,以免在重写规则中混淆ANTLR(请参见内联注释):

You can do this directly in the parser. You do need to create some more parser rules as to not confuse ANTLR in the rewrite rules (see the inline comments):

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:

Parsing input like "a && b && c || d || f || g" will produce the following AST:

树语法如下:

tree grammar TWalker;

options {
  tokenVocab=T;
  ASTLabelType=CommonTree;
}

start 
 : expr
 ;

expr
 : ^(OR expr+)
 | ^(AND expr+)
 | ^(NOT expr)
 | ID
 ;

这篇关于antlr3删除带有子树的treenode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆