Example

Example

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()