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