import java.util.Stack;

public class Client {
	
	private SymbolTable table;
	
	public Client() {
		table = new SymbolTable();
	}
	
	public boolean isOperator(String symbol) {
		return (symbol.equals("+") || symbol.equals("-") || symbol.equals("*") || symbol.equals("/") || symbol.equals("="));
	}
	
	public boolean isConstant(String symbol) {
		return Character.isDigit(symbol.charAt(0));
	}
	
	public int parseExpression(String exp) {
		System.out.println("Input Expression: " + exp);
		Stack<Expression> expressionStack = new Stack<Expression>();
		Stack<String> opStack = new Stack<String>();
		String[] tokens = exp.split(" ");
		Expression terminalExp;
		for (int i = 0; i < tokens.length; i++) {
			String token = tokens[i];
			if (!isOperator(token)) {
				terminalExp = buildLeafExpression(token);
				expressionStack.push(terminalExp);
				System.out.println("terminal expression pushed to stack: " + terminalExp.toString());
				if (!opStack.isEmpty()) {
					Expression rhs = expressionStack.pop();
					Expression lhs = expressionStack.pop();
					Expression compositeExp = new CompositeExpression(lhs, rhs, opStack.pop().charAt(0), table);
					expressionStack.push(compositeExp);
					System.out.println("composite expression pushed to stack: " + compositeExp.toString());
				}
			} else { // is operator
				char op = (char) token.charAt(0);
				opStack.push(Character.toString(op));
			}
		}
		int result = expressionStack.pop().interpret();
		return result;
	}
		
	public Expression buildLeafExpression(String exp) {
		Expression e;
		if (isConstant(exp)) {
			e = new IntegerExpression(exp);
		} else {
			e = new VariableExpression(exp, table);
		}
		return e;
	}
		
	public static void main(String[] args) {
		Client c = new Client();
		System.out.println("result: " + c.parseExpression("x = 4") + "\n");
		System.out.println("result: " + c.parseExpression("y = 7") + "\n");
		System.out.println("result: " + c.parseExpression("x * y * 10 / 2 - 1") + "\n"); 
		System.out.println("result: " + c.parseExpression("n = 2 * y") + "\n");
		System.out.println("result: " + c.parseExpression("n") + "\n"); // operator precedence not implemented...
	}
}
