我使用ANTLR构建一个树(CommonTree),如下面的语言(语言:JAVA):
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());
答案 0 :(得分:3)
尝试这样的事情:
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
。
请注意,我选择CommonTree
和CommonToken
个对象,因为这些是默认的Token
和Tree
实现。如果您选择创建自己的Token
和/或Tree
,则可能会将CommonTree
和CommonToken
类子类化,在这种情况下,我的建议不会中断
CommonTree
只不过是CommonToken
的包装器,它包含一些额外的信息:父节点和子节点。这就是为什么我还要复制CommonToken
个对象的所有信息。
答案 1 :(得分:2)
我有同样的问题在dupTree()
上磕磕绊绊,这似乎已被弃用,然后Bart的发布,这引导我走向正确的方向。我最终得到了以下内容,它使用CommonTree
的构造函数接受CommonTree
- 从需要复制单个字段中抽象它。
private static CommonTree copyTreeRecursive(CommonTree original) {
CommonTree copy = new CommonTree(original); // Leverage constructor
if(original.getChildren() != null) {
for(Object o : original.getChildren()) {
CommonTree childCopy = copyTreeRecursive((CommonTree)o);
childCopy.setParent(copy);
copy.addChild(childCopy);
}
};
return copy;
}
注意:我坚持使用Bart的命名惯例。