我使用ANTLR来构建像follwing(语言:JAVA)的树(CommonTree):

  Parser.prog_return r = parser.prog();
  CommonTree t = (CommonTree) r.getTree();


现在,我需要传递“ t”作为参数,并进行一些更改而不影响原始树。但是,使用Java的指针无法完成此操作,因此我需要复制树。

我一直在互联网上搜索,发现的最隐蔽的东西是ASTFactory类的dupTree()方法。

任何建议或建议如何实现这一目标将不胜感激!

编辑

@Bart Kiers,谢谢您的回答,它绝对有效!

我看到您正在深度遍历树,并为每个被访问的节点创建一个CommonTree对象。

我的问题是,CommonToken和CommonTree之间是什么关系,这些属性有什么作用:

cTok.setCharPositionInLine(oTok.getCharPositionInLine());
cTok.setChannel(oTok.getChannel());
cTok.setStartIndex(oTok.getStartIndex());
cTok.setStopIndex(oTok.getStopIndex());
cTok.setTokenIndex(oTok.getTokenIndex());

最佳答案

尝试这样的事情:

public static CommonTree copyTree(CommonTree original) {
  CommonTree copy = new CommonTree(original.getToken());
  copyTreeRecursive(copy, original);
  return copy;
}

private static void copyTreeRecursive(CommonTree copy, CommonTree original) {
  if(original.getChildren() != null) {
    for(Object o : original.getChildren()) {

      CommonTree originalChild = (CommonTree)o;

      // get the token from the original child node
      CommonToken oTok = (CommonToken)originalChild.getToken();

      // create a new token with the same type & text as 'oTok'
      CommonToken cTok = new CommonToken(oTok.getType(), oTok.getText());

      // copy all attributes from 'oTok' to 'cTok'
      cTok.setLine(oTok.getLine());
      cTok.setCharPositionInLine(oTok.getCharPositionInLine());
      cTok.setChannel(oTok.getChannel());
      cTok.setStartIndex(oTok.getStartIndex());
      cTok.setStopIndex(oTok.getStopIndex());
      cTok.setTokenIndex(oTok.getTokenIndex());

      // create a new tree node with the 'cTok' as token
      CommonTree copyChild = new CommonTree(cTok);

      // set the parent node of the child node
      copyChild.setParent(copy);

      // add the child to the parent node
      copy.addChild(copyChild);

      // make a recursive call to copy deeper
      copyTreeRecursive(copyChild, originalChild);
    }
  }
}

...

// get the original tree
CommonTree tree = (CommonTree)parser.parse().getTree();

// create a copy of the tree
CommonTree copy = copyTree(tree);

// change the contents of the right node of the right node of the root
((CommonTree)tree.getChild(1).getChild(1)).getToken().setText("X");

System.out.println(tree.toStringTree());
System.out.println(copy.toStringTree());


会产生:

(&& a(|| b X))
(&& a(|| b c))


输入"a && (b || c)"。即,tree具有X,但是copy将具有原始内容:c

请注意,我选择CommonTreeCommonToken对象是因为它们是默认的TokenTree实现。如果选择创建自己的Token和/或Tree,则很有可能会将CommonTreeCommonToken类子类化,在这种情况下,我的建议不会被破坏。

CommonTree仅仅是CommonToken的包装,其中包含一些额外的信息:父节点和子节点。这就是为什么我还从CommonToken对象复制所有信息的原因。

10-07 21:33