I'm new to ANTLR and currently I'm trying to use ANTLR 3.1.3 with Python. I've already installed successfully ANTLR runtime for Python. But I don't know how to print out the parse tree of a particular input.
Grammar
grammar Expr;
options {
language=Python;
output=AST;
}
expr : atom (op atom)* NEWLINE ;
op : '+' | '-';
atom : ID | INT;
ID : ('a'..'z'|'A'..'Z')+ ;
INT : ('0'..'9')+ ;
NEWLINE : '\r'? '\n' ;
WS : (' '|'\t'|'\n'|'\r')+ {self.skip()} ;
Python code
import sys
import antlr3
from antlr3 import *
from ExprLexer import ExprLexer
from ExprParser import ExprParser
# test the parser with an input
char_stream = antlr3.ANTLRStringStream('3+5\n')
lexer = ExprLexer(char_stream)
tokens = antlr3.CommonTokenStream(lexer)
parser = ExprParser(tokens)
# print the parse tree
t = parser.expr().tree
print t.toStringTree()
Although what I want when the code's executed is the parse tree. The code will print out '3+5' only.
Would you please tell me how to modify the code to get the parse tree printed?
2 Answers 2
Some weeks ago, I wanted to print out the ANTLR AST (not the parse tree, but it depends on how you implemented your grammar..) for debugging purposes.
You can do something very easy like:
def print_tree(tree, lev):
print (" " * lev) + "` " + str(tree)
for c in tree.getChildren():
print_tree(c, lev + 1)
print_tree(parser.expr().tree, 0)
NB: I've written the code directly in SO, so it is untested
Comments
Here is another version...
from antlr4 import *
from antlr4.tree.Tree import TerminalNodeImpl
from antlr4.tree.Trees import Trees
def dump(node, depth=0, ruleNames=None):
depthStr = '. ' * depth
if isinstance(node, TerminalNodeImpl):
print(f'{depthStr}{node.symbol}')
else:
print(f'{depthStr}{Trees.getNodeText(node, ruleNames)}')
for child in node.children:
dump(child, depth + 1, ruleNames)
def test_parse_tree():
istream = FileStream(INFILE, encoding='utf-8')
lexer = MyLexer(istream)
stream = CommonTokenStream(lexer)
parser = MyParser(stream)
tree = parser.MAINRULE()
print(tree.toStringTree(recog=parser)) # lisp repr of tree
dump(tree, ruleNames=parser.ruleNames) # pretty printed version
It yields output like so...
prog
. line
. . text
. . . [@0,0:0='@',<5>,1:0]
. . cmnt
. . . [@1,1:2='\n@',<1>,1:1]
. . . [@2,3:3=' ',<4>,2:1]
. . . text
. . . . [@3,4:4=' ',<4>,2:2]