docs: private Token advanceToken() throws JsonParserException {
      int c = advanceChar();
      while (isWhitespace(c))
        c = advanceChar();
  
      tokenLinePos = linePos;
      tokenCharPos = index - rowPos - utf8adjust;
      tokenCharOffset = charOffset + index;
  
      switch (c) {
      case -1:
        return token = Token.EOF;
      case '[': // Inlined function to avoid additional stack
        JsonArray list = new JsonArray();
        if (advanceToken() != Token.ARRAY_END)
          while (true) {
            list.add(currentValue());
            if (advanceToken() == Token.ARRAY_END)
              break;
            if (token != Token.COMMA)
              throw createParseException(null, "Expected a comma or end of the array instead of " + token,
                  true);
            if (advanceToken() == Token.ARRAY_END)
              throw createParseException(null, "Trailing comma found in array", true);
          }
        value = list;
        return token = Token.ARRAY_START;
      case ']':
        return token = Token.ARRAY_END;
      case ',':
        return token = Token.COMMA;
      case ':':
        return token = Token.COLON;
      case '{': // Inlined function to avoid additional stack
        JsonObject map = new JsonObject();
        if (advanceToken() != Token.OBJECT_END)
          while (true) {
            if (token != Token.STRING)
              throw createParseException(null, "Expected STRING, got " + token, true);
            String key = (String)value;
            if (advanceToken() != Token.COLON)
              throw createParseException(null, "Expected COLON, got " + token, true);
            advanceToken();
            map.put(key, currentValue());
            if (advanceToken() == Token.OBJECT_END)
              break;
            if (token != Token.COMMA)
              throw createParseException(null, "Expected a comma or end of the object instead of " + token,
                  true);
            if (advanceToken() == Token.OBJECT_END)
              throw createParseException(null, "Trailing object found in array", true);
          }
        value = map;
        return token = Token.OBJECT_START;
      case '}':
        return token = Token.OBJECT_END;
      case 't':
        consumeKeyword((char)c, TRUE);
        value = Boolean.TRUE;
        return token = Token.TRUE;
      case 'f':
        consumeKeyword((char)c, FALSE);
        value = Boolean.FALSE;
        return token = Token.FALSE;
      case 'n':
        consumeKeyword((char)c, NULL);
        value = null;
        return token = Token.NULL;
      case '\"':
        value = consumeTokenString();
        return token = Token.STRING;
      case '-':
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        value = consumeTokenNumber((char)c);
        return token = Token.NUMBER;
      case '+':
      case '.':
        throw createParseException(null, "Numbers may not start with '" + (char)c + "'", true);
      default:
      }
  
      if (isAsciiLetter(c))
        throw createHelpfulException((char)c, null, 0);
  
      throw createParseException(null, "Unexpected character: " + (char)c, true);
    }