import java.util.ArrayList;

/**
 * Derived class that represents an expression in the SILLY language.
 * 
 * @author Dave Reed
 * @version 2/9/07
 */
public class Expression
{
    private ArrayList<Token> expr;
    
    /**
     * Reads in an expression from the specified program
     *   @param program the source code of the program to be read from
     */
    public void read(SourceCode program) {
        expr = new ArrayList<Token>();
        
        expr.add(program.next());
        while (program.hasNext() && program.peek().getType() == Token.Type.OPERATOR) {
            expr.add(program.next());
            expr.add(program.next());
        }
        
        if (expr.size() % 2 == 0) {
            System.out.println("SYNTAX ERROR: Malformed expression");
            System.exit(0);
        }
        for (int i = 0; i < expr.size(); i++) {
            if ((i % 2 == 0 && !(expr.get(i).getType() == Token.Type.INTEGER || 
                                expr.get(i).getType() == Token.Type.IDENTIFIER)) ||
                (i % 2 == 1 && expr.get(i).getType() != Token.Type.OPERATOR)) {
                    System.out.println("SYNTAX ERROR: Malformed expression");
                    System.exit(0);
            }
        }
    }
    
    /**
     * Private helper method, called by evaluate.
     */
    private int getValue(Token t, VariableTable variables) {
        if (t.getType() == Token.Type.IDENTIFIER) {
            return variables.lookup(t.toString());
        }
        return Integer.parseInt(t.toString());
    }
    
    /**
     * Evaluates the current expression involving integers and/or variables.
     *   @param variables the table representing the current bindings for all variables
     *   @return the value represented by the expression
     */
    public int evaluate(VariableTable variables) {
        int value = this.getValue(expr.get(0), variables);
    
        for (int i = 1; i < expr.size(); i+=2) {
            if (expr.get(i).toString().equals("+")) {
                value += this.getValue(expr.get(i+1), variables);
            }
        }
        return value;
    }
      
	/**
	 * Converts the current expression into a String.
	 *   @return the String representation of this expression
	 */
	public String toString() {
        if (expr.size() == 0) {
            return "";
        }
        
        String str = expr.get(0).toString();
        for (int i = 1; i < expr.size(); i++) {
            str += " " + expr.get(i);
        }
        return str;
    }
}
