public Token nextToken() throws ArithmeticTokenizationException {
    if (!hasNext()) throw new NoSuchElementException("Next element does not exist");

    char c = mExpression.charAt(mCurrentIndex);
    Token<?> token;
    if (isDigit(c)) {
      token = readNumber();
    } else if (isLetter(c)) {
      token = readVariable();
    } else if (OperatorToken.isOperator(c)) {
      mCurrentIndex++;
      token = new OperatorToken(c);
    } else if (ParenthesisToken.isParenthesis(c)) {
      mCurrentIndex++;
      token = new ParenthesisToken(c);
      mParenthesesCount += (token.getValue() == ParenthesisType.OPEN ? 1 : -1);
      assertThat(mParenthesesCount >= 0, "Unbalanced parenthesis", "#!UNBLN", mCurrentIndex);
    } else {
      throw new ArithmeticTokenizationException("Unrecognized character: " + c, "#!INVLD", mCurrentIndex);
    }
    assertThat(token.isValidAfter(mLastToken), "Malformed expression", "#!INVLD", mCurrentIndex);
    mLastToken = token;

    skipWhitespace();
    if (!hasNext()) {
      assertThat(mParenthesesCount == 0, "Unbalanced parenthesis", "#!UNBLN", mCurrentIndex);
    }
    return token;
  }