#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 варианта (насколько я понял):
- создайте «посетителя дерева» и обрабатывайте значения, или
- создайте анализатор дерева, «почти дублируя» определение грамматики.
В случае версии 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
orYTree
, это не имеет значения. В этом случае вы можете захотеть перейтиASTLabelType
наCommonTree
или какой-либо другой класс, который расширяют все ваши пользовательские деревья.3. Я думаю, что нашел то, что искал: antlr.org/wiki/display/ANTLR3/Tree construction (Разнородные узлы дерева). Спасибо за подсказки! 🙂
4. Я только что разместил ссылку на это! 🙂 Пожалуйста, конечно.