我想创建一个树(使用Node
或ADT
),其中每个节点都有一个指向其父节点的注释。下面是一个简单的链表数据结构示例:
import util::Math;
import IO;
import Node;
anno LinkedList LinkedList@parent;
anno int LinkedList@something;
data LinkedList = item(int val, LinkedList next)
| last(int val)
;
public LinkedList linkedList = item(5,
item(4,
item(3,
item(2,
last(1)[@something=99]
)[@something=99]
)[@something=99]
)[@something=99]
)[@something=99];
public LinkedList addParentAnnotations(LinkedList n) {
return top-down visit (n) {
case LinkedList x: {
/* go through all children whose type is LinkedList */
for (LinkedList cx <- getChildren(x), LinkedList ll := cx) {
/* setting the annotation like this doesn't seem to work */
cx@parent = x;
// DOESN'T WORK EITHER: setAnnotation(cx, getAnnotations(cx) + ("parent": x));
}
}
}
}
执行addParentAnnotations(linkedList)
会产生以下结果:
rascal>addParentAnnotations(linkedList);
LinkedList: item(
5,
item(
4,
item(
3,
item(
2,
last(1)[
@something=99
])[
@something=99
])[
@something=99
])[
@something=99
])[
@something=99
]
答案 0 :(得分:2)
事实是Rascal数据是不可变的,因此您无法使用赋值更新任何内容。赋值将只为您提供带有注释集的cx
的新绑定,但不会更改原始树。
要更改原始树,您可以使用=>
运算符作为case语句,也可以使用insert
语句,如下所示:
case LinkedList x => x[@parent=...] // replace x by a new x that is annotated
或:
case LinkedList x : {
...
x@parent= ...;
insert x; // replace original x by new x in tree
}
在Traversal.rsc
库中,您可以找到一个名为getTraversalContext()
的函数的其他提示,如果从案例正文中调用,则会生成当前访问过的节点的父项列表:
import Traversal;
visit (...) {
case somePattern: {
parents = getTraversalContext();
parent = parents[1];
}
}