访问Rascal中节点的_all_下游注释

时间:2015-06-17 20:03:10

标签: attributes rascal

我在尝试做类似事情的同时阅读this question。那里给出的答案并没有解决我的问题。

我想使用访问语句来确定每个子树的“质量”,因此对于每个节点,我想要总结所有后代的质量。例如,访问步骤遇到此节点表达式,其中包含一个列表:

\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])

应该产生这个:

\anode([\bnode()[@mass=1], \bnode()[@mass=2]], \cnode()[@mass=5])[@mass=8]

所以我不只想过滤掉非节点,而是实际遍历它们。在我的访问语句中包含列表的情况不起作用(至少不是很明显),因为列表不能有注释。

有没有一种自然的方法可以将完整的注释信息传播到树上?

1 个答案:

答案 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