Прежде всего, вы проделали большую работу, учитывая тот факт, что вы никогда раньше не использовали ANTLR.
Вы можете опустить language=Java
и ASTLabelType=CommonTree
, которые являются значениями по умолчанию. Так что вы можете просто сделать:
options {
output=AST;
}
Кроме того, вам не нужно указывать корневой узел для каждого оператора отдельно. Так что вам не нужно делать:
(ADD^ | SUB^)
но следующее:
(ADD | SUB)^
будет достаточно. Имея только два оператора, разница невелика, но при реализации реляционных операторов (>=
, <=
, >
и <
) последние немного проще.
Теперь для вас AST: вы, вероятно, захотите создать бинарное дерево: таким образом, все внутренние узлы являются операторами, а листья будут операндами, что значительно упрощает фактическую оценку ваших выражений. Чтобы получить двоичное дерево, вам нужно немного изменить правило atom
:
atom
: INTEGER
| (
OPARN expression CPARN -> expression
)
(
OPARN e=expression CPARN -> ^(MUL $atom $e)
)*
;
, который выдает следующий AST при вводе "(2-3)(4+5)(6*7)"
:
![enter image description here](https://i.stack.imgur.com/bjncL.png)
(изображение предоставлено: graphviz-dev.appspot.com )
Файл DOT был сгенерирован со следующим тестовым классом:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
GLexer lexer = new GLexer(new ANTLRStringStream("(2-3)(4+5)(6*7)"));
GParser parser = new GParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.start().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}