АНТЛР дублирует дерево - PullRequest
2 голосов
/ 21 июля 2011

Я использую ANTLR для построения дерева (CommonTree), например, follwing (язык: JAVA):

  Parser.prog_return r = parser.prog();
  CommonTree t = (CommonTree) r.getTree();

Теперь мне нужно передать «t» в качестве параметра и внести некоторые изменения, не затрагивая исходное дерево. Однако, с указателем Java, это не могло быть сделано, поэтому мне нужно продублировать дерево.

Я искал в интернете, что я нашел, так это метод dupTree () класса ASTFactory.

Буду признателен за любые предложения или советы о том, как этого добиться!

EDIT

@ Барт Киерс, спасибо за ваш ответ, он абсолютно работает!

Я вижу, что вы сначала проходите глубину по дереву и создаете объект CommonTree для каждого посещенного узла.

Мой вопрос сейчас, какова связь между CommonToken и CommonTree, и что делают эти атрибуты:

cTok.setCharPositionInLine(oTok.getCharPositionInLine());
cTok.setChannel(oTok.getChannel());
cTok.setStartIndex(oTok.getStartIndex());
cTok.setStopIndex(oTok.getStopIndex());
cTok.setTokenIndex(oTok.getTokenIndex());

Ответы [ 2 ]

3 голосов
/ 22 июля 2011

Попробуйте что-то вроде этого:

public static CommonTree copyTree(CommonTree original) {
  CommonTree copy = new CommonTree(original.getToken());
  copyTreeRecursive(copy, original);
  return copy;
}

private static void copyTreeRecursive(CommonTree copy, CommonTree original) {
  if(original.getChildren() != null) {
    for(Object o : original.getChildren()) {

      CommonTree originalChild = (CommonTree)o;

      // get the token from the original child node
      CommonToken oTok = (CommonToken)originalChild.getToken();

      // create a new token with the same type & text as 'oTok' 
      CommonToken cTok = new CommonToken(oTok.getType(), oTok.getText());

      // copy all attributes from 'oTok' to 'cTok'  
      cTok.setLine(oTok.getLine());
      cTok.setCharPositionInLine(oTok.getCharPositionInLine());
      cTok.setChannel(oTok.getChannel());
      cTok.setStartIndex(oTok.getStartIndex());
      cTok.setStopIndex(oTok.getStopIndex());
      cTok.setTokenIndex(oTok.getTokenIndex());

      // create a new tree node with the 'cTok' as token
      CommonTree copyChild = new CommonTree(cTok);

      // set the parent node of the child node
      copyChild.setParent(copy);

      // add the child to the parent node
      copy.addChild(copyChild);

      // make a recursive call to copy deeper
      copyTreeRecursive(copyChild, originalChild);
    }
  }
}

...

// get the original tree
CommonTree tree = (CommonTree)parser.parse().getTree();

// create a copy of the tree
CommonTree copy = copyTree(tree);

// change the contents of the right node of the right node of the root 
((CommonTree)tree.getChild(1).getChild(1)).getToken().setText("X");

System.out.println(tree.toStringTree());
System.out.println(copy.toStringTree());

, что даст:

(&& a (|| b X))
(&& a (|| b c))

для ввода "a && (b || c)".То есть tree имеет X, но copy будет иметь исходное содержимое: c.

Обратите внимание, что я выбираю CommonTree и CommonToken объекты, потому что они по умолчаниюToken и Tree реализации.Если вы решите создать свои собственные Token и / или Tree, есть вероятность, что вы создадите подклассы классов CommonTree и CommonToken, и в этом случае мое предложение не будет нарушено.

ACommonTree является не более чем оболочкой вокруг CommonToken, содержащей немного дополнительной информации: родительский узел и дочерние узлы.Вот почему я также копирую всю информацию из CommonToken объектов.

2 голосов
/ 29 августа 2012

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

  private static CommonTree copyTreeRecursive(CommonTree original) {

    CommonTree copy = new CommonTree(original); // Leverage constructor

    if(original.getChildren() != null) {
      for(Object o : original.getChildren()) {
        CommonTree childCopy  = copyTreeRecursive((CommonTree)o);
        childCopy.setParent(copy);
        copy.addChild(childCopy);
      }
    };
    return copy;
  }

NB. Я придерживался соглашения об именах Барта.

...