访问 Rascal 节点的_all_下游注解
Accessing _all_ downstream annotations of a node in Rascal
我在尝试做类似的事情时阅读了 。那里给出的答案没有解决我的问题。
我想用访问语句来确定每个子树的'mass',所以对于每个节点我想对所有后代的质量求和。例如,一个访问步骤遇到了这个节点表达式,里面有一个列表:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])
应该产生这个:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])[@mass=8]
所以我不只是想过滤掉非节点,而是实际遍历它们。在我的访问语句中包含列表的案例不起作用(至少不明显),因为列表不能有注释。
有没有一种自然的方法可以将完整的注释信息传播到树上?
如果具有容器子节点的节点数不是很大,那么第一个解决方案是精确且有用的:
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))]
}
我更喜欢第一个解决方案,因为它最精确。
请注意,我们将在不久的将来用 "keyword parameters" 替换注释功能;具有几乎相同的语义,不同的语法,例如 \cnode(mass=2)
对应 \code()[@mass=2]
。使用新的关键字参数,您还可以为 mass 字段提供延迟计算的默认值,如下所示:
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
我在尝试做类似的事情时阅读了
我想用访问语句来确定每个子树的'mass',所以对于每个节点我想对所有后代的质量求和。例如,一个访问步骤遇到了这个节点表达式,里面有一个列表:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])
应该产生这个:
\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])[@mass=8]
所以我不只是想过滤掉非节点,而是实际遍历它们。在我的访问语句中包含列表的案例不起作用(至少不明显),因为列表不能有注释。
有没有一种自然的方法可以将完整的注释信息传播到树上?
如果具有容器子节点的节点数不是很大,那么第一个解决方案是精确且有用的:
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))]
}
我更喜欢第一个解决方案,因为它最精确。
请注意,我们将在不久的将来用 "keyword parameters" 替换注释功能;具有几乎相同的语义,不同的语法,例如 \cnode(mass=2)
对应 \code()[@mass=2]
。使用新的关键字参数,您还可以为 mass 字段提供延迟计算的默认值,如下所示:
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