2013-09-26 2 views
3

Я хочу создать дерево (используя Node или ADT), в котором каждый узел имеет аннотацию, указывающую обратно на родителя. Ниже приведен пример с простой связанной структуры данных списка:Аннотирование дерева ADT/Node с «родительскими» метками в Rascal

import util::Math; 
import IO; 
import Node; 

anno LinkedList [email protected]; 
anno int [email protected]; 

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 */ 
       [email protected] = 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 
] 

ответ

2

Дело в том, что данные Rascal неизменна, так что вы ничего не можете обновить используя назначение. Назначение просто даст вам новую привязку для cx с набором аннотаций, но не изменит исходное дерево.

Чтобы изменить исходное дерево, вы можете использовать либо => оператор для случая заявления, или insert заявление следующим образом:

case LinkedList x => x[@parent=...] // replace x by a new x that is annotated 

или:

case LinkedList x : { 
    ... 
    [email protected]= ...; 
    insert x; // replace original x by new x in tree 
} 

Некоторые другие наконечник, в Traversal.rsc вы можете найти функцию под названием getTraversalContext(), которая выдает список родителей текущего посещенного узла, если вызвана из тела корпуса:

import Traversal; 

visit (...) { 
    case somePattern: { 
     parents = getTraversalContext(); 
     parent = parents[1]; 
    } 
} 
+0

Это выглядит очень многообещающим, за исключением того, что я не могу импортировать модуль Traversal. Он не может быть найден в соответствии с затмением. – pancake

+0

После небольшого исследования я вижу разницу между последней версией git-репозитория и плагином eclipse. 'Traversal.rsc' отсутствует в плагине eclipse. Я предполагаю, что плагин eclipse с сайта обновления еще не имеет этой функции. Я попытался установить плагин с «неустойчивого» сайта обновлений, но он не работает: он требует 'org.eclipse.jetty.http 8.1.3', но его не найти. Я использую eclipse 3.7 для разработчиков RCP/RAP. – pancake

+0

Проблема решена после установки eclipse Juno (4.2) для разработчиков RCP/RAP. И я забыл поблагодарить вас за ваше решение. Большое спасибо, спасибо! Кроме того, я все время получаю корневой узел как родительский и любой другой индекс, чем -1 (например, 1 или -2). Мне нужен прямой родитель текущего оцениваемого узла. – pancake