我在尝试做类似事情的同时阅读this question。那里给出的答案并没有解决我的问题。
我想使用访问语句来确定每个子树的“质量”,因此对于每个节点,我想要总结所有后代的质量。例如,访问步骤遇到此节点表达式,其中包含一个列表:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])
应该产生这个:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])[@mass=8]
所以我不只想过滤掉非节点,而是实际遍历它们。在我的访问语句中包含列表的情况不起作用(至少不是很明显),因为列表不能有注释。
有没有一种自然的方法可以将完整的注释信息传播到树上?
答案 0 :(得分:2)
如果具有容器子节点的节点数量不是很大,则第一个解决方案是精确且有用的:
x = \anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5]);
visit(x) {
case n:\anode(l) => n[@mass=(0 | it + e@mass | e <- l)]
}
(您可能还会在本地函数中抽象reducer表达式)
第二种解决方案是从节点类型中抽象出来,以防你有很多这样的:
visit(x) {
case n:str _(l) => n[@mass=(0 | it + e@mass | e <- l)]
}
如果注释嵌套得更深,第三种解决方案最有效,如列表列表等,并且您有许多不同类型的节点:
import Node;
int computeMass(list[value] x) {
mass = 0;
top-down-break visit(x) {
case node x : mass += (x@mass?) ? x@mass : 0;
}
return mass;
}
visit(x) {
case node n => n[@mass=computeMass(getChildren(n))]
}
我更喜欢第一种解决方案,因为它最精确。
请注意,我们正在使用&#34;关键字参数替换注释功能&#34;在不远的将来;具有几乎相同的语义,不同的语法,例如\cnode(mass=2)
\code()[@mass=2]
。使用新的关键字参数,您还可以为质量字段提供一个延迟计算的默认值,如下所示:
data N()
= anode(list[N] children, int mass=(0 | it + c.mass | c <- children))
| cnode(int mass=0)
;
anode([cnode(mass=1),cnode(mass=2)]).mass == 3