/*******************************************************************************
 * Copyright (c) 2004, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 *  $RCSfile: ExpressionProcesser.java,v $
 *  $Revision: 1.21 $  $Date: 2005/08/24 20:39:07 $ 
 */
package org.eclipse.jem.internal.proxy.initParser.tree;

import java.lang.reflect.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jem.internal.proxy.common.*;
import org.eclipse.jem.internal.proxy.initParser.InitializationStringEvaluationException;
import org.eclipse.jem.internal.proxy.initParser.InitializationStringParser;
 
/**
 * Expression processing. This does the actual expression processing with the live objects.
 * It is meant to be subclassed only to provide additional expression types. All of the
 * current expressions cannot be overridden. This is because the stack is very sensitive to 
 * call order.
 * 
 * @since 1.0.0
 */
public class ExpressionProcesser {

	/**
	 * A variable reference for a field access.
	 * 
	 * @since 1.1.0
	 */
	protected static class FieldAccessReference extends VariableReference {
		
		private final Field field;
		private final Object receiver;

		/**
		 * Use this to construct a FieldAccessReference. This will do checks to make sure
		 * it is valid so that exceptions won't be thrown later when actually dereferenced.
		 * 
		 * @param field
		 * @param receiver
		 * @return
		 * @throws IllegalArgumentException
		 * 
		 * @since 1.1.0
		 */
		public static FieldAccessReference createFieldAccessReference(Field field, Object receiver) throws IllegalArgumentException {
			// If static, then receiver is ignored.
			if (!Modifier.isStatic(field.getModifiers())) {
				if (!field.getDeclaringClass().isInstance(receiver))
					throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.CreateFieldAccessReference.FieldsTypesNotMatching_EXC_"), new Object[]{field.getType(), (receiver!=null ? receiver.getClass() : null)})); //$NON-NLS-1$
			}
			field.setAccessible(true);	// Make it always accessible. Trust it. 
			return new FieldAccessReference(field, receiver);
		}
		
		protected FieldAccessReference(Field field, Object receiver) {
			this.field = field;
			this.receiver = receiver;
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser.VariableReference#dereference()
		 */
		public Object dereference() {
			try {
				return field.get(receiver);
			} catch (IllegalArgumentException e) {
				// Shouldn't occur. Already tested for this.
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// Shouldn't occur. Already tested for this.
				e.printStackTrace();
			}
			return null;
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser.VariableReference#set(java.lang.Object, java.lang.Class)
		 */
		public Object set(Object value, Class type) throws IllegalArgumentException, IllegalAccessException {
			field.set(receiver, value);
			return field.get(receiver);	// Just in case some conversion happened. Technically it is not the value set but the retrieved when in an assignment.
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Object#toString()
		 */
		public String toString() {
			return "FieldAccess{"+field.toString()+"} on "+(receiver != null ? receiver.toString() : "<static access>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
	}
	
	/**
	 * A variable reference for an Array access. It will reference only the last indexed entry of the array.
	 * For example if <code>x[3][4]</code> is the access, then what will be given to this reference will be
	 * the array entry at x[3][4], not the x array itself.
	 * 
	 * @since 1.1.0
	 */
	protected static class ArrayAccessReference extends VariableReference {
		
		
		private final Object array;
		private final int index;

		/**
		 * Use this to construct an array access reference. This will do checks to make sure
		 * it is valid so that exceptions won't be thrown later when actually dereferenced.
		 * 
		 * @param array
		 * @param index
		 * @return
		 * @throws IllegalArgumentException
		 * 
		 * @since 1.1.0
		 */
		public static ArrayAccessReference createArrayAccessReference(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
			int len = Array.getLength(array);
			if (index < 0 || len <= index)
				throw new ArrayIndexOutOfBoundsException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.CreateArrayAccessReference.OutOfBounds_EXC_"), new Object[]{new Integer(index), new Integer(len)})); //$NON-NLS-1$
			return new ArrayAccessReference(array, index);
		}
		/**
		 * Construct the reference with the array and the index of the entry being referenced.
		 * @param array
		 * @param index
		 * 
		 * @since 1.1.0
		 */
		protected ArrayAccessReference(Object array, int index) {
			this.array = array;
			this.index = index;
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.initParser.tree.VariableReference#dereference()
		 */
		public Object dereference() {
			return Array.get(array, index);
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.initParser.tree.VariableReference#set(java.lang.Object, java.lang.Class)
		 */
		public Object set(Object value, Class type) throws IllegalArgumentException {
			Array.set(array, index, value);
			return Array.get(array, index);	// In case there was some conversion applied. Technically it is not the value set but the retrieved when in an assignment.
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Object#toString()
		 */
		public String toString() {
			return "ArrayAccess["+index+"]: "+array.toString(); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
	
	/**
	 * The expression result stack and the expression result type stack.
	 * The type stack is used to be expected type of the corresponding
	 * expression result. This is needed for converting to primitives
	 * and for finding correct method call from the argument types. In
	 * this case, it is not the true value, but the value expected, e.g.
	 * <code>Object getObject()</code> returns something of type Object.
	 * This needs to be maintained so that if it goes into another method
	 * we don't accidently return a more specific method instead of the
	 * one that takes Object as an argument. 
	 * 
	 * expressionStack has result of the expression.
	 * expressionTypeStack has the computed type of the expression i.e.
	 * the type that the expression returns, not the type of the value.
	 * These can be different because the expression (e.g. method) may
	 * return an Object, but the expression value will be some specific
	 * subclass. So the expressionTypeStack would have a <code>java.lang.Object.class</code>
	 * on it in that case.
	 * Note: if the expressionStack has a <code>null</code> on it, then the type stack
	 * may either have a specific type in it, or it may be <code>MethodHelper.NULL_TYPE</code>. It
	 * would be this if it was explicitly pushed in and not as the
	 * result of a computation. If the result of a computation, it would have the
	 * true value.
	 * Note: if the expressionStack has a <code>Void.type</code> on it, then that
	 * means the previous expression had no result. This is an error if trying to
	 * use the expression in another expression.
	 * 
	 * @see org.eclipse.jem.internal.proxy.initParser.MethodHelper#NULL_TYPE
	 */
	private List expressionStack = new ArrayList(10);
	private List expressionTypeStack = new ArrayList(10);
	
	/**
	 * List of the expression proxies. The index into the list is the
	 * same as the expression proxy id. 
	 */
	private ArrayList expressionProxies;	// It is array list because we want to call ensureCapacity and that is not available on List.
	
	/**
	 * An error has occurred. At this point all subcommands will simply make sure they flush the input stream
	 * correctly, but they do not process it.
	 * 
	 * @since 1.0.0
	 */
	private boolean errorOccurred = false;
	private boolean novalueException = false;
	
	private Throwable exception = null;	// Was there another kind of exception that was caught.
	
	/**
	 * Process all other exceptions then the NoExpressionValueException. This can be called from usage code so that if there was an error
	 * in setting up for a call to the processer it can be logged.
	 * 
	 * @param e
	 * 
	 * @since 1.0.0
	 */
	public final void processException(Throwable e) {
		// Process all other exceptions.
		novalueException = false;
		while (e.getCause() != null)
			e = e.getCause();
		if (traceOn) {
			System.out.println();
			System.out.print("***** >>>\tException: "); //$NON-NLS-1$
			System.out.println(e);
		}
		throwException(e);	// Treat as a throw to let try/catches expressions handle it.
	}
	
	/**
	 * This is a syntax exception. This means data coming across is corrupted in
	 * some way so no further processing should occur. 
	 * @param e
	 * 
	 * @since 1.1.0
	 */
	protected final void processSyntaxException(Throwable e) {
		errorOccurred = true;
		novalueException = false;
		exception = e;		
	}
		
	/**
	 * Process a NoExpressionValueException. Don't wrapper these.
	 * @param e
	 * 
	 * @since 1.1.0
	 */
	protected final void processSyntaxException(NoExpressionValueException e) {
		if (traceOn) {
			// This can happen at any time, so make sure we are on a new line.
			System.out.println();
			printTrace("Expression has no value", false); //$NON-NLS-1$
		}
		try {
			errorOccurred = true;
			novalueException = true;
			exception = e;
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Return whether there are any errors.
	 * 
	 * @return <code>true</code> if no errors.
	 * 
	 * @since 1.0.0
	 */
	public boolean noErrors() {
		return !errorOccurred;
	}
	
	/**
	 * Return whether the error is a NoExpressionValueException or not.
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public boolean isNoExpressionValue() {
		return novalueException;
	}
	
	/**
	 * Return the throwable if a Throwable was caught.
	 * 
	 * @return The throwable, or <code>null</code> if not set.
	 * 
	 * @since 1.0.0
	 */
	public Throwable getErrorThrowable() {
		return exception;
	}

	/**
	 * Push the expression value and its expected type.
	 * @param o
	 * @param type
	 * 
	 * @since 1.0.0
	 */
	protected final void pushExpressionValue(Object o, Class type) {
		expressionStack.add(o);
		expressionTypeStack.add(type);
	}

	/**
	 * Pop just the expression value. It is imperitive that the expression type
	 * is popped immediately following. Separated the methods so that we
	 * don't need to create an array to return two values. This will dereference
	 * any variable references.
	 * 
	 * @return The value.
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.0.0
	 */
	protected final Object popExpression() throws NoExpressionValueException {
		return popExpression(true);
	}
	
	/**
	 * Pop just the expression value. It is imperitive that the expression type
	 * is popped immediately following. Separated the methods so that we
	 * don't need to create an array to return two values.
	 * 
	 * @param deReference If the top expression is a Reference, then dereference it.
	 * @return The value.
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.0.0
	 */
	protected final Object popExpression(boolean deReference) throws NoExpressionValueException {
		try {
			// Do not pop above the current subexpression pos, if any.
			if (topSubexpression != -1)
				if (expressionStack.size() == subexpressionStackPos[topSubexpression])
					throw new NoExpressionValueException();
			
			Object result = expressionStack.remove(expressionStack.size()-1);
			if (deReference && result instanceof VariableReference)
				result = ((VariableReference) result).dereference();
			return result;
		} catch (IndexOutOfBoundsException e) {
			throw new NoExpressionValueException();
		}
	}

	/**
	 * Get the expression at <code>fromTop</code> down from the top. This is
	 * need for when multi-operators happen and they are stored in reverse of 
	 * what is needed. They would normally be stored left to right, with the
	 * rightmost one on top. But they need to be processed left to right, so
	 * to get the left most one requires digging down in the stack.
	 * <p>
	 * When done, <code>popExpressions(int count)</code> must be called to
	 * clean them out since they were processed.
	 * <p>
	 * This will not dereference the expression. It is the job of the caller to do this. 
	 *  
	 * @param fromTop <code>1</code> is the top one, <code>2</code> is the next one down.
	 * @return The entry from the top that was requested.
	 * @throws NoExpressionValueException
	 * 
	 * @see IDEExpression#popExpressions(int)
	 * @since 1.0.0
	 */
	protected final Object getExpression(int fromTop) throws NoExpressionValueException {
		try {
			// Do not pull above the current subexpression pos, if any.			
			if (topSubexpression != -1)
				if (expressionStack.size()-fromTop < subexpressionStackPos[topSubexpression])
					throw new NoExpressionValueException();
			
			return expressionStack.get(expressionStack.size()-fromTop);
		} catch (IndexOutOfBoundsException e) {
			throw new NoExpressionValueException();
		}
	}
	
	/**
	 * Remove the top <code>count</code> items. This will not cause dereferencing to occur. It
	 * removes the corresponding type stack entries.
	 * 
	 * @param count
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.0.0
	 */
	protected final void popExpressions(int count) throws NoExpressionValueException {
		try {
			// Do not pop above the current subexpression pos, if any.
			int stop = topSubexpression != -1 ? subexpressionStackPos[topSubexpression] : -1;
			int remove = expressionStack.size()-1;
			while (count-- > 0) {
				if (expressionStack.size() <= stop)
					throw new NoExpressionValueException();	// Try to go above the current subexpression.
				expressionStack.remove(remove);
				expressionTypeStack.remove(remove--);
			}
		} catch (IndexOutOfBoundsException e) {
			throw new NoExpressionValueException();
		}
	}
	
	/**
	 * Pop just the expression type. It is imperitive that the expression type
	 * is popped immediately following popExpression. Separated the methods so that we
	 * don't need to create an array to return two values.
	 * <p>
	 * If the allowVoid is false and type is void, then a NoExpressionValueException will be thrown.
	 * This is for the case where the expression was trying to be used in a different
	 * expression. This will be set to void only on expressions that return no value (only
	 * method's do this for now).
	 * 
	 * @param allowVoid Allow void types if <code>true</code>
	 * @return The type.
	 * @throws NoExpressionValueException
	 * @since 1.0.0
	 */
	protected final Class popExpressionType(boolean allowVoid) throws NoExpressionValueException {
		try {
			Class result = (Class) expressionTypeStack.remove(expressionTypeStack.size()-1);
			if (!allowVoid && result == Void.TYPE)
				throw new NoExpressionValueException(InitparserTreeMessages.getString("ExpressionProcesser.PopExpressionType.ExpressionVoid_EXC_")); //$NON-NLS-1$
			return result;
				
		} catch (IndexOutOfBoundsException e) {
			throw new NoExpressionValueException();
		}
	}

	/**
	 * Get the expression type at <code>fromTop</code> down from the top. This is
	 * need for when multi-operators happen and they are stored in reverse of 
	 * what is needed. They would normally be stored left to right, with the
	 * rightmost one on top. But they need to be processed left to right, so
	 * to get the left most one requires digging down in the stack.
	 * <p>
	 * When done, <code>popExpressionTypes(int count)</code> must be called to
	 * clean them out since they were processed.

	 * @param fromTop <code>1</code> is the top one, <code>2</code> is the next one down.
	 * @param allowVoid Allow void types if <code>true</code>
	 * @return The type from the top that was requested.
	 * @throws ThrowableProxy
	 * @throws NoExpressionValueException
	 * 
	 * @see IDEExpression#popExpressionTypes(int)
	 * @since 1.0.0
	 */
	protected final Class getExpressionType(int fromTop, boolean allowVoid) throws NoExpressionValueException {
		try {
			Class result = (Class) expressionTypeStack.get(expressionTypeStack.size()-fromTop);
			if (!allowVoid && result == Void.TYPE)
				throw new NoExpressionValueException();
			return result;
		} catch (IndexOutOfBoundsException e) {
			throw new NoExpressionValueException();
		}
	}
	
	/**
	 * Flag indicating expression should be ignored and not processed.
	 * This happens because of few cases, like conditional and, that
	 * if one returns false, the rest of the expressions in that conditional and
	 * expression should be ignored and not processed.
	 * <p>
	 * It is an Object that acts as an enum for the type of expression that initiated the ignore. 
	 * If it is <code>null</code> then no one is ignoring. 
	 * <p>
	 * All of the pushTo...Proxy methods must test this for this to work correctly.
	 * Each expression has some way of testing that their particular nesting of 
	 * expressions is complete and they can turn off the ignore flag.
	 * <p>
	 * Only one type of ignore can exist at a time.
	 */
	protected Object ignoreExpression = null;	
	
	
	private List saveStates;
	
	/**
	 * Are we tracing or not.
	 */
	protected final boolean traceOn;
	private final long thresholdTime;
	private long startExpressionStepTime;
	private long startExpressionTime;
	private long lastExpressionEndTime;
	
	/**
	 * Trace head of this expression. So that traces from different expressions can be distinquished.
	 * It is simply an monotonically increasing counter. It is the header string for any trace output.
	 */
	protected final String traceHeader;
	
	private int indent = 0;	// Indented for certain block expressions.
	
	/*
	 * Trace counter. It is incremented once for each expression and assigned to the traceId of the expression.
	 */
	private static int TRACE_COUNTER;
	
	/**
	 * Create the Expression without tracing.
	 * @param registry
	 * 
	 * @since 1.0.0
	 */
	public ExpressionProcesser() {
		this(false, -1);
	}
	
	/**
	 * Create the expression, and set the tracing mode and threshold time. Use -1
	 * for default time of 100ms.
	 * @param traceOn
	 * 
	 * @since 1.1.0
	 */
	public ExpressionProcesser(boolean traceOn, long threshold) {
		this.traceOn = traceOn;
		if (traceOn) {
			traceHeader = "**"+(++TRACE_COUNTER)+':'; //$NON-NLS-1$
			System.out.print(traceHeader);
			System.out.println(" Start expression"); //$NON-NLS-1$
			this.thresholdTime = threshold != -1 ? threshold : 100;
			lastExpressionEndTime = startExpressionTime = System.currentTimeMillis();
		} else {
			traceHeader = null;
			thresholdTime = 100;
		}
	}
	
	/**
	 * Trace msg helper. Should only be called if traceOn is true. This method is only used to start a new trace message.
	 * The caller is must call printTraceEnd at the end.
	 *  
	 * @param msg message to print
	 * @param ignore are we ignoring the expression, or is it being processed (this just alters the trace output slightly).
	 * 
	 * @since 1.1.0
	 */
	protected void printTrace(String msg, boolean ignore) {
		startExpressionStepTime = System.currentTimeMillis();
		long sinceLastExpression = startExpressionStepTime - lastExpressionEndTime;
		System.out.print(traceHeader);
		if (sinceLastExpression > 0) {
			System.out.print('(');
			if (sinceLastExpression > thresholdTime)
				System.out.print("***"); //$NON-NLS-1$
			System.out.print(sinceLastExpression);
			System.out.print("ms)"); //$NON-NLS-1$
		}
		System.out.print('\t');
		if (!ignore)
			System.out.print("\t"); //$NON-NLS-1$
		else
			System.out.print("##\t"); //$NON-NLS-1$
		
		printIndent();
		System.out.print(msg);
	}
	
	/**
	 * print the indent. It will not do a new line before nor after.
	 * 
	 * @since 1.1.0
	 */
	protected void printIndent() {
		for(int i=indent; i>0; i--) {
			System.out.print("  "); //$NON-NLS-1$
		}
	}

	protected void printTraceEnd() {
		long stop = System.currentTimeMillis()-startExpressionStepTime;
		if (stop > 0) {
			System.out.print(" ("); //$NON-NLS-1$
			if (stop > thresholdTime)
				System.out.print("***"); //$NON-NLS-1$
			System.out.print(stop);
			System.out.print("ms)"); //$NON-NLS-1$
		}
		System.out.println();
		lastExpressionEndTime = System.currentTimeMillis();
	}
	
	/**
	 * Do an indent (undent) according to indent flag.
	 * @param indent <code>true</code> to increment indent, or otherwise decrement.
	 * 
	 * @since 1.1.0
	 */
	protected void indent(boolean indent) {
		this.indent += (indent ? 1 : -1);
		if (this.indent < 0)
			this.indent = 0;
	}
	
	/**
	 * Print the object and type. It will not end with a newline char, so one will be needed afterwards.
	 * 
	 * @param o
	 * @param t
	 * 
	 * @since 1.1.0
	 */
	protected void printObjectAndType(Object o, Class t) {
		System.out.print(' ');
		System.out.print("Object-"); //$NON-NLS-1$
		System.out.print(o);
		System.out.print(" Type-"); //$NON-NLS-1$
		System.out.print(t);
		System.out.print(' ');
	}
	
	/**
	 * Close the exception processing
	 * 
	 * @since 1.0.0
	 */
	public final void close() {
		boolean firstClose = expressionStack != null;
		if (firstClose && traceOn) {
			printTrace("End expression", false); //$NON-NLS-1$
			long totalTime = System.currentTimeMillis()-startExpressionTime;
			System.out.print(" Total expression evaluation time: "); //$NON-NLS-1$
			System.out.print(totalTime);
			System.out.print("ms."); //$NON-NLS-1$
		}
		try {
			expressionStack = null;
			expressionTypeStack = null;
			expressionProxies = null;
			exception = null;
			catchThrowable = null;
			saveStates = null;
		} finally {
			if (firstClose && traceOn)
				printTraceEnd();
		}
	}

	/**
	 * Pull the value. The value will be placed into the array passed in.
	 * It will be stored as value[0] = value value[1] = valuetype(Class).
	 * 
	 * @param value The value array to store the value and type into.
	 * @throws NoExpressionValueException
	 * @since 1.0.0
	 */
	public final void pullValue(Object[] value) throws NoExpressionValueException {
		if (traceOn)
			printTrace("Pull value:", false); //$NON-NLS-1$
		try {
			value[0] = popExpression();
			value[1] = popExpressionType(false);
		} finally {
			if (traceOn) {
				printObjectAndType(value[0], (Class) value[1]);
				printTraceEnd();
			}
		}
		close();
	}
	
	/**
	 * Pull the value of the expression proxy, dereferencing it if necessary. This is for resolution only purposes at the
	 * end of the expression being processed. Not meant for general access to the value of expression proxy. Use 
	 * {@link ExpressionProcesser#getExpressionProxyValue(int, Object[])} instead for general access to the value.
	 * 
	 * @param proxyid
	 * @param value
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.1.0
	 */
	public final void pullExpressionProxyValue(int proxyid, Object[] value) throws NoExpressionValueException {
		getExpressionProxyValue(proxyid, value, true, true);
	}
	
	/**
	 * Get the expression proxy value. If the expression has not yet been evaluated it will
	 * return false. If it has it will return true.
	 * @param proxyid
	 * @param value put value into value[0] and the type into value[1].
	 * @return <code>true</code> if successful, or <code>false</code> if the expression proxy was never resolved or doesn't exist.
	 * 
	 * @since 1.1.0
	 */
	public boolean getExpressionProxyValue(int proxyid, Object[] value) {
		try {
			return getExpressionProxyValue(proxyid, value, true, false);
		} catch (NoExpressionValueException e) {
			return false;
		}
	}
	
	/**
	 * Get the expression proxy value, or the NoExpressionValueException if not resolved. This
	 * is useful for callers that need to handle the proxy itself for failed calls.
	 * 
	 * @param proxyid
	 * @param value
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.1.0
	 */
	public void getExpressionProxy(int proxyid, Object[] value) throws NoExpressionValueException {
		getExpressionProxyValue(proxyid, value, true, false);
	}
	
	/*
	 * Internal method use to actually get the value, but to distinquish between pull and get of the public interface.
	 * Get will process the errors as normal execution errors, while pull will throw the errors. finalTrace is when
	 * this is the final call to return the values to the client. We will trace the results in that case.
	 * Return true if successful.
	 */
	private boolean getExpressionProxyValue(int proxyid, Object[] value, boolean pull, boolean finalTrace) throws NoExpressionValueException {
		// Note: This will throw the exceptions right away since this is called from outside to fill in the value and
		// so we are holding such exceptions.
		boolean doTrace = finalTrace && traceOn;
		try {
			if (expressionProxies != null && expressionProxies.size() > proxyid) {
				InternalExpressionProxy proxy = (InternalExpressionProxy) expressionProxies.get(proxyid);
				if (proxy != null && proxy.isSet()) {
					value[0] = proxy.getValue();
					if (value[0] instanceof VariableReference)
						value[0] = ((VariableReference) value[0]).dereference(); // Here we want the final current value.
					value[1] = proxy.getType();
					if (doTrace)
						if (value[1] != Void.TYPE) {
							printTrace("Return Proxy #" + proxyid + " Resolved to", false); //$NON-NLS-1$ //$NON-NLS-2$
							printObjectAndType(value[0], (Class) value[1]);
						} else
							printTrace("Return Proxy #" + proxyid + " Resolved to void.", false); //$NON-NLS-1$ //$NON-NLS-2$
					return true;

				} else {
					if (doTrace)
						printTrace("Return Proxy #" + proxyid + ": Not resolved", false); //$NON-NLS-1$ //$NON-NLS-2$
					NoExpressionValueException e = new NoExpressionValueException(InitparserTreeMessages.getString("ExpressionProcesser.GetExpressionProxyValue.ExpressionProxyNotSet_EXC_"), proxy); //$NON-NLS-1$
					if (pull)
						throw e;
					else
						processSyntaxException(e);
					return false;
				}
			} else {
				if (doTrace)
					printTrace("Return Proxy #" + proxyid + ": Never created.", false); //$NON-NLS-1$ //$NON-NLS-2$
				NoExpressionValueException e = new NoExpressionValueException(InitparserTreeMessages.getString("ExpressionProcesser.GetExpressionProxyValue.ExpressionProxyDoesntExist_EXC_")); //$NON-NLS-1$
				if (pull)
					throw e;
				else
					processSyntaxException(e);
				return false;
			}
		} finally {
			if (doTrace)
				printTraceEnd();
		}
	}
	
	/**
	 * Push the expression (just a value) onto the stack.
	 * 
	 * @param o
	 * @param t
	 * 
	 * @since 1.0.0
	 */
	public final void pushExpression(Object o, Class t) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		if (traceOn) {
			printTrace("Push: ", ignore); //$NON-NLS-1$
			printObjectAndType(o, t);
		}
		try {
			if (ignore)
				return;
			pushExpressionValue(o, t);
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Get the value of the expression proxy (from proxy id), and push the value onto the stack.
	 *  
	 * @param proxyid The proxy id of the ExpressionProxy to push as a value.
	 * 
	 * @since 1.0.0
	 */
	public final void pushExpressionProxy(int proxyid) {
		boolean ignore =(ignoreExpression != null || errorOccurred);
		if (traceOn)
			printTrace("Push Expression Proxy #"+proxyid, ignore); //$NON-NLS-1$
		try {
			if (ignore)
				return;
			if (expressionProxies != null && expressionProxies.size() > proxyid) {
				InternalExpressionProxy proxy = (InternalExpressionProxy) expressionProxies.get(proxyid);
				if (proxy != null && proxy.isSet()) {
					if (traceOn)
						printObjectAndType(proxy.getValue(), proxy.getType());
					pushExpressionValue(proxy.getValue(), proxy.getType());	// Can push a VariableReference. This is ok. When used it will then deref with the current value.
				} else
					processSyntaxException(new NoExpressionValueException("Proxy id: "+proxyid)); //$NON-NLS-1$
			} else
				processSyntaxException(new NoExpressionValueException("Proxy id: "+proxyid)); //$NON-NLS-1$
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Push a cast onto stack. The type passed in is either a String (with classname to cast to) or the
	 * type to cast to.
	 * @param type To cast to. If <code>String</code> then convert to type (using something like <code>Class.forName()</code>) or it is a Class
	 * 
	 * @since 1.0.0
	 */
	public final void pushCast(Class type) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		if (traceOn)
			printTrace("Cast to: "+type, ignore); //$NON-NLS-1$
		try {
			if (ignore)
				return;
			
			try {
				Object exp = popExpression();
				Class exptype = popExpressionType(false);
				
				pushExpressionValue(castBean(type, exp, exptype), type);
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}
	
	/**
	 * Cast a bean into the return type. If the return type is not primitive, then
	 * the bean is left alone, however it is checked to be an instance of
	 * the return type. If the return type is primitive, then the
	 * correct primitive wrapper is created from the bean (bean must be a number or character or boolean primitve so
	 * that cast will work).
	 * <p>
	 * However if can't be cast for primitive or if not an instance of the
	 * returntype for objects, a ClassCastException will be raised.
	 * <p>
	 * This is a helper method for expression processer to cast a bean. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.
	 * 
	 * @param returnType
	 * @param bean
	 * @param beanType The type that bean is supposed to be (e.g. even though it is a Number, it actually represents a primitive).
	 * @return The cast bean (either to the appropriate primitive wrapper type or bean)
	 * 
	 * @throws ClassCastException
	 * @since 1.0.0
	 */
	protected final Object castBean(Class returnType, Object bean, Class beanType) throws ClassCastException {
		// Cast uses true value and true class of bean, not expected type (i.e. not beanType).
		if (bean == null)
			if (!returnType.isPrimitive())
				return bean;	// bean is null, and return type is not primitive, so this is a valid cast.
			else 
				throwClassCast(returnType, bean);
		else if (returnType.equals(bean.getClass()))
			return bean;	// They are already the same.
		else if (!returnType.isPrimitive()) {
			if (!beanType.isPrimitive() && returnType.isInstance(bean))
				return bean;
			else
				throwClassCast(returnType, bean);	// Either bean type was wrappering primitive or not instanceof returntype.
		} else {
			if (!beanType.isPrimitive())
				throwClassCast(returnType, bean);	// bean type was not wrappering a primitive. Can't cast to primitive.
			// It is return type of primitive. Now convert to correct primitive.
			if (returnType == Boolean.TYPE)
				if (bean instanceof Boolean)
					return bean;
				else
					throwClassCast(returnType, bean);
			else {
				if (bean instanceof Number) {
					if (returnType == Integer.TYPE)
						if (bean instanceof Integer)
							return bean;
						else
							return new Integer(((Number) bean).intValue());
					else if (returnType == Byte.TYPE)
						if (bean instanceof Byte)
							return bean;
						else
							return new Byte(((Number) bean).byteValue());
					else if (returnType == Character.TYPE)
						if (bean instanceof Character)
							return bean;
						else
							return new Character((char) ((Number) bean).intValue());
					else if (returnType == Double.TYPE)
						if (bean instanceof Double)
							return bean;
						else
							return new Double(((Number) bean).doubleValue());
					else if (returnType == Float.TYPE)
						if (bean instanceof Float)
							return bean;
						else
							return new Float(((Number) bean).floatValue());
					else if (returnType == Long.TYPE)
						if (bean instanceof Long)
							return bean;
						else
							return new Long(((Number) bean).longValue());
					else if (returnType == Short.TYPE)
						if (bean instanceof Short)
							return bean;
						else
							return new Short(((Number) bean).shortValue());	
					else
						throwClassCast(returnType, bean);
				} else if (bean instanceof Character) {
					if (returnType == Character.TYPE)
						return bean;
					else if (returnType == Integer.TYPE)
						return new Integer(((Character) bean).charValue());
					else if (returnType == Byte.TYPE)
						return new Byte((byte) ((Character) bean).charValue());
					else if (returnType == Double.TYPE)
						return new Double(((Character) bean).charValue());
					else if (returnType == Float.TYPE)
						return new Float(((Character) bean).charValue());
					else if (returnType == Long.TYPE)
						return new Long(((Character) bean).charValue());
					else if (returnType == Short.TYPE)
						return new Short((short) ((Character) bean).charValue());	
					else
						throwClassCast(returnType, bean);
				} else
					throwClassCast(returnType, bean);
			}
			
		}
		return null;	// It should never get here;
	}
	
	private void throwClassCast(Class returnType, Object bean) throws ClassCastException {
		throw new ClassCastException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.CannotCastXToY_EXC_"), new Object[] {bean != null ? bean.getClass().getName() : null, returnType.getName()})); //$NON-NLS-1$
	}

	/**
	 * Return the primitive type that the wrapper bean represents (i.e. Boolean instance returns Boolean.TYPE) 
	 * <p>
	 * This is a helper method for expression processer to get the primitive type. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.

	 * @param bean
	 * @return the primitive type class of the given bean.
	 * @throws IllegalArgumentException if bean is <code>null</code> or not of the type that can be converted to a primitive.
	 * 
	 * @since 1.0.0
	 */
	protected final Class getPrimitiveType(Object bean) throws IllegalArgumentException {
		if (bean instanceof Boolean)
			return Boolean.TYPE;
		else if (bean instanceof Integer)
			return Integer.TYPE;
		else if (bean instanceof Byte)
			return Byte.TYPE;
		else if (bean instanceof Character)
			return Character.TYPE;
		else if (bean instanceof Double)
			return Double.TYPE;
		else if (bean instanceof Float)
			return Float.TYPE;
		else if (bean instanceof Long)
			return Long.TYPE;
		else if (bean instanceof Short)
			return Short.TYPE;
		else
			throw new IllegalArgumentException(bean != null ? bean.getClass().getName() : "null"); //$NON-NLS-1$
	}
	
	private static final Object IFELSE_IGNORE = "IF/ELSE IGNORE";	// Flag for if/else in ingore //$NON-NLS-1$
	private int ifElseNesting = 0;	// Nesting of if/else expressions.
	private int ifElseIgnoreNestCount = 0;	// When ignoring if/else expressions, ignore until this nest count.
	private boolean ifElseSkipTruePart;

	
	/**
	 * Push an if test expression.
	 * @param hasElseClause
	 * 
	 * @since 1.0.0
	 */
	public final void pushIfElse() {
		try {
			boolean ignore = true;
			try {
				if (errorOccurred)
					return;
				// Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
				// we can get the expression grouping correct.
				ifElseNesting++;	// We have the test.
	
				if (ignoreExpression != null)
					return;
				ignore = false;
			} finally {
				if (traceOn)
					printTrace("If test condition", ignore); //$NON-NLS-1$
			}
					
			try {
				Object condition = popExpression();
				Class type = popExpressionType(false);
				if (type != Boolean.TYPE)
					throwClassCast(Boolean.TYPE, condition);
				if (traceOn) {
					System.out.print(" Test Result="+condition); //$NON-NLS-1$
					printTraceEnd();
					indent(true);
					printTrace("Begin True Expression.", ignore); //$NON-NLS-1$
					printTraceEnd();
					indent(true);
				}				
				if (((Boolean) condition).booleanValue()) {
					// Condition was true.
					// Do nothing. Let true condition be processed.
				} else {
					// Condition was false.
					ifElseSkipTruePart = true;	// Tell the true condition should be ignored.
					ignoreExpression = IFELSE_IGNORE;
					ifElseIgnoreNestCount = ifElseNesting;
				}
				// We don't put anything back on the stack because the condition test is not ever returned.
				// The appropriate true or false condition evaluation will be left on the stack.
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}

	/**
	 * Push an if/else clause. It can be any clause of the if (true, or false clause).
	 * @param clauseType
	 * 
	 * @since 1.0.0
	 */
	public final void pushIfElse(InternalIfElseOperandType clauseType) {
		try {
			boolean ignore = true;
			if (errorOccurred)
				return;
			// Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
			// we can get the expression grouping correct.
			switch (clauseType.getValue()) {
			case InternalIfElseOperandType.TRUE_CLAUSE_VALUE:
					if (traceOn) {
						indent(false);
						printTrace("Begin False Expression.", ignore); //$NON-NLS-1$
						printTraceEnd();
						indent(true);
					}
					if (ifElseSkipTruePart && ignoreExpression == IFELSE_IGNORE && ifElseIgnoreNestCount == ifElseNesting) {
						// stop ignoring, we've ignored the true condition of interest.
						ignoreExpression = null;
						return; // However, leave because since this condition was ignored.
					}
					break;
				case InternalIfElseOperandType.ELSE_CLAUSE_VALUE:
					if (traceOn) {
						indent(false);
						indent(false);
						printTrace("End IF/ELSE Expression.", ignore); //$NON-NLS-1$
						printTraceEnd();
					}					
					int currentNesting = ifElseNesting--;
					if (ignoreExpression == IFELSE_IGNORE && ifElseIgnoreNestCount == currentNesting) {
						// stop ignoring, we've ignored the false condition of interest.
						ignoreExpression = null;
						return; // However, leave because since this condition was ignored.
					}
			}
	
				if (ignoreExpression != null)
					return;
				ignore = false;

					
			try {
				switch (clauseType.getValue()) {
					case InternalIfElseOperandType.TRUE_CLAUSE_VALUE:
						ifElseSkipTruePart = false;	// Tell the false condition should be ignored.
						ignoreExpression = IFELSE_IGNORE;
						ifElseIgnoreNestCount = ifElseNesting;
						break;
					case InternalIfElseOperandType.ELSE_CLAUSE_VALUE:
						// There's nothing to do, if it was ignored due to true, we wouldn't of gotton here.
						// If it wasn't ignored, then the result of the false expression is on the stack, which is what it should be.
						break;
				}
			} catch (RuntimeException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}

	/**
	 * Push the instanceof expression.  The type passed in is either a String (with classname to test against) or the
	 * type to test against.
	 * @param type To test against.
	 * @since 1.0.0
	 */
	public final void pushInstanceof(Class type) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		if (traceOn)
			printTrace("Instanceof type: "+type, ignore); //$NON-NLS-1$
		try {
			if (ignore)
				return;
			
			try {
				Object exp = popExpression();
				Class exptype = popExpressionType(false);
				pushExpressionValue(Boolean.valueOf(isInstance(type, exp, exptype)), Boolean.TYPE);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (RuntimeException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Test if instance of. It will make sure that primitive to non-primitive is not permitted.
	 * This is a true instance of, which means null IS NOT AN instance of any type. This is
	 * different then assignable from, in that case null can be assigned to any class type.
	 * <p>
	 * This is a helper method for expression processer to do isInstance. Since it is a helper method it doesn't
	 * check nor process exceptions.

	 * @param type
	 * @param bean
	 * @param beanType
	 * @return
	 * 
	 * @since 1.0.0
	 */
	protected final boolean isInstance(Class type, Object bean, Class beanType) {
		if (type.isPrimitive())
			return beanType.isPrimitive() && type == beanType;	// Can't use isInstance because for a primitive type isInstance returns false.
		else 
			return type.isInstance(bean);
	}
	
	/**
	 * Push new instance from string.
	 * @param initializationString
	 * @param resultType expected result type. If it isn't of that type, a classcast will be processed. 
	 * @param classloader classloader to use for finding classes, or <code>null</code> to use classloader of InitializationStringParser.class.
	 * 
	 * @since 1.1.0
	 */
	public final void pushNewInstanceFromString(String initializationString, Class resultType, ClassLoader classloader) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		if (traceOn)
			printTrace("New instance from string: \""+initializationString+"\" Type="+resultType, ignore); //$NON-NLS-1$ //$NON-NLS-2$
		try {
			if (ignore)
				return;
			
			try {
				InitializationStringParser parser = InitializationStringParser.createParser(initializationString, classloader);
				Object newValue = parser.evaluate();
				newValue = castBean(resultType, newValue, parser.getExpectedType());
				pushExpressionValue(newValue, resultType);
			} catch (RuntimeException e) {
				processException(e);
			} catch (InitializationStringEvaluationException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}

	}

	/**
	 * Push prefix expression.
	 * @param operator 
	 * @since 1.0.0
	 */
	public final void pushPrefix(PrefixOperator operator) {
		try {
			if (ignoreExpression != null || errorOccurred) {
				if (traceOn)
					printTrace("Prefix: \'"+operator+"\'", true); //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
			
			if (operator == PrefixOperator.PRE_PLUS)
				return;	// Do nothing. "+" doesn't affect the result of the current top expression.
	
			if (traceOn)
				printTrace("Prefix: \'"+operator+"\' ", false); //$NON-NLS-1$ //$NON-NLS-2$
	
			try {
				Object exp = popExpression();
				Class exptype = popExpressionType(false);
				if (!exptype.isPrimitive())
					throwInvalidPrefix(operator, exp);
				
				int primTypeEnum = getEnumForPrimitive(exptype);
				switch (operator.getValue()) {
					case PrefixOperator.PRE_MINUS_VALUE:
						switch (primTypeEnum) {
							case BOOLEAN:
								throwInvalidPrefix(operator, exp);						
							case BYTE:
								exp = new Integer(-((Number) exp).byteValue());
								break;
							case CHAR:
								exp = new Integer(-((Character) exp).charValue());
								break;
							case DOUBLE:
								exp = new Double(-((Number) exp).doubleValue());
								break;
							case FLOAT:
								exp = new Float(-((Number) exp).floatValue());
								break;
							case INT:
								exp = new Integer(-((Number) exp).intValue());
								break;
							case LONG:
								exp = new Long(-((Number) exp).longValue());
								break;
							case SHORT:
								exp = new Integer(-((Number) exp).shortValue());
								break;
						}
						exptype = getPrimitiveType(exp);	// It can actually change the type.				
						break;
						
					case PrefixOperator.PRE_COMPLEMENT_VALUE:
						switch (primTypeEnum) {
							case BOOLEAN:
							case DOUBLE:
							case FLOAT:
								throwInvalidPrefix(operator, exp);						
							case BYTE:
								exp = new Integer(~((Number) exp).byteValue());
								break;
							case CHAR:
								exp = new Integer(~((Character) exp).charValue());
								break;
							case INT:
								exp = new Integer(~((Number) exp).intValue());
								break;
							case LONG:
								exp = new Long(~((Number) exp).longValue());
								break;
							case SHORT:
								exp = new Integer(~((Number) exp).shortValue());
								break;
						}
						exptype = getPrimitiveType(exp);	// It can actually change the type.
						break;
					case PrefixOperator.PRE_NOT_VALUE:
						switch (primTypeEnum) {
							case BOOLEAN:
								exp = !((Boolean) exp).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
								break;
							case BYTE:
							case CHAR:
							case DOUBLE:
							case FLOAT:
							case INT:
							case LONG:
							case SHORT:
								throwInvalidPrefix(operator, exp);						
						}				
						break;
					}
				
				if (traceOn)
					printObjectAndType(exp, exptype);
				pushExpressionValue(exp, exptype);	// Push the result back on the stack.
	
			} catch (IllegalArgumentException e) {
				processSyntaxException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (RuntimeException e) {
				processException(e);
			} 
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}
	
	/**
	 * Assign the right expression to the left expression.
	 * @since 1.1.0
	 */
	public final void pushAssignment() {
		if (ignoreExpression != null || errorOccurred) {
			if (traceOn) {
				printTrace("Assignment", true); //$NON-NLS-1$
				printTraceEnd();
			}
			return;
		}
		
		try {
			// KLUDGE: The only reason leftValue/refType are outside of try/finally is because
			// of tracing. pushExpression() does its own trace statements, so we need to end
			// our trace before calling pushExpression. 
			Object leftValue;
			Class refType;
			try {
				if (traceOn)
					printTrace("Assignment: ", false);			 //$NON-NLS-1$	
				// The order on the stack is right then left operand.
				// First the right operand
				Object value = popExpression();
				Class type = popExpressionType(false);

				// Next the left operand, should be a reference.
				VariableReference left = (VariableReference) popExpression(false); // Don't dereference it.
				refType = popExpressionType(false);

				if (traceOn)
					printObjectAndType(left, refType);

				leftValue = left.set(value, type);
			} finally {
				if (traceOn)
					printTraceEnd();
			}
			
			// Now do assignment and return the value to the stack.
			pushExpression(leftValue, refType);	// The type of the result is the type of the reference.

		} catch (IllegalArgumentException e) {
			processException(e);
		} catch (NoExpressionValueException e) {
			processSyntaxException(e);
		} catch (IllegalAccessException e) {
			processException(e);
		} catch (RuntimeException e) {
			processException(e);
		}
			
	}
	
	/**
	 * Assign the expression proxy to the top expression value.
	 * 
	 * @param proxy
	 * 
	 * @since 1.1.0
	 */
	public final void pushAssignment(InternalExpressionProxy proxy) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		try {
			if (traceOn) {
				printTrace("Assign to Proxy #"+proxy.getProxyID(), ignore); //$NON-NLS-1$
			}
			if (ignore)
				return;
			
			try {
				assignToExpressionProxyFromTopStackEntry(proxy);
				if (traceOn)
					printObjectAndType(proxy.getValue(), proxy.getType());
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (RuntimeException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}

	}

	/**
	 * Assign the top stack entry to the new expression proxy and allocate it for callback later.
	 * @param proxy
	 * @throws NoExpressionValueException
	 * 
	 * @since 1.1.0
	 */
	protected void assignToExpressionProxyFromTopStackEntry(InternalExpressionProxy proxy) throws NoExpressionValueException {
		Object value = getExpression(1);
		Class type = getExpressionType(1, true);
		if (value instanceof VariableReference)
			value = ((VariableReference) value).dereference();	// Here we want the final current value.

		proxy.setProxy(value, type);
		allocateExpressionProxy(proxy);
	}

	/**
	 * Allocate an expression proxy. This is used to make an expression proxy known to the processor. The expression proxy must
	 * have been setProxy() at this point. This is used to assign from the top of the stack or to add from outside an evaluated proxy
	 * to be used later by others.
	 * 
	 * @param proxy
	 * 
	 * @since 1.1.0
	 */
	public void allocateExpressionProxy(InternalExpressionProxy proxy) {
		int minSize = proxy.getProxyID()+1;
		if (expressionProxies == null)
			expressionProxies = new ArrayList(minSize+10);	// Allow room to grow ten more.
		else if (expressionProxies.size() < minSize)
			expressionProxies.ensureCapacity(minSize+10);	// Allow room to grow ten more.
		int fill = minSize-expressionProxies.size();	// Number of "null" fill entries needed. Probably shouldn't occur, but to be safe.
		if (fill > 0) {
			while (--fill > 0)
				expressionProxies.add(null);
			expressionProxies.add(proxy);
		} else
			expressionProxies.set(proxy.getProxyID(), proxy);	// Already large enough, replace entry.

	}

	/**
	 * The primitive enums. 
	 * NOTE: Their order must not changed. They are in order of permitted widening.
	 * 
	 */
	protected static final int
		BOOLEAN = 0,
		BYTE = 1,
		SHORT = 2,	
		CHAR = 3,
		INT = 4,
		LONG = 5,
		FLOAT = 6,
		DOUBLE = 7;
		
		
	
	/**
	 * Get the enum constant for the type of primitive passed in.
	 * <p>
	 * This is a helper method for expression processer to get the enum for the primitive type. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.

	 * @param primitiveType
	 * @return
	 * @throws IllegalArgumentException if type is not a primitive.
	 * 
	 * @see ExpressionProcesser#BOOLEAN
	 * @since 1.0.0
	 */
	protected final int getEnumForPrimitive(Class primitiveType) throws IllegalArgumentException {
		if (primitiveType == Boolean.TYPE)
			return BOOLEAN;
		else if (primitiveType == Integer.TYPE)
			return INT;
		else if (primitiveType == Byte.TYPE)
			return BYTE;
		else if (primitiveType == Character.TYPE)
			return CHAR;
		else if (primitiveType == Double.TYPE)
			return DOUBLE;
		else if (primitiveType == Float.TYPE)
			return FLOAT;
		else if (primitiveType == Long.TYPE)
			return LONG;
		else if (primitiveType == Short.TYPE)
			return SHORT;
		else
			throw new IllegalArgumentException(primitiveType != null ? primitiveType.getName() : "null"); //$NON-NLS-1$
	}
	
	private void throwInvalidPrefix(PrefixOperator operator, Object exp) throws IllegalArgumentException {
		throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfPrefixOperator_EXC_"), new Object[] {exp != null ? exp.toString() : null, operator.toString()})); //$NON-NLS-1$
	}		
	
	private static final Object INFIX_IGNORE = "INFIX IGNORE";	// Flag for infix in ingore //$NON-NLS-1$
	private int infixNesting = 0;	// Nesting of infix expressions.
	private int infixIgnoreNestCount = 0;	// When ignoring infix expressions, ignore until this nest count.
	/**
	 * Push the infix expression onto the stack.
	 * @param operator
	 * @param operandType The operator type. Left, right, other.
	 * @since 1.0.0
	 */
	public final void pushInfix(InfixOperator operator, InternalInfixOperandType operandType) {
		try {
			boolean ignore = true;
			try {
				if (errorOccurred) {
					return;
				}
				// Slightly different here in that if an ignored occurred we still need to process at least part of it so that
				// we can get the expression grouping correct.
				if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
					infixNesting++;
				else if (operandType == InternalInfixOperandType.INFIX_LAST_OPERAND) {
					int currentNest = infixNesting--;
					if (ignoreExpression == INFIX_IGNORE && currentNest == infixIgnoreNestCount) {
						// We were ignoring, and it was this expression that was being ignore.
						// We have received the last operand of the nested expression that was being ignored,
						// so we can stop ignoring. But we still leave since the value of the expression is on the
						// top of the stack.
						ignoreExpression = null;
						return;
					}
				}
	
				if (ignoreExpression != null)
					return;
				ignore = false;
			} finally {
				if (traceOn)
					printTrace("Infix: "+operator, ignore); //$NON-NLS-1$
			}
			
			try {
				Object right = null;
				Class rightType = null;
				if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
					// We are not the left operand, so the stack has the right on the top, followed by the left.
					right = popExpression();
					rightType = popExpressionType(false);
				} 
				
				Object value = popExpression();
				Class valueType = popExpressionType(false);
	
				switch (operator.getValue()) {
					case InfixOperator.IN_AND_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_AND);
						testValidBitType(rightType, InfixOperator.IN_AND);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) & getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) & getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_CONDITIONAL_AND_VALUE:
						// This is tricky.
						// First if this is left type, then just continue.
						// Else if this other or last, then need to make it the new value.
						if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
							value = right;
							valueType = rightType;
						}
							
						//If the value is now false, we need to ignore the rest.
						if (valueType != Boolean.TYPE)
							throwInvalidInfix(operator, value);
						if (!((Boolean) value).booleanValue() && operandType != InternalInfixOperandType.INFIX_LAST_OPERAND)
							startInfixIgnore();	// Start ignoring because we know the value of the expression at this point. It is false.
						break;
					case InfixOperator.IN_CONDITIONAL_OR_VALUE:
						// This is tricky.
						// First if this is left type, then just continue.
						// Else if this other or last, then need to make it the new value.
						if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
							value = right;
							valueType = rightType;
						}
						
						//If the value is now true, we need to ignore the rest.
						if (valueType != Boolean.TYPE)
							throwInvalidInfix(operator, value);
						if (((Boolean) value).booleanValue() && operandType != InternalInfixOperandType.INFIX_LAST_OPERAND)
							startInfixIgnore(); // Start ignoring because we know the value of the expression at this point. It is true.
						break;
					case InfixOperator.IN_DIVIDE_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_DIVIDE);
						testValidArithmeticType(rightType, InfixOperator.IN_DIVIDE);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, the result will be double.
							value = new Double(getDouble(value) / getDouble(right));
							valueType = Double.TYPE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, the result will be float.
							value = new Float(getFloat(value) / getFloat(right));
							valueType = Float.TYPE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) / getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it will result in an int, even if both sides are short.
							value = new Integer(getInt(value) / getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_EQUALS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						// We should never get extended operator for this, but we'll ignore the possibility.
						if (valueType.isPrimitive() && rightType.isPrimitive()) {
							// Primitives require more testing than just ==. boolean primitives 
							if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
								// If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
								if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
									value = Boolean.FALSE;
								else
									value = (((Boolean) value).booleanValue() == ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
							} else {
								// Now do number tests since not boolean primitive, only numbers are left
								if (valueType == Double.TYPE || rightType == Double.TYPE) {
									// If either side is double, compare as double.
									value = (getDouble(value) == getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
									// If either side is float, compare as float.
									value = (getFloat(value) == getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
									// If either side is long, the compare as long.
									value = (getLong(value) == getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else {
									// Else it will compare as int, even if both sides are short.
									value = (getInt(value) == getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
								}
							}
						} else if (valueType.isPrimitive() || rightType.isPrimitive())
							value = Boolean.FALSE;	// Can't be true if one side prim and the other isn't
						else {
							// Just do object ==
							value = (value == right) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_GREATER_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_GREATER);
						testValidArithmeticType(rightType, InfixOperator.IN_GREATER);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, compare will be double.
							value = (getDouble(value) > getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, compare will be float.
							value = (getFloat(value) > getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, compare will be long.
							value = (getLong(value) > getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else {
							// Else compare will be int, even if both sides are short.
							value = (getInt(value) > getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_GREATER_EQUALS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_GREATER_EQUALS);
						testValidArithmeticType(rightType, InfixOperator.IN_GREATER_EQUALS);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, compare will be double.
							value = (getDouble(value) >= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, compare will be float.
							value = (getFloat(value) >= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, compare will be long.
							value = (getLong(value) >= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else {
							// Else compare will be int, even if both sides are short.
							value = (getInt(value) >= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_LEFT_SHIFT_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_LEFT_SHIFT);
						testValidBitType(rightType, InfixOperator.IN_LEFT_SHIFT);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) << getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) << getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_LESS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_LESS);
						testValidArithmeticType(rightType, InfixOperator.IN_LESS);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, compare will be double.
							value = (getDouble(value) < getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, compare will be float.
							value = (getFloat(value) < getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, compare will be long.
							value = (getLong(value) < getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else {
							// Else compare will be int, even if both sides are short.
							value = (getInt(value) < getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_LESS_EQUALS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_LESS_EQUALS);
						testValidArithmeticType(rightType, InfixOperator.IN_LESS_EQUALS);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, compare will be double.
							value = (getDouble(value) <= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, compare will be float.
							value = (getFloat(value) <= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, compare will be long.
							value = (getLong(value) <= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
						} else {
							// Else compare will be int, even if both sides are short.
							value = (getInt(value) <= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_MINUS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_MINUS);
						testValidArithmeticType(rightType, InfixOperator.IN_MINUS);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, the result will be double.
							value = new Double(getDouble(value) - getDouble(right));
							valueType = Double.TYPE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, the result will be float.
							value = new Float(getFloat(value) - getFloat(right));
							valueType = Float.TYPE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) - getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it will result in an int, even if both sides are short.
							value = new Integer(getInt(value) - getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_NOT_EQUALS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						// We should never get extended operator for this, but we'll ignore the possibility.
						if (valueType.isPrimitive() && rightType.isPrimitive()) {
							// Primitives require more testing than just ==. boolean primitives 
							if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
								// If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
								if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
									value = Boolean.TRUE;
								else
									value = (((Boolean) value).booleanValue() != ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
							} else {
								// Now do number tests since not boolean primitive, only numbers are left
								if (valueType == Double.TYPE || rightType == Double.TYPE) {
									// If either side is double, compare as double.
									value = (getDouble(value) != getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
									// If either side is float, compare as float.
									value = (getFloat(value) != getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
									// If either side is long, the compare as long.
									value = (getLong(value) != getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
								} else {
									// Else it will compare as int, even if both sides are short.
									value = (getInt(value) != getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
								}
							}
						} else if (valueType.isPrimitive() || rightType.isPrimitive())
							value = Boolean.TRUE;	// Must be true if one side prim and the other isn't
						else {
							// Just do object !=
							value = (value != right) ? Boolean.TRUE : Boolean.FALSE;
						}
						valueType = Boolean.TYPE;	// We know result will be a boolean.
						break;
					case InfixOperator.IN_OR_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_OR);
						testValidBitType(rightType, InfixOperator.IN_OR);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) | getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) | getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_PLUS_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND) {
							if (valueType == String.class) {
								// Special. left argument is a string, so we want to store a string buffer instead
								// since we know we will be appending to it. 
								value = new StringBuffer((String) value);
							}	
							break;	// Do nothing with first operand
						}
						
						testValidPlusType(valueType, rightType);
						if (valueType == String.class || rightType == String.class) {
							// Special we have a string on one side. Need to do it as strings instead.
							// We are going to be tricky in that we will store a StringBuffer on the stack (if not last operand)
							// but call it a string.
							StringBuffer sb = null;
							if (valueType == String.class) {
								sb = (StringBuffer) value;	// We know that if the value (left) is string type, we've already converted it to buffer.
							} else {
								// The right is the one that introduces the string, so we change the value over to a string buffer.
								sb = new StringBuffer(((String) right).length()+16);	// We can't put the value in yet, need to get left into it.
								appendToBuffer(sb, value, valueType);	// Put the left value in now
								value = sb;
								valueType = String.class;	// Make it a string class
							}
							appendToBuffer(sb, right, rightType);
							// Now if we are the last operand, we should get rid of the buffer and put a true string back in.
							if (operandType == InternalInfixOperandType.INFIX_LAST_OPERAND)
								value = sb.toString();
						} else if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, the result will be double.
							value = new Double(getDouble(value) + getDouble(right));
							valueType = Double.TYPE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, the result will be float.
							value = new Float(getFloat(value) + getFloat(right));
							valueType = Float.TYPE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) + getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it will result in an int, even if both sides are short.
							value = new Integer(getInt(value) + getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_REMAINDER_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_REMAINDER);
						testValidArithmeticType(rightType, InfixOperator.IN_REMAINDER);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, the result will be double.
							value = new Double(getDouble(value) % getDouble(right));
							valueType = Double.TYPE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, the result will be float.
							value = new Float(getFloat(value) % getFloat(right));
							valueType = Float.TYPE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) % getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it will result in an int, even if both sides are short.
							value = new Integer(getInt(value) % getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_RIGHT_SHIFT_SIGNED_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_RIGHT_SHIFT_SIGNED);
						testValidBitType(rightType, InfixOperator.IN_RIGHT_SHIFT_SIGNED);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) >> getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) >> getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_RIGHT_SHIFT_UNSIGNED_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_RIGHT_SHIFT_UNSIGNED);
						testValidBitType(rightType, InfixOperator.IN_RIGHT_SHIFT_UNSIGNED);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) >>> getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) >>> getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_TIMES_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidArithmeticType(valueType, InfixOperator.IN_TIMES);
						testValidArithmeticType(rightType, InfixOperator.IN_TIMES);
						if (valueType == Double.TYPE || rightType == Double.TYPE) {
							// If either side is double, the result will be double.
							value = new Double(getDouble(value) * getDouble(right));
							valueType = Double.TYPE;
						} else if (valueType == Float.TYPE || rightType == Float.TYPE) {
							// If either side is float, the result will be float.
							value = new Float(getFloat(value) * getFloat(right));
							valueType = Float.TYPE;
						} else if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) * getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it will result in an int, even if both sides are short.
							value = new Integer(getInt(value) * getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					case InfixOperator.IN_XOR_VALUE:
						if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
							break;	// Do nothing with first operand
						
						testValidBitType(valueType, InfixOperator.IN_XOR);
						testValidBitType(rightType, InfixOperator.IN_XOR);
						if (valueType == Long.TYPE || rightType == Long.TYPE) {
							// If either side is long, the result will be long.
							value = new Long(getLong(value) ^ getLong(right));
							valueType = Long.TYPE;
						} else {
							// Else it is int. (even two shorts together produce an int).
							value = new Integer(getInt(value) ^ getInt(right));
							valueType = Integer.TYPE;
						}
						break;
					} 
				
				if (traceOn)
					printObjectAndType(value, valueType);
				pushExpressionValue(value, valueType);	// Push the result back on the stack.
	
			} catch (IllegalArgumentException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (RuntimeException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}

	/**
	 * Start ignoring rest of the current infix expression.
	 * 
	 * @since 1.1.0
	 */
	private void startInfixIgnore() {
		ignoreExpression = INFIX_IGNORE;
		infixIgnoreNestCount = infixNesting;	// Ignore until we get back to the current nesting.

	}

	/**
	 * Get int value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
	 * Anything else will cause a class cast error.
	 * <p>
	 * This is a helper method for expression processer to get the int value of the object. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.
	 * @param bean
	 * @return the int value of the number/character
	 * @throws ClassCastException
	 * 
	 * @since 1.0.0
	 */
	protected final int getInt(Object bean) throws ClassCastException {
		return (bean instanceof Number) ? ((Number) bean).intValue() : ((Character) bean).charValue();
	}
	
	/**
	 * Get float value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
	 * Anything else will cause a class cast error.
	 * <p>
	 * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.
	 * @param bean 
	 * @return float value of the Number/character
	 * @throws ClassCastException
	 * @since 1.0.0
	 */
	protected final float getFloat(Object bean) throws ClassCastException {
		return (bean instanceof Number) ? ((Number) bean).floatValue() : ((Character) bean).charValue();
	}

	/**
	 * Get double value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
	 * Anything else will cause a class cast error.
	 * <p>
	 * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.
	 * 
	 * @param bean
	 * @return double value of the Number/Character.
	 * @throws ClassCastException
	 * @since 1.0.0
	 */
	protected final double getDouble(Object bean) throws ClassCastException {
		return (bean instanceof Number) ? ((Number) bean).doubleValue() : ((Character) bean).charValue();
	}
	
	/**
	 * Get long value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
	 * Anything else will cause a class cast error.
	 * <p>
	 * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
	 * check nor process the exception. It throws it. Callers must handle it as they see fit.
	 * 
	 * @param bean
	 * @return
	 * @throws ClassCastException
	 * @since 1.0.0
	 */
	protected final long getLong(Object bean) throws ClassCastException {
		return (bean instanceof Number) ? ((Number) bean).longValue() : ((Character) bean).charValue();
	}
	
	private void throwInvalidInfix(InfixOperator operator, Object value) throws IllegalArgumentException {
		throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfOperator_EXC_"), new Object[] {value != null ? value.toString() : null, operator.toString()})); //$NON-NLS-1$
	}
	
	private void testValidBitType(Class type, InfixOperator operator) {
		if (!type.isPrimitive() || type == Boolean.TYPE || type == Double.TYPE|| type == Float.TYPE)
			throwInvalidInfix(operator, type);
	}
	
	private void testValidArithmeticType(Class type, InfixOperator operator) {
		if (!type.isPrimitive() || type == Boolean.TYPE)
			throwInvalidInfix(operator, type);
	}

	private void testValidPlusType(Class left, Class right) {
		// Plus is special in that string objects are also valid.
		if (left == String.class || right == String.class)
			return;	// As long as one side is string. Anything is valid.
		// If neither is string, then standard arithmetic test.
		testValidArithmeticType(left, InfixOperator.IN_PLUS);
		testValidArithmeticType(right, InfixOperator.IN_PLUS);
	}
	
	private void appendToBuffer(StringBuffer sb, Object value, Class valueType) {
		if (value == null)
			sb.append((Object)null);
		else if (valueType == String.class)
			sb.append((String) value);
		else if (valueType.isPrimitive()) {
			switch (getEnumForPrimitive(valueType)) {
				case BOOLEAN:
					sb.append(((Boolean) value).booleanValue());
					break;
				case BYTE:
					sb.append(((Number) value).byteValue());
					break;
				case CHAR:
					sb.append(((Character) value).charValue());
					break;
				case DOUBLE:
					sb.append(((Number) value).doubleValue());
					break;
				case FLOAT:
					sb.append(((Number) value).floatValue());
					break;
				case INT:
					sb.append(((Number) value).intValue());
					break;
				case LONG:
					sb.append(((Number) value).longValue());
					break;
				case SHORT:
					sb.append(((Number) value).shortValue());
					break;		
			}
		} else {
			// Just an object.
			sb.append(value);
		}
	}
	
	/**
	 * Push the array access expression.
	 * 
	 * @param indexCount Number of dimensions being accessed
	 * @since 1.0.0
	 */
	public final void pushArrayAccess(int indexCount) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		
		if (traceOn) {
			printTrace("Array Access["+indexCount+']', ignore); //$NON-NLS-1$
		}
		try {
			if (ignore)
				return;
			
			try {
				// We need to pop off the args. The topmost will be the rightmost index, and the bottom most will be the array itself.
				int[] arguments = new int[indexCount];
				// Fill the arg array in reverse order.
				for(int i=indexCount-1; i >= 0; i--) {
					Object index = popExpression();
					Class indexType = popExpressionType(false);
					if (indexType.isPrimitive() && (indexType == Integer.TYPE || indexType == Short.TYPE || indexType == Character.TYPE || indexType == Byte.TYPE)) {
						arguments[i] = getInt(index);
					} else
						throwClassCast(Integer.TYPE, index);
				}
				
				Object array = popExpression();
				Class arrayType = popExpressionType(false);
				if (arrayType.isArray()) {
					// First figure out how many dimensions are available. Stop when we hit indexcount because we won't be going further.
					int dimcount = 0;
					Class[] componentTypes = new Class[indexCount];	// 
					Class componentType = arrayType;
					while (dimcount < indexCount && componentType.isArray()) {
						componentTypes[dimcount++] = componentType = componentType.getComponentType();
					}
					
					if (dimcount < indexCount)
						throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.XIsGreaterThanNumberOfDimensionsInArray_EXC_"), new Object[] {new Integer(indexCount), new Integer(dimcount)})); //$NON-NLS-1$
					
					// Now start accessing one index at a time, stop just before the last one. The last one will be turned into an ArrayAccessReference.
					Object value = array;	// Final value, start with full array.
					int pullCount = indexCount-1;
					for(int i=0; i<pullCount; i++) {
						value = Array.get(value, arguments[i]);
					}
					ArrayAccessReference arrayValue = ArrayAccessReference.createArrayAccessReference(value, arguments[pullCount]);
					if (traceOn)
						printObjectAndType(arrayValue, componentTypes[pullCount]);
					pushExpressionValue(arrayValue, componentTypes[pullCount]);
				}  else
					 throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.NotAnArray_EXC_"), new Object[] {arrayType})); //$NON-NLS-1$
	
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (RuntimeException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Push the array creation request.
	 * 
	 * @param arrayType The type of the array
	 * @param dimensionCount The number of dimensions being initialized. Zero if using an initializer.
	 * @since 1.0.0
	 */
	public final void pushArrayCreation(Class arrayType, int dimensionCount) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		if (traceOn)
			printTrace("Array Creation: "+arrayType.getName()+'['+dimensionCount+']', ignore); //$NON-NLS-1$
		
		try {
			if (ignore)
				return;
			
			try {
				if (dimensionCount == 0) {
					// The top value is the array itself, from the array initializer.
					// So we do nothing.
				} else {
					// Strip off dimensionCounts from the array type, e.g.
					// ArrayType is int[][][]
					// Dimensioncount is 2
					// Then we need to strip two componenttypes off of the array type
					// wind up with int[]
					// This is necessary because Array.new will add those dimensions back
					// on through the dimension count.
					Class componentType = arrayType;
					for(int i=0; i < dimensionCount && componentType != null; i++)
						componentType = componentType.getComponentType();
					if (componentType == null)
						throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.ArraytypeHasFewerDimensionsThanRequested_EXC_"), new Object[] {arrayType, new Integer(dimensionCount)})); //$NON-NLS-1$
					
					// We need to pull in the dimension initializers. They are stacked in reverse order.
					int[] dimInit = new int[dimensionCount];
					for(int i=dimensionCount-1; i >= 0; i--) {
						Object index = popExpression();
						Class dimType = popExpressionType(false);
						if (dimType.isPrimitive() && (dimType == Integer.TYPE || dimType == Short.TYPE || dimType == Character.TYPE || dimType == Byte.TYPE)) {
							dimInit[i] = getInt(index);
						} else
							throwClassCast(Integer.TYPE, index);
					}
					
					// Finally create the array.
					Object array = Array.newInstance(componentType, dimInit);
					pushExpressionValue(array, arrayType);
				}
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}

	/**
	 * Push the array initializer request.
	 * 
	 * @param arrayType The original type of the array to create.
	 * @param stripCount the count of how many dimensions to strip to get the type needed for this initializer.
	 * @param expressionCount
	 * @since 1.0.0
	 */
	public final void pushArrayInitializer(Class arrayType, int stripCount, int expressionCount) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		
		if (traceOn)
			printTrace("Initialize Array: "+arrayType.getName()+'{'+expressionCount+'}', ignore); //$NON-NLS-1$
		
		try {
			if (ignore)
				return;
	
			try {
				if (!arrayType.isArray()) {
					// It is not an array type.
					throw new ClassCastException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.CannotCastXToY_EXC_"), new Object[] {arrayType, "array"})); //$NON-NLS-1$ //$NON-NLS-2$
				} 
				// Strip off the number of dimensions specified.
				while(stripCount-->0) {
					arrayType = arrayType.getComponentType();
				}
				Object[] dimValues = null;
				if (expressionCount > 0) {
					// We need to pull in the initializers. They are stacked in reverse order.
					dimValues = new Object[expressionCount];
					for (int i = expressionCount - 1; i >= 0; i--) {
						Object dimValue = dimValues[i] = popExpression();
						Class dimType = popExpressionType(false);
						if (arrayType.isPrimitive()) {
							if (dimValue == null || !dimType.isPrimitive())
								throwClassCast(arrayType, dimType);
							// A little trickier. Can assign short to an int, but can't assign long to an int. Widening is permitted.
							if (arrayType != dimType) {
								int compEnum = getEnumForPrimitive(arrayType);
								int dimEnum = getEnumForPrimitive(dimType);
								if (compEnum == BOOLEAN || dimEnum == BOOLEAN)
									throwClassCast(arrayType, dimType);
								int dimValueAsInt = getInt(dimValue);
								switch (compEnum) {
									case BYTE :
										// Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
										// Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
										// however, at this point in time we no longer know this. So we will simply allow it.
										if (dimEnum > INT || dimValueAsInt > Byte.MAX_VALUE || dimValueAsInt < Byte.MIN_VALUE)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Byte((byte)dimValueAsInt);
										break;
									case SHORT :								
										// Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
										// Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
										// however, at this point in time we no longer know this. So we will simply allow it.
										if (dimEnum > INT || dimValueAsInt > Short.MAX_VALUE || dimValueAsInt < Short.MIN_VALUE)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Short((short)dimValueAsInt);
										break;
									case CHAR :
										// Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
										// Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
										// however, at this point in time we no longer know this. So we will simply allow it.
										if (dimEnum > INT || dimValueAsInt > Character.MAX_VALUE || dimValueAsInt < Character.MIN_VALUE)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Character((char)dimValueAsInt);
										break;
									case INT :
										// Can accept byte, short, char, or int. Can't accept long, double, float at all.
										if (dimEnum > INT)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Integer(dimValueAsInt);
										break;
									case LONG :
										// Can accept byte, short, char, int, or long. Can't accept double, float at all.
										if (dimEnum > LONG)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Long(getLong(dimValue));
										break;
									case FLOAT :
										// Can accept byte, short, char, int, long, or float. Can't accept double at all.
										if (dimEnum > FLOAT)
											throwClassCast(arrayType, dimType);
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Float(getFloat(dimValue));
										break;
									case DOUBLE :
										// But need to be changed to appropriate type for the array.set to work.									
										dimValues[i] = new Double(getDouble(dimValue));
										break;
	
								}
							}
							// Compatible, so ok.
						} else if (dimType != MethodHelper.NULL_TYPE && !arrayType.isAssignableFrom(dimType)) {
							// If it is NULL_TYPE, then this is a pushed null. This is always assignable to a non-primitive.
							// So we don't enter here in that case. However, a null that was returned from some expression
							// won't have a NULL_TYPE, it will instead have the expected return type. That must be used
							// in the assignment instead. That is because in java it uses the expected type to determine
							// compatibility, not the actual type.
							throwClassCast(arrayType, dimType);
						}
					}
					
				}
				
				// Now we finally create the array.
				Object array = Array.newInstance(arrayType, new int[] {expressionCount});
				for (int i = 0; i < expressionCount; i++) {
					Array.set(array, i, dimValues[i]);
				}
				
				pushExpressionValue(array, array.getClass());	// Adjust to true array type, not the incoming type (which is one dimension too small).
	
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}

	/**
	 * Push the class instance creation request.
	 * 
	 * @param type The type to create an instance of
	 * @param argumentCount The number of arguments (which are stored on the stack).	 * @throws NoExpressionValueException
	 * @since 1.0.0
	 */
	public final void pushClassInstanceCreation(Class type, int argumentCount) {
		boolean ignore = (ignoreExpression != null || errorOccurred);
		
		if (traceOn)
			printTrace("Create Class: "+type+" (", ignore); //$NON-NLS-1$ //$NON-NLS-2$
		try {
			if (ignore)
				return;
						
			try {
				// We need to pull in the arguments. They are stacked in reverse order.
				Object value = null;	// The new instance.
				if (argumentCount > 0) {
					Object[]  args = new Object[argumentCount];
					Class[] argTypes = new Class[argumentCount];
					for (int i = argumentCount - 1; i >= 0; i--) {
						args[i] = popExpression();
						argTypes[i] = popExpressionType(false);
					}
					
					// Now we need to find the appropriate constructor.
					Constructor ctor;
					ctor = MethodHelper.findCompatibleConstructor(type, argTypes);
					if (traceOn) {
						System.out.print(ctor);
						System.out.print(')');
					}
					value = ctor.newInstance(args);
				} else {
					// No args, just do default ctor.
					if (traceOn) {
						System.out.print("Default ctor)"); //$NON-NLS-1$
					}
					value = type.newInstance();
				}
				
				pushExpressionValue(value, type);
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (InstantiationException e) {
				processException(e);
			} catch (IllegalAccessException e) {
				processException(e);
			} catch (InvocationTargetException e) {
				processException(e);
			} catch (NoSuchMethodException e) {
				processException(e);
			} catch (AmbiguousMethodException e) {
				processException(e);
			} catch (LinkageError e) {
				processException(e);
			} catch (Error e) {
				if (e.getClass() == Error.class) {
					// If exactly Error.class, then process it. This is hopefully just a "unresolved compilation error".
					processException(new UnresolvedCompilationError(e));
				} else
					throw e;	// All subclasses we throw on out.
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}

	/**
	 * Push the field access expression.
	 * @param field String for fieldname, or a java.lang.reflect.Field.
	 * @param fieldIsString <code>true</code> if field is a string name, and not a java.lang.reflect.Field.
	 * @param hasReceiver
	 * 
	 * @since 1.0.0
	 */
	public final void pushFieldAccess(Object field, boolean fieldIsString, boolean hasReceiver) {
		try {
			if (ignoreExpression != null || errorOccurred) {
				if (traceOn)
					printTrace("Field Access", true); //$NON-NLS-1$
				return;
			}
		
			if (traceOn)
				printTrace("Field Access: ", false); //$NON-NLS-1$
			try {
				// Get the receiver off of the stack.
				Object receiver = null;
				Class receiverType = null;
				if (hasReceiver) {
					receiver = popExpression();
					receiverType = popExpressionType(false);
				}
				
				// Find the field.
				Field reflectField = fieldIsString ? receiverType.getField((String) field) : (Field) field;
				// Access the field.
				Object value = FieldAccessReference.createFieldAccessReference(reflectField, receiver);
				Class valueType = reflectField.getType();
				if (traceOn) {
					System.out.print("Field: "); //$NON-NLS-1$
					if (fieldIsString)
						System.out.print("(looked up) "); //$NON-NLS-1$
					System.out.print(reflectField);
					System.out.print(">"); //$NON-NLS-1$
					printObjectAndType(value, valueType);
				}
					
				pushExpressionValue(value, valueType);
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (NoSuchFieldException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}

	/**
	 * Push the method invocation expression.
	 * @param method
	 * @param methodIsString <code>true</code> if method is a string (so string name) or else it is a java.lang.reflect.Method.
	 * @param hasReceiver
	 * @param argCount
	 * @since 1.0.0
	 */
	public final void pushMethodInvocation(Object method, boolean methodIsString, boolean hasReceiver, int argCount) {
		try {
			if (ignoreExpression != null || errorOccurred) {
				if (traceOn)
					printTrace("Invoke", true); //$NON-NLS-1$
				return;
			}
			
			if (traceOn)
				printTrace("Invoke: ", false); //$NON-NLS-1$
			
			Method reflectMethod = null;
			try {
				// We need to pull in the arguments. They are stacked in reverse order.
				Object[]  args = new Object[argCount];
				Class[] argTypes = new Class[argCount];
				for (int i = argCount - 1; i >= 0; i--) {
					args[i] = popExpression();
					argTypes[i] = popExpressionType(false);
				}
				
				// Now get receiver
				Object receiver = null;
				Class receiverType = null;
				if (hasReceiver) {
					receiver = popExpression();
					receiverType = popExpressionType(false);
				}
				
				// Now we need to find the appropriate method. If it is a string then there must be a receiver, otherwise no way to know.
				if (methodIsString) {
					reflectMethod = MethodHelper.findCompatibleMethod(receiverType, (String) method, argTypes);
				} else
					reflectMethod = (Method) method;
				
				if (traceOn && reflectMethod != null) {
					System.out.print("Method: "); //$NON-NLS-1$
					if (methodIsString)
						System.out.print("(looked up) "); //$NON-NLS-1$
					System.out.print(reflectMethod);					
				}
				
				if (!Modifier.isStatic(reflectMethod.getModifiers()) && receiver == null)
					throw new NullPointerException("No receiver for non-static method: "+reflectMethod.toString()); //$NON-NLS-1$
					
				Object value = reflectMethod.invoke(receiver, args);
				
				if (traceOn) {
					System.out.print(" returns: "); //$NON-NLS-1$
					printObjectAndType(value, reflectMethod.getReturnType());
				}
				pushExpressionValue(value, reflectMethod.getReturnType());
			} catch (RuntimeException e) {
				processException(fixUpMethodException(e, reflectMethod));
			} catch (NoExpressionValueException e) {
				processException(fixUpMethodException(e, reflectMethod));
			} catch (IllegalAccessException e) {
				processException(fixUpMethodException(e, reflectMethod));
			} catch (InvocationTargetException e) {
				processException(fixUpMethodException(e.getCause(), reflectMethod));
			} catch (NoSuchMethodException e) {
				processException(e);
			} catch (AmbiguousMethodException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
			
	}
	
	/*
	 * Many of the exceptions don't add in what method had the error, so we
	 * will do that here.
	 */
	private Throwable fixUpMethodException(Throwable e, Method method) {
		if (method == null)
			return e;
		try {
			String msg = e.getMessage();
			Constructor eWithStringCtor = e.getClass().getConstructor(new Class[] {String.class});
			String newMsg;
			if (msg == null) {
				newMsg = method.toString();
			} else {
				newMsg = method.toString()+": \""+msg+'\"'; //$NON-NLS-1$
			}
			Exception fixedupE = (Exception) eWithStringCtor.newInstance(new Object[] {newMsg});
			fixedupE.setStackTrace(e.getStackTrace());
			return fixedupE;
		} catch (Exception e1) {
			return e;
		}
  
	}

	private static final Object CONDITIONAL_IGNORE = "CONDITIONAL IGNORE";	// Flag for conditional in ingore //$NON-NLS-1$
	private int conditionalNesting = 0;	// Nesting of conditional expressions.
	private int conditionalIgnoreNestCount = 0;	// When ignoring conditional expressions, ignore until this nest count.
	private boolean skipTruePart;

	/**
	 * Push a conditional expression. It can be any clause of the conditional (test, true, or false clause).
	 * @param expressionType
	 * 
	 * @since 1.0.0
	 */
	public final void pushConditional(InternalConditionalOperandType expressionType) {
		try {
			boolean ignore = true;
			try {
				if (errorOccurred)
					return;
				// Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
				// we can get the expression grouping correct.
				switch (expressionType.getValue()) {
					case InternalConditionalOperandType.CONDITIONAL_TEST_VALUE:
						conditionalNesting++;
						break;
					case InternalConditionalOperandType.CONDITIONAL_TRUE_VALUE:
						if (skipTruePart && ignoreExpression == CONDITIONAL_IGNORE && conditionalIgnoreNestCount == conditionalNesting) {
							// stop ignoring, we've ignored the true condition of interest.
							ignoreExpression = null;
							return; // However, leave because since this condition was ignored.
						}
						break;
					case InternalConditionalOperandType.CONDITIONAL_FALSE_VALUE:
						int currentNesting = conditionalNesting--;
						if (ignoreExpression == CONDITIONAL_IGNORE && conditionalIgnoreNestCount == currentNesting) {
							// stop ignoring, we've ignored the false condition of interest.
							ignoreExpression = null;
							return; // However, leave because since this condition was ignored.
						}
				}
	
				if (ignoreExpression != null)
					return;
				ignore = false;
			} finally {
				if (traceOn)
					printTrace("Conditional "+expressionType, ignore); //$NON-NLS-1$
			}
					
			try {
				switch (expressionType.getValue()) {
					case InternalConditionalOperandType.CONDITIONAL_TEST_VALUE:
						Object condition = popExpression();
						Class type = popExpressionType(false);
						if (type != Boolean.TYPE)
							throwClassCast(Boolean.TYPE, condition);
						if (((Boolean) condition).booleanValue()) {
							// Condition was true.
							// Do nothing. Let true condition be processed.
						} else {
							// Condition was false.
							skipTruePart = true;	// Tell the true condition should be ignored.
							ignoreExpression = CONDITIONAL_IGNORE;
							conditionalIgnoreNestCount = conditionalNesting;
						}
						// We don't put anything back on the stack because the condition test is not ever returned.
						// The appropriate true or false condition evaluation will be left on the stack.
						break;
					case InternalConditionalOperandType.CONDITIONAL_TRUE_VALUE:
						skipTruePart = false;	// Tell the false condition should be ignored.
						ignoreExpression = CONDITIONAL_IGNORE;
						conditionalIgnoreNestCount = conditionalNesting;
						break;
					case InternalConditionalOperandType.CONDITIONAL_FALSE_VALUE:
						// There's nothing to do, if it was ignored due to true, we wouldn't of gotton here.
						// If it wasn't ignored, then the result of the false expression is on the stack, which is what it should be.
						break;
				}
			} catch (RuntimeException e) {
				processException(e);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	private static final Object BLOCK_IGNORE = "BLOCK IGNORE"; //$NON-NLS-1$
	private int[] blocks;	// Stack of block numbers currently evaluating.
	private int topBlock = -1;	// Top block index.
	private int breakBlock = -1;	// Block number we are breaking to.
	
	/**
	 * Push a begin block.
	 * @param blockNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushBlockBegin(int blockNumber) {
		if (traceOn) {
			printTrace("Begin Block #"+blockNumber, errorOccurred); //$NON-NLS-1$
			indent(true);
		}
		try {
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (blocks == null)
				blocks = new int[10];
			if (++topBlock >= blocks.length) {
				int[] newList = new int[blocks.length*2];
				System.arraycopy(blocks, 0, newList, 0, blocks.length);
				blocks = newList;
			}
			blocks[topBlock] = blockNumber;
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Push a block end. The current block must be the given number, or it is an error.
	 * 
	 * @param blockNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushBlockEnd(int blockNumber) {
		try {
			if (traceOn) {
				indent(false);
				printTrace("End Block #"+blockNumber, errorOccurred); //$NON-NLS-1$
			}
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (blocks == null || topBlock < 0 || blocks[topBlock] != blockNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushBlockEnd.ReceivedEndBlocksOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else {
				topBlock--;
				if (ignoreExpression == BLOCK_IGNORE && blockNumber == breakBlock) {
					ignoreExpression = null;
				}
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}
	
	/**
	 * Skip all following until we hit the requested block number.
	 * @param blockNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushBlockBreak(int blockNumber) {
		try {
			if (traceOn)
				printTrace("Break Block #"+blockNumber, errorOccurred); //$NON-NLS-1$
			if (errorOccurred)
				return;
			if (ignoreExpression == null) {
				ignoreExpression = BLOCK_IGNORE;	// Start ignoring expressions until we hit the block number end block.
				breakBlock = blockNumber;
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	private static final Object TRY_THROW_IGNORE = "TRY THROW IGNORE"; //$NON-NLS-1$
	private static final Object TRY_FINAL_IGNORE = "TRY FINAL IGNORE"; //$NON-NLS-1$
	private int[] trys;	// Stack of try numbers currently evaluating.
	// Stack of trys in catch clause (i.e. starting executing a catch/final clause for the try). Corresponds with try from same index in trys. Contains the throwable for the catch.
	// This is used to know we are executing a catch (entry not null) and for the rethrow short-hand to rethrow the same exception within the catch.
	private Throwable[] trysInCatch;	
	private int topTry = -1;	// Top try index.
	private int breakTry = -1;	// Try number we are breaking to.
	private Throwable catchThrowable;	// The throwable to check catches against.
	
	/**
	 * Push a try statement.
	 * @param tryNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushTryBegin(int tryNumber) {
		try {
			if (traceOn) {
				printTrace("Begin Try #"+tryNumber, errorOccurred); //$NON-NLS-1$
				indent(true);
			}
	
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (trys == null) {
				trys = new int[10];
				trysInCatch = new Throwable[10];
			}
			if (++topTry >= trys.length) {
				int[] newList = new int[trys.length*2];
				System.arraycopy(trys, 0, newList, 0, trys.length);
				trys = newList;
				Throwable[] newCatches = new Throwable[trys.length];
				System.arraycopy(trysInCatch, 0, newCatches, 0, trysInCatch.length);
				trysInCatch = newCatches;
			}
			trys[topTry] = tryNumber;
			trysInCatch[topTry] = null;
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}

	/**
	 * Throw the top stack entry. It must be an exception.
	 * 
	 * 
	 * @since 1.1.0
	 */
	public final void pushThrowException() {
		try {
			boolean ignore = (ignoreExpression != null || errorOccurred);
			if (traceOn)
				printTrace("Throw exception: ", ignore); //$NON-NLS-1$
			
			if (ignore)
				return;
	
			try {
				Object t = popExpression();
				popExpressionType(false);
				if (traceOn) {
					System.out.print(t);
				}
				throwException((Throwable) t);
			} catch (NoExpressionValueException e) {
				processSyntaxException(e);
			} catch (ClassCastException e) {
				processException(e);
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}
	
	/**
	 * Throw this exception (means throw through the expression being processed, not throw for this thread).
	 * @param exception
	 * 
	 * @since 1.1.0
	 */
	protected final void throwException(Throwable exception) {
		if (topTry == -1) {
			// There are no tries, so treat this as a syntax error.
			processSyntaxException(exception);
		} else if (trysInCatch[topTry] == null) {
			// We are not in a catch clause of the top try. So do a throw ignore for toptry.
			ignoreExpression = TRY_THROW_IGNORE;
			breakTry = trys[topTry];
			catchThrowable = exception;
		} else {
			// We are in a catch of the top try. So do a throw to finally instead.
			ignoreExpression = TRY_FINAL_IGNORE;
			trysInCatch[topTry] = FINAL_CATCH;
			breakTry = trys[topTry];
			catchThrowable = exception;
		}
	}
	
	/**
	 * Push a catch clause
	 * @param tryNumber
	 * @param exceptionType
	 * @param expressionProxy
	 * 
	 * @since 1.1.0
	 */
	public final void pushTryCatchClause(int tryNumber, Class exceptionType, InternalExpressionProxy expressionProxy) {
		try {
			if (traceOn) {
				indent(false);
				if (expressionProxy == null)
					printTrace("Catch Try #"+tryNumber+" ("+exceptionType+')', errorOccurred); //$NON-NLS-1$ //$NON-NLS-2$
				else
					printTrace("Catch Try #"+tryNumber+" ("+exceptionType+") Return exception in proxy #"+expressionProxy.getProxyID(), errorOccurred); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				indent(true);
			}
			
			if (errorOccurred)
				return;
			
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushTryCatchClause.CatchReceivedOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else {
				if (ignoreExpression == null) {
					// Normal flow, no throw in progress, so just ignore now until the finally or end try reached.
					ignoreExpression = TRY_FINAL_IGNORE;
					breakTry = tryNumber;
				} else if (ignoreExpression == TRY_THROW_IGNORE && tryNumber == breakTry) {
					// We are here due to a throw occuring in this try block, see if for us, and if it is, stop ignoring.
					// Else just continue ignoring.
					if (exceptionType.isInstance(catchThrowable)) {
						// For us, so just turn everything back on, except mark that we are in the catch phase.
						ignoreExpression = null;
						trysInCatch[topTry] = catchThrowable; // This is so that we know if we throw again that we should not catch anything.
						breakTry = -1;
						if (expressionProxy != null) {
							expressionProxy.setProxy(catchThrowable, catchThrowable.getClass());
							allocateExpressionProxy(expressionProxy);
						}
						if (traceOn) {
							System.out.print(" Caught: "); //$NON-NLS-1$
							System.out.print(catchThrowable);
						}
						catchThrowable = null;
					}
				}
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}
	
	// This is used only so that finally clause can indicate it was executing so that end expression knows this.
	private static final Throwable FINAL_CATCH = new RuntimeException();

	/**
	 * Push the try finally clause.
	 * @param tryNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushTryFinallyClause(int tryNumber) {
		try {
			if (traceOn) {
				indent(false);
				printTrace("Finally Try #"+tryNumber, errorOccurred); //$NON-NLS-1$
				indent(true);
			}
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushTryFinallyClause.FinallyReceivedOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else {
				if (tryNumber == breakTry && (ignoreExpression == TRY_THROW_IGNORE || ignoreExpression == TRY_FINAL_IGNORE)) {
					// We are here due to a throw occuring in this try block or a catch was reached (in which case all intervening catch's were ignored).
					// Now do a normal execution. If we are here due to a throw that wasn't cleared (either no catch or another throw occured within the catch)
					// then we leave it uncleared so that try/end may rethrow it.
					ignoreExpression = null;
					trysInCatch[topTry] = FINAL_CATCH; // We are in the finally clause of a exception being thrown within this try.
					breakTry = -1;
					if (traceOn)
						System.out.print(" Executing finally."); //$NON-NLS-1$
				}
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}
	
	/**
	 * Rethrow the caught exception. This is a shortcut for:
	 * } catch (Exception e) {
	 *   ... do stuff ...
	 *   throw e;
	 * }
	 * @param tryNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushTryRethrow(int tryNumber) {
		if (traceOn)
			printTrace("Rethrow Try #"+tryNumber, errorOccurred  || ignoreExpression != null); //$NON-NLS-1$
		
		try {
			if (errorOccurred)
				return;
			// We are not checking ignore because we need to make sure this is not called out of order.
			if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushTryRethrow.RethrowReceivedOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else if (ignoreExpression == null) {
				if (trysInCatch[topTry] == null || trysInCatch[topTry] == FINAL_CATCH)
					processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushTryRethrow.RetryReceivedOutOfExecutingCatchClause_EXC_"))); //$NON-NLS-1$
				else {
					throwException(trysInCatch[topTry]);
				}
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}		
	}
	
	public final void pushTryEnd(int tryNumber) {
		if (traceOn) {
			indent(false);
			printTrace("End Try #"+tryNumber, errorOccurred); //$NON-NLS-1$
		}
		try {
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushTryEnd.TryEndReceivedOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else {
				boolean inCatch = trysInCatch[topTry] != null;
				trysInCatch[topTry] = null;
				topTry--;
				if (inCatch || (tryNumber == breakTry && (ignoreExpression == TRY_THROW_IGNORE || ignoreExpression == TRY_FINAL_IGNORE))) {
					// We are here due to a throw or normal flow through a catch. Either way if there is a throwable still pending, we rethrow.
					ignoreExpression = null;
					breakTry = -1;
					if (catchThrowable != null)
						throwException(catchThrowable);
				} 
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}
	
	/**
	 * Class used to save the state at time of mark. It will
	 * be used to restore state if error.
	 * 
	 * @since 1.1.0
	 */
	protected class SaveState {
		public int markID;
		
		// Block state
		public int topBlock;
		public int breakBlock;

		// Subexpression state
		public int topSubexpression;

		// Try state
		public int topTry;
		public int breakTry;
		public Throwable catchThrowable;
		
		// Error state
		public boolean errorOccurred;
		public boolean novalueException;
		public Throwable exception;
		public Object ignoreExpression;
		
		// Expression stack state
		public int expressionStackPos;
		
		// If/else state
		public int ifElseNesting;
		public int ifElseIgnoreNestCount;
		public boolean ifElseSkipTruePart;
		
		// Other
		public int indent;
		public int expressionProxyPos;
		
		/**
		 * Construct and save the state.
		 * 
		 * @param markNumber
		 * 
		 * @since 1.1.0
		 */
		public SaveState(int markID) {
			this.markID = markID;
			
			ExpressionProcesser ep = ExpressionProcesser.this;
			this.topBlock = ep.topBlock;
			this.breakBlock = ep.breakBlock;
			
			this.topSubexpression = ep.topSubexpression;
			
			this.topTry = ep.topTry;
			this.breakTry = ep.breakTry;
			this.catchThrowable = ep.catchThrowable;
			
			this.errorOccurred = ep.errorOccurred;
			this.novalueException = ep.novalueException;
			this.exception = ep.exception;
			this.ignoreExpression = ep.ignoreExpression;
			
			this.expressionStackPos = expressionStack.size()-1;
			
			this.ifElseNesting = ep.ifElseNesting;
			this.ifElseIgnoreNestCount = ep.ifElseIgnoreNestCount;
			this.ifElseSkipTruePart = ep.ifElseSkipTruePart;
			
			this.indent = ep.indent;
			this.expressionProxyPos = expressionProxies != null ? expressionProxies.size()-1 : -1;
		}
		
		/**
		 * Restore the state.
		 * 
		 * 
		 * @since 1.1.0
		 */
		public void restoreState() {
			ExpressionProcesser ep = ExpressionProcesser.this;
			ep.topBlock = this.topBlock;
			ep.breakBlock = this.breakBlock;

			ep.topSubexpression = this.topSubexpression;
			
			ep.topTry = this.topTry;
			ep.breakTry = this.breakTry;
			ep.catchThrowable = this.catchThrowable;
			if (trysInCatch != null) {
				for (int i = topTry + 1; i < ep.trysInCatch.length; i++) {
					ep.trysInCatch[i] = null;
				}
			}

			ep.errorOccurred = this.errorOccurred;
			ep.novalueException = ep.novalueException;
			ep.exception = this.exception;
			ep.ignoreExpression = this.ignoreExpression;
			
			// Pop stack down to saved state.
			for (int i = expressionStack.size()-1; i > this.expressionStackPos; i--) {
				expressionStack.remove(i);
				expressionTypeStack.remove(i);
			}
			
			ep.ifElseNesting = this.ifElseNesting;
			ep.ifElseIgnoreNestCount = this.ifElseIgnoreNestCount;
			ep.ifElseSkipTruePart = this.ifElseSkipTruePart;
			
			ep.indent = this.indent;
			
			if (expressionProxies != null) {
				for (int i = expressionProxies.size() - 1; i > this.expressionProxyPos; i--) {
					expressionProxies.remove(i);
				}
			}
			
			// These settings can't cross mark boundaries, so reset them to not set. This is in case we were in this state somewhere
			// in the mark when the restore occurred.
			ep.conditionalIgnoreNestCount = 0;
			ep.conditionalNesting = 0;
			ep.skipTruePart = false;
			
			ep.infixIgnoreNestCount = 0;
			ep.infixNesting = 0;
		}
	}
	
	/**
	 * Create the save state with the given id.
	 * @param markID
	 * @return
	 * 
	 * @since 1.1.0
	 */
	protected SaveState createSaveState(int markID) {
		return new SaveState(markID);
	}
	
	/**
	 * Push the start of a mark.
	 * @param markNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushMark(int markNumber) {
		if (traceOn)
			printTrace("Mark#"+markNumber, false); //$NON-NLS-1$
		
		if (saveStates == null)
			saveStates = new ArrayList();
		saveStates.add(createSaveState(markNumber));
		
		if (traceOn)
			printTraceEnd();
	}
	
	/**
	 * Push the end mark. If there is no error, it will simply
	 * remove it and all save states in the map after it. If there
	 * is an error it will do this plus it will restore the state.
	 * <p>
	 * It is assumed that the calls are coming in correct order from
	 * the server so we won't check validity.
	 * 
	 * @param markID
	 * @param restore
	 * 
	 * @since 1.1.0
	 */
	public final void pushEndmark(int markID, boolean restore) {
		if (traceOn)
			printTrace("End Mark#"+markID+" Restored="+restore, false); //$NON-NLS-1$ //$NON-NLS-2$
		
		try {
			if (saveStates != null) {
				// Start from the end (since that is where it most likely will be) and start
				// search, removing the end one until we reach the markID.
				for (int i = saveStates.size() - 1; i >= 0; i--) {
					SaveState state = (SaveState) saveStates.remove(i);
					if (state.markID == markID) {
						// We found it.
						if (restore)
							state.restoreState();
						return;
					}
				}
				// But to be safe, if we got here, this is bad. We tried restore a mark we didn't have.
				processSyntaxException(new IllegalStateException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.PushEndmark.EndMarkOnNonExistingID_EXC_"), new Object[]{new Integer(markID)}))); //$NON-NLS-1$
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	private int[] subexpressions;	// Stack of subexpression numbers currently evaluating.
	private int[] subexpressionStackPos;	// Stack of the expression stack positions (next entry index) for currently evaluating expressions. The evaluation stack cannot be popped beyond the current top. And at end it will be cleaned up to the position.
	private int topSubexpression = -1;	// Top subexpression index.

	
	/**
	 * Push a begin subexpression.
	 * @param subexpressionNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushSubexpressionBegin(int subexpressionNumber) {
		if (traceOn) {
			printTrace("Begin Subexpression #"+subexpressionNumber, errorOccurred); //$NON-NLS-1$
			indent(true);
		}
		try {
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (subexpressions == null) {
				subexpressions = new int[10];
				subexpressionStackPos = new int[10];
			}
			if (++topSubexpression >= subexpressions.length) {
				int[] newList = new int[subexpressions.length*2];
				System.arraycopy(subexpressions, 0, newList, 0, subexpressions.length);
				subexpressions = newList;
				newList = new int[subexpressionStackPos.length*2];
				System.arraycopy(subexpressionStackPos, 0, newList, 0, subexpressionStackPos.length);
				subexpressionStackPos = newList;				
			}
			subexpressions[topSubexpression] = subexpressionNumber;
			subexpressionStackPos[topSubexpression] = expressionStack.size();
		} finally {
			if (traceOn)
				printTraceEnd();
		}
	}
	
	/**
	 * Push a subexpression end. The current subexpression must be the given number, or it is an error.
	 * 
	 * @param subexpressionNumber
	 * 
	 * @since 1.1.0
	 */
	public final void pushSubexpressionEnd(int subexpressionNumber) {
		try {
			if (traceOn) {
				indent(false);
				printTrace("End Subexpression #"+subexpressionNumber, errorOccurred); //$NON-NLS-1$
			}
			if (errorOccurred)
				return;
			// We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
			if (subexpressions == null || topSubexpression < 0 || subexpressions[topSubexpression] != subexpressionNumber) {
				processSyntaxException(new IllegalStateException(InitparserTreeMessages.getString("ExpressionProcesser.PushSubexpressionEnd.ReceivedEndSubexpressionsOutOfOrder_EXC_"))); //$NON-NLS-1$
			} else {
				try {
					popExpressions(expressionStack.size()-subexpressionStackPos[topSubexpression]);
					topSubexpression--;
				} catch (NoExpressionValueException e) {
					processSyntaxException(e);
				}
			}
		} finally {
			if (traceOn)
				printTraceEnd();
		}			
	}


}
