Book Examples Modified for Python
The code snippets below are my adaptations of the tree walking example files from chapter 3 in The Book to make them work with Python.
Notes
- Set language=Python option in both .g files
- In Eval.g I had to change references to $INT.text and $ID.text to $INT.getText() and $ID.getText() respectively
- In Eval.g I had to use @init{} instead of @members{} action to initialize memory variable
- In Expr.g I had to use self.skip() instead of just skip()
- Based Test.py on example from Antlr3PythonTarget
Expr.g
grammar Expr;
options {
language=Python;
output=AST;
ASTLabelType=CommonTree;
}
prog : ( stat {print $stat.tree.toStringTree();} )+ ;
stat : expr NEWLINE -> expr
| ID '=' expr NEWLINE -> ^('=' ID expr)
| NEWLINE ->
;
expr : multExpr (('+'^|'-'^) multExpr)*
;
multExpr
: atom ('*'^ atom)*
;
atom : INT
| ID
| '('! expr ')'!
;
ID : ('a'..'z'|'A'..'Z')+ ;
INT : '0'..'9'+ ;
NEWLINE : '\r'? '\n' ;
WS : (' '|'\t'|'\n'|'\r')+ {self.skip()} ;
Eval.g
tree grammar Eval;
options {
language=Python;
tokenVocab=Expr;
ASTLabelType=CommonTree;
}
@init {self.memory = {}}
// START:stat
prog: stat+ ;
stat: expr
{print $expr.value}
| ^('=' ID expr)
{self.memory[$ID.getText()] = int($expr.value)}
;
// END:stat
// START:expr
expr returns [value]
: ^('+' a=expr b=expr) {$value = a+b;}
| ^('-' a=expr b=expr) {$value = a-b;}
| ^('*' a=expr b=expr) {$value = a*b;}
| ID
{
k = $ID.getText()
if k in self.memory:
$value = self.memory[k]
else:
print >> sys.stderr, "undefined variable "+k
}
| INT {$value = int($INT.getText())}
;
// END:expr
Test.py
import sys import antlr3 import antlr3.tree from ExprLexer import ExprLexer from ExprParser import ExprParser from Eval import Eval char_stream = antlr3.ANTLRInputStream(sys.stdin) lexer = ExprLexer(char_stream) tokens = antlr3.CommonTokenStream(lexer) parser = ExprParser(tokens) r = parser.prog() # this is the root of the AST root = r.tree nodes = antlr3.tree.CommonTreeNodeStream(root) nodes.setTokenStream(tokens) eval = Eval(nodes) eval.prog()
Labels: