Построение дерева: размножить поддерево для ребенка
Предположим, у меня есть эта простая и бессмысленная грамматика:
propagate : what^ where*;
what : CHAR^;
where : NUMBER -> ^(PLUS NUMBER);
NUMBER : '0'..'9';
CHAR : 'a'..'z';
PLUS : '+';
Если он разбирает строку как a123456789
, он генерирует AST, как:
Что я хотел бы сделать, это передать маркер, проанализированный what
в where
и создайте AST (для того же самого ввода) как:
Я попробовал следующим образом:
propagate : w=what^ where[$w.text]*;
what : CHAR^;
where[String s] : NUMBER -> ^(PLUS CHAR[s] NUMBER);
NUMBER : '0'..'9';
CHAR : 'a'..'z';
PLUS : '+';
это работает, если what
это один токен, но что если это дерево? Это правильный подход?
1 ответ
Решение
Вот как:
grammar T;
options {
output=AST;
ASTLabelType=CommonTree;
}
parse
: propagate EOF!
;
propagate
: what^ where[$what.tree]*
;
what
: CHAR
;
where[CommonTree lhs]
: NUMBER -> ^(PLUS {new CommonTree($lhs)} NUMBER)
;
NUMBER : '0'..'9';
CHAR : 'a'..'z';
PLUS : '+';
Отладчик ANTLRWorks может не отображать правильный AST: создайте небольшой класс драйверов самостоятельно:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("a123"));
TParser parser = new TParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
Чтобы запустить его, сделайте:
java -cp antlr-3.3.jar org.antlr.Tool Tg javac -cp antlr-3.3.jar *.java java -cp .:antlr-3.3.jar Главная> ast.dot
что приведет к DOT-файлу, представляющему следующий AST: