Расширение ANTLR3 AST

#tree #antlr #antlr3 #tree-nodes #heterogeneous

#дерево #antlr #antlr3 #дерево-узлы #неоднородный

Вопрос:

С помощью ANTLR2 вы могли бы определить что-то подобное в файле определения грамматики:

 options
{
   language = "CSharp";
   namespace = "Extended.Tokens";
}

tokens {
   TOKEN<AST=Extended.Tokens.TokenNode>;
}
  

И затем вы могли бы создать класс:

 public class TokenNode: antlr.BaseAST
{
    ...
}
  

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

Редактировать

Я не пытаюсь создавать пользовательские токены, а пользовательские «анализаторы узлов».

Для того, чтобы «выполнить» дерево, у вас есть 2 варианта (насколько я понял):

  1. создайте «посетителя дерева» и обрабатывайте значения, или
  2. создайте анализатор дерева, «почти дублируя» определение грамматики.

В случае версии 2 я мог бы украсить узел дерева любым методом, который мне бы понравился, а затем вызвать их после запуска синтаксического анализатора, просто вызвав что-то вроде ‘execute’ из корневого узла.

Комментарии:

1. Извините, это опечатка: это определение было с v2. Я отредактировал сообщение.

2. Имеет ли это какой-либо смысл? Есть ли какой-либо способ реализовать в ANTLR3 что-то похожее на ANTLR2?

3. Не пользовательские токены, а пользовательские «анализаторы узлов». Для того, чтобы «выполнить» дерево, у вас есть 2 варианта (насколько я понял): 1. создать «посетителя дерева» и обрабатывать значения и 2. создать анализатор дерева, «почти дублируя» определение грамматики. В случае версии 2 я мог бы украсить узел дерева любым методом, который мне бы понравился, а затем вызвать их после запуска синтаксического анализатора, просто вызвав что-то вроде ‘execute’ из корневого узла.

Ответ №1:

Я мало знаю C #, но не должно быть большой разницы с целью Java.

Вы можете создать — и позволить ANTLR использовать — пользовательское дерево, установив ASTLabelType в options { ... } разделе ( XTree в данном случае an):

T.g

 grammar T;

options {
  output=AST;
  ASTLabelType=XTree;
}

tokens {
  ROOT;
}

@parser::header {
  package demo;
  import demo.*;
}

@lexer::header {
  package demo;
  import demo.*;
}

parse
  :  Any* EOF -> ^(ROOT Any*)
  ;

Any
  :  .
  ;
  

Затем вы создаете пользовательский класс, который расширяет CommonTree :

demo/XTree.java

 package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class XTree extends CommonTree {

  public XTree(Token t) {
    super(t);
  }

  public void x() {
    System.out.println("XTree.text="   super.getText()   ", children="   super.getChildCount());
  }
}
  

и когда вы TParser создаете свой экземпляр, вы должны создать и установить пользовательский TreeAdaptor интерфейс, который создает экземпляры вашего XTree :

demo/Main.java

 package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class Main {

  public static void main(String[] args) throws Exception {
    String source = "ABC";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.setTreeAdaptor(new CommonTreeAdaptor(){
      @Override
      public Object create(Token t) {
        return new XTree(t);
      }
    }); 
    XTree root = (XTree)parser.parse().getTree();
    root.x();
  }
}
  

Запуск демо-версии:

 java -cp antlr-3.2.jar org.antlr.Tool T.g -o demo/
javac -cp antlr-3.2.jar demo/*.java
java -cp .:antlr-3.2.jar demo.Main
  

будет выводить:

 XTree.text=ROOT, children=3
  

Для получения дополнительной информации см.: http://www.antlr.org/wiki/display/ANTLR3/Tree construction

Комментарии:

1. Это не совсем то, что я искал… В примере, который я видел ( antlr2.org/doc/trees.html — «Фабрики AST» и «Гетерогенные AST») вы можете определить, какой класс создавать для конкретного токена. В вашем примере вы можете создать один тип объекта (XTree) после анализа дерева.

2. Ну, в create методе CommonTreeAdaptor вы можете вернуть любое дерево, которое вам нравится, на основе токена, который передается в качестве параметра, будь то XTree or YTree , это не имеет значения. В этом случае вы можете захотеть перейти ASTLabelType на CommonTree или какой-либо другой класс, который расширяют все ваши пользовательские деревья.

3. Я думаю, что нашел то, что искал: antlr.org/wiki/display/ANTLR3/Tree construction (Разнородные узлы дерева). Спасибо за подсказки! 🙂

4. Я только что разместил ссылку на это! 🙂 Пожалуйста, конечно.