/** Compiles UnaryExpression */
  @Override
  public void visit(UnaryExpression expression) {
    if (expression == null) {
      throw new ArgumentException(EXPRESSION + E_IS_NULL);
    }

    expression.getExpression().accept(this);

    switch (expression.getType()) {
      case NOT:
        result.setResult(new Not(result.getResult()));
        break;

      case NEGATE:
        result.setResult(new Negate(result.getResult()));
        break;
    }
  }
  @Override
  public void visit(AssignmentExpression assignment) {
    if (assignment == null) {
      throw new ArgumentException(ASSIGNMENT + E_IS_NULL);
    }
    /** processes the left hand expression and saves the value to result */
    assignment.getLeft().accept(this);
    LogicalExpression left = result.getResult();
    // LHS must always be a variable.
    if (!(left instanceof Variable)) {
      throw new ArgumentException(E_ASSIGNMENT_LHS_NOT_VARIABLE);
    }
    assignment.setLeft(left);

    /** processes the right hand expression and saves the value to result */
    assignment.getRight().accept(this);
    assignment.setRight(result.getResult());

    /** No magic here, just set the original instance */
    result.setResult(assignment);
  }
 private LogicalExpression evaluate(LogicalExpression expression) {
   expression.accept(this);
   return result.getResult();
 }
  /** Compiles BinaryExpressions */
  @Override
  public void visit(BinaryExpression expression) {
    if (expression == null) {
      throw new ArgumentException(EXPRESSION + E_IS_NULL);
    }
    /** processes the left hand expression and saves the value to result */
    expression.getLeft().accept(this);
    LogicalExpression left = result.getResult();

    /** processes the right hand expression and saves the value to result */
    expression.getRight().accept(this);
    LogicalExpression right = result.getResult();

    switch (expression.getType()) {
      case AND:
        result.setResult(new And(left, right));
        break;

      case OR:
        result.setResult(new Or(left, right));
        break;

      case DIV:
        result.setResult(new Divide(left, right));
        break;

      case EQ:
        result.setResult(new Equal(left, right));
        break;

      case GT:
        result.setResult(new Greater(left, right));
        break;

      case GTE:
        result.setResult(new GreaterEqual(left, right));
        break;

      case LT:
        result.setResult(new Lesser(left, right));
        break;

      case LTE:
        result.setResult(new LesserEqual(left, right));
        break;

      case MINUS:
        result.setResult(new Minus(left, right));
        break;

      case MOD:
        result.setResult(new Modulo(left, right));
        break;

      case NE:
        result.setResult(new NotEqual(left, right));
        break;

      case PLUS:
        result.setResult(new Plus(left, right));
        break;

      case MULT:
        result.setResult(new Multiply(left, right));
        break;

      case POW:
        result.setResult(new Power(left, right));
        break;
    }
  }