private Double processExpression(ArithmeticExpressionTokenizer tokenizer) throws ArithmeticParseException {
    Deque<OperandToken> operandStack = new LinkedList<>();
    Deque<OperatorToken> operatorStack = new LinkedList<>();
    while (tokenizer.hasNext()) {
      Token<?> token = tokenizer.nextToken();
      if (token instanceof OperandToken) {
        operandStack.offerLast((OperandToken) token);
      } else if (token instanceof OperatorToken) {
        processOperatorToken((OperatorToken) token, operandStack, operatorStack);
      } else if (token instanceof ParenthesisToken) {
        ParenthesisType type = ((ParenthesisToken) token).getValue();
        if (type == ParenthesisType.OPEN) {
          Double parenthesisValue = processExpression(tokenizer);
          operandStack.offerLast(new LiteralToken(parenthesisValue));
        } else if (type == ParenthesisType.CLOSE) {
          break;
        }
      } else {
        throw new IllegalStateException("Unrecognized token class");
      }
    }
    while (!operatorStack.isEmpty()) {
      executeStackedOperation(operandStack, operatorStack);
    }
    return pollLastOperandDoubleValue(operandStack);
  }