<?xml version="1.0" encoding="UTF-8"?>
<code>
  <code>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&lt;Integer&gt; args) throws Exception {
		Object result;
		Class[] params = m.getParameterTypes();
		if (params.length &gt; 0 &amp;&amp; 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&lt;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 + " -&gt; " + (Integer)result);
		return (Integer)result;
	}

	public Integer dispatchFnToObject(Object obj, String fn, ArrayList&lt;Integer&gt; 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&lt;Integer&gt; 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&lt;Integer&gt; args = new ArrayList&lt;Integer&gt;(); }	
	:
	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();} ;
</code>
  <comment>This is a mix of ANTLR ( http://www.antlr.org/ ) and regular Java.</comment>
  <created-at type="datetime">2008-12-25T00:21:21+00:00</created-at>
  <id type="integer">683</id>
  <language>Java</language>
  <permalink>antlr-java</permalink>
  <refactors-count type="integer">1</refactors-count>
  <title>ANTLR / Java</title>
  <trackback-url></trackback-url>
  <updated-at type="datetime">2009-01-06T05:31:34+00:00</updated-at>
  <user-id type="integer">1237</user-id>
  <refactors type="array">
    <refactor>
      <code></code>
      <code-id type="integer">683</code-id>
      <comment>hi could u help me to learn this program.</comment>
      <created-at type="datetime">2009-01-06T05:31:33+00:00</created-at>
      <id type="integer">142654</id>
      <language>Java</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On ANTLR / Java</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>shankar</user-name>
      <user-website></user-website>
    </refactor>
  </refactors>
</code>
