private IExpressionNode booleanExpression() throws ParserException {
    IExpressionNode expr = expression();
    String comparator = lookahead.sequence;
    nextToken();
    IExpressionNode expr2 = expression();

    try {
      if (comparator.equals(LT))
        return new BooleanExpressionNode(expr.getValue() < expr2.getValue());
      if (comparator.equals(GT))
        return new BooleanExpressionNode(expr.getValue() > expr2.getValue());
      if (comparator.equals(LTEQ))
        return new BooleanExpressionNode(expr.getValue() <= expr2.getValue());
      if (comparator.equals(GTEQ))
        return new BooleanExpressionNode(expr.getValue() >= expr2.getValue());
      if (comparator.equals(NTEQ))
        return new BooleanExpressionNode(expr.getValue() != expr2.getValue());
    } catch (EvaluationException ex) {
      throw new ParserException(
          "EvaluationException caught when calculating boolean expression"
              + ": "
              + expr.toString()
              + comparator
              + expr2.toString());
    }
    throw new ParserException("No Comparator found, instead found: " + comparator);
  }
  private IExpressionNode argument() throws ParserException {
    if (lookahead.token == Token.FUNCTION) {
      // argument -> FUNCTION argument
      int function = FunctionExpressionNode.stringToFunction(lookahead.sequence);
      nextToken();
      IExpressionNode expr = argument();
      return new FunctionExpressionNode(function, expr);
    } else if (lookahead.token == Token.PRINT) {
      // argumement -> PRINT expression
      nextToken();
      IExpressionNode expr = expression();

      try {
        System.out.println(expr.getValue());
      } catch (EvaluationException ex) {
        Logger.getLogger(LOGGER_NAME)
            .severe("EvaulationException thrown while printing the value of: " + expr.toString());
      }

      return expr;
    } else if (lookahead.token == Token.LPAREN) {
      // argument -> LPAREN sum RPAREN
      nextToken();
      IExpressionNode expr = expression();

      if (lookahead.token != Token.RPAREN)
        throw new ParserException(String.format(ERR_RPAREN, lookahead.sequence));

      nextToken();
      return expr;
    }

    // argument -> value
    return value();
  }
  private IExpressionNode assignmentOp(IExpressionNode variable) throws ParserException {
    if (lookahead.token == Token.EQUALS) {
      nextToken();
      IExpressionNode newVariable = expression();
      if (!(variable.getType() == IExpressionNode.VARIABLE_NODE))
        throw new ParserException(String.format(ERR_VARIABLE, variable.toString()));

      try {
        variable.accept(
            new SetVariable(((VariableExpressionNode) variable).getName(), newVariable.getValue()));
      } catch (EvaluationException ex) {
        throw new ParserException(
            String.format("The variable [%s] did not return a valid value", newVariable));
      }
    }

    return variable;
  }