分享

Expression evaluator - ANTLR Wiki

 快乐学习 2007-01-07

Here is a complete grammar that evaluates expressions containing +, -, * and variable assignments. A simple hash table is used to store variable values.

The tutorial requires the current depot version of ANTLR 3.0, i.e. the version must be later than 3.0 beta 5.

grammar Expr;
@header {
import java.util.HashMap;
}
@members {
/** Map variable name to Integer object holding value */
HashMap memory = new HashMap();
}
prog:   stat+ ;
stat:   expr NEWLINE {System.out.println($expr.value);}
|   ID ‘=‘ expr NEWLINE
{memory.put($ID.text, new Integer($expr.value));}
|   NEWLINE
;
expr returns [int value]
:   e=multExpr {$value = $e.value;}
(   ‘+‘ e=multExpr {$value += $e.value;}
|   ‘-‘ e=multExpr {$value -= $e.value;}
)*
;
multExpr returns [int value]
:   e=atom {$value = $e.value;} (‘*‘ e=atom {$value *= $e.value;})*
;
atom returns [int value]
:   INT {$value = Integer.parseInt($INT.text);}
|   ID
{
Integer v = (Integer)memory.get($ID.text);
if ( v!=null ) $value = v.intValue();
else System.err.println("undefined variable "+$ID.text);
}
|   ‘(‘ expr ‘)‘ {$value = $expr.value;}
;
ID  :   (‘a‘..‘z‘|‘A‘..‘Z‘)+ ;
INT :   ‘0‘..‘9‘+ ;
NEWLINE:‘\r‘? ‘\n‘ ;
WS  :   (‘ ‘|‘\t‘)+ {skip();} ;

And here is the main program to execute the parser:

import org.antlr.runtime.*;
public class Test {
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
ExprLexer lexer = new ExprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.prog();
}
}

Here is a sample run:

$java Test
x=1
y=2
3*(x+y)
<EOF>
9
$

What if you want to build trees instead? Here is a grammar that builds trees instead of evaluating the expressions:

grammar Expr;
options {
output=AST;
ASTLabelType=CommonTree; // type of $stat.tree ref etc...
}
prog:   ( stat {System.out.println($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‘)+ {skip();} ;

And here is the tree grammar that will read the trees and evaluate the expressions.

tree grammar Eval;
options {
tokenVocab=Expr;
ASTLabelType=CommonTree;
}
@header {
import java.util.HashMap;
}
@members {
/** Map variable name to Integer object holding value */
HashMap memory = new HashMap();
}
prog:   stat+ ;
stat:   expr
{System.out.println($expr.value);}
|   ^(‘=‘ ID expr)
{memory.put($ID.text, new Integer($expr.value));}
;
expr returns [int value]
:   ^(‘+‘ a=expr b=expr)  {$value = a+b;}
|   ^(‘-‘ a=expr b=expr)  {$value = a-b;}
|   ^(‘*‘ a=expr b=expr)  {$value = a*b;}
|   ID
{
Integer v = (Integer)memory.get($ID.text);
if ( v!=null ) $value = v.intValue();
else System.err.println("undefined variable "+$ID.text);
}
|   INT                   {$value = Integer.parseInt($INT.text);}
;

Here is the main program:

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
public class Test {
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
ExprLexer lexer = new ExprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
ExprParser.prog_return r = parser.prog();
// walk resulting tree
        CommonTree t = (CommonTree)r.getTree();
CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
EvalTreeParser walker = new EvalTreeParser(nodes);
walker.prog();
}
}

and a sample run:

$ java Test
x=1
y=2
3*(x+y)
<EOF>
(= x 1)
(= y 2)
(* 3 (+ x y))
9
$

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多