<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:www.refactormycode.com,2007:users1237</id>
  <link type="application/atom+xml" href="http://www.refactormycode.com/users/1237" rel="self"/>
  <title>congofreestate.blogspot.com</title>
  <updated>Thu Dec 25 00:21:21 -0800 2008</updated>
  <entry>
    <id>tag:www.refactormycode.com,2007:Code683</id>
    <published>2008-12-25T00:21:21-08:00</published>
    <updated>2009-01-06T05:31:34-08:00</updated>
    <title>[Java] ANTLR / Java</title>
    <content type="html">&lt;p&gt;This is a mix of ANTLR ( &lt;a href="http://www.antlr.org/" target="_blank"&gt;http://www.antlr.org/&lt;/a&gt; ) and regular Java.&lt;/p&gt;

&lt;pre&gt;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&amp;lt;Integer&amp;gt; args) throws Exception {
		Object result;
		Class[] params = m.getParameterTypes();
		if (params.length &amp;gt; 0 &amp;amp;&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&amp;lt;params.length-1; i++) {
				arguments[i] = args.get(i);
			}
			arguments[i] = args.subList(i, args.size()).toArray(new Integer[0]);
			//System.out.println(&amp;quot;calling with array:&amp;quot; + arguments[i]);
			result = m.invoke(obj, arguments);
		}
		else {
			// normal function call.
			result = m.invoke(obj, args.toArray());
		}
		System.out.println(&amp;quot;method: &amp;quot;+m.getName() + &amp;quot; &amp;quot; + args + &amp;quot; -&amp;gt; &amp;quot; + (Integer)result);
		return (Integer)result;
	}

	public Integer dispatchFnToObject(Object obj, String fn, ArrayList&amp;lt;Integer&amp;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(&amp;quot;Error when calling &amp;quot; + m.getName() + &amp;quot;\nError: &amp;quot; + e);
					// just continue...
				}
			}
			else {
				//System.out.println(&amp;quot;got method: &amp;quot; + m.toString());
			}
		}
		System.err.println(&amp;quot;Could not find method &amp;quot; + fn + &amp;quot;. returning null.&amp;quot;);
		return null;
	}
	public int dispatchFn(String fn, ArrayList&amp;lt;Integer&amp;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&amp;lt;Integer&amp;gt; args = new ArrayList&amp;lt;Integer&amp;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(&amp;quot;got fn:&amp;quot; + $fn.text + &amp;quot; with args:&amp;quot;+ 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(&amp;quot;undefined variable &amp;quot;+$ID.text);
        }
    |   '(' expr ')' {$value = $expr.value;}
    ;

ID  :   ('a'..'z'|'A'..'Z')+ ;
INT :   '0'..'9'+ ;
NEWLINE:'\r'? '\n' ;
WS  :   (' '|'\t')+ {skip();} ;
&lt;/pre&gt;</content>
    <author>
      <name>congofreestate.blogspot.com</name>
      <email>no-email@refactormycode.com</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/683-antlr-java" rel="alternate"/>
  </entry>
</feed>

