2015-06-17 2 views
4

Я читал this question при попытке сделать что-то подобное. Ответ, данный там, не решает мою проблему.Доступ к _all_ нисходящим аннотациям узла в Rascal

Я хочу использовать заявление посещения, чтобы определить «массу» каждого поддерева, поэтому для каждого узла я хочу суммировать массы всех потомков. Например, шаг посещения который встречает это выражение узла со списком в нем:

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

должен дать это:

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

Так что я не хочу, чтобы отфильтровать не-узлы, но фактически пересекают их. Включение случая для списков в моем заявлении посещения не работает (по крайней мере, не очевидно), потому что списки не могут содержать аннотации.

Есть ли естественный способ распространения всей аннотации информации по дереву?

+0

Я думаю, вы думаете, что грамматики атрибутов? – jurgenv

+0

Да. Сначала я этого не понимал, но об этом я и думаю. Я прочитал [здесь] (http://www.homepages.cwi.nl/~paulk/publications/rascal-lncs.pdf), что Rascal обобщает функциональность инструментов грамматики атрибутов. Включает ли это вышеупомянутое? – Anson

+0

(или что-то подобное) – Anson

ответ

2

Это первое решение является точным и полезным, если число узлов с контейнерными детьми не так велико:

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

visit(x) { 
    case n:\anode(l) => n[@mass=(0 | it + [email protected] | e <- l)] 
} 

(Вы, вероятно, также абстрактное выражение редуктора в локальной функции)

Второе решение было бы абстрагироваться от типа узла, в случае, если у вас есть много из них:

visit(x) { 
    case n:str _(l) => n[@mass=(0 | it + [email protected] | e <- l)] 
} 

третье решение будет работать лучше в случае annotat ионы вложены еще глубже, так как в списках списков и т.д., и у вас есть много различных типов узлов:

import Node; 
int computeMass(list[value] x) { 
    mass = 0; 
    top-down-break visit(x) { 
    case node x : mass += ([email protected]?) ? [email protected] : 0; 
    } 
    return mass; 
} 

visit(x) { 
    case node n => n[@mass=computeMass(getChildren(n))] 
} 

Я предпочитаю очень первое решение, потому что это наиболее точные.

Обратите внимание, что мы заменяем функцию аннотаций на «параметры ключевых слов» в ближайшем будущем; с почти той же семантикой, различный синтаксис, например \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 
+0

BTW, приведенные выше решения суммируют _direct_ потомков. Вы также можете сделать _all_ потомков, используя оператор глубокого соответствия '/ node n', чтобы найти все вложенные узлы рекурсивно в редукторе, который итерации над дочерними элементами. – jurgenv

+0

Спасибо! Число конструкторов с детьми-контейнерами было большим, а также были прямые потомки, поэтому я выбрал третий вариант. Синтаксис «x has mass» не обнаружил аннотацию, когда я ее использовал. Надеюсь, вы не против, если я немного отредактирую код в вашем ответе. – Anson

+0

Благодарим за редактирование! – jurgenv

Смежные вопросы