grammar Expr;
options {
backtrack=true;
}
@header {
import java.util.HashMap;
import java.lang.reflect.Method;
}
@members {
/** Map variable name to Integer object holding value */
HashMap memory = new HashMap();
class PublicFunctions {
public Integer square(Integer x) { return x*x; }
public Integer addfive(Integer x) { return x+5; }
public Integer add(Integer...arguments) {
Integer sum = new Integer(0);
for (Integer x : arguments) {
sum+= x;
}
return sum;
}
}
public Integer dispatchMethod(Method m, Object obj, ArrayList<Integer> args) throws Exception {
Object result;
Class[] params = m.getParameterTypes();
if (params.length > 0 && params[params.length-1].isArray()) {
// function expects last argument to be an array.
Object[] arguments = new Object[params.length];
int i=0;
// could be buggy..
for (i=0; i<params.length-1; i++) {
arguments[i] = args.get(i);
}
arguments[i] = args.subList(i, args.size()).toArray(new Integer[0]);
//System.out.println("calling with array:" + arguments[i]);
result = m.invoke(obj, arguments);
}
else {
// normal function call.
result = m.invoke(obj, args.toArray());
}
System.out.println("method: "+m.getName() + " " + args + " -> " + (Integer)result);
return (Integer)result;
}
public Integer dispatchFnToObject(Object obj, String fn, ArrayList<Integer> args) {
for (Method m : obj.getClass().getDeclaredMethods()) {
if ( m.getName().compareTo(fn) == 0 ) {
try {
Integer result = dispatchMethod(m, obj, args);
if (result!=null) { return result; }
}
catch (Exception e) {
System.err.println("Error when calling " + m.getName() + "\nError: " + e);
// just continue...
}
}
else {
//System.out.println("got method: " + m.toString());
}
}
System.err.println("Could not find method " + fn + ". returning null.");
return null;
}
public int dispatchFn(String fn, ArrayList<Integer> args) {
return this.dispatchFnToObject( new PublicFunctions(), fn, args).intValue();
}
}
prog: stat+ ;
stat: expr NEWLINE {System.out.println($expr.value);}
| ID '=' expr NEWLINE
{memory.put($ID.text, new Integer($expr.value));}
| NEWLINE
;
funcall returns [int value]
@init { ArrayList<Integer> args = new ArrayList<Integer>(); }
:
fn=ID '(' (fexpr=expr { args.add( new Integer($fexpr.value)); } // is there a better way to do this?
(',' aexpr=expr { args.add( new Integer($aexpr.value)); } )* // is there a better way to do this?
)? ')'
{
//System.out.println("got fn:" + $fn.text + " with args:"+ args );
$value = this.dispatchFn( (String) $fn.text, args);
};
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);}
| funcall {$value = $funcall.value; }
| 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();} ;
Refactorings
No refactoring yet !
shankar
January 6, 2009, January 06, 2009 05:31, permalink
hi could u help me to learn this program.
This is a mix of ANTLR ( http://www.antlr.org/ ) and regular Java.