private void parseListResponse(ImapResponse response) throws IOException {
   expect(' ');
   parseList(response, '(', ')');
   expect(' ');
   // TODO: Add support for NIL
   String delimiter = parseQuoted();
   response.add(delimiter);
   expect(' ');
   String name = parseString();
   response.add(name);
   expect('\r');
   expect('\n');
 }
  private void readContinuationRequest(ImapResponseCallback callback) throws IOException {
    parseCommandContinuationRequest();
    response = ImapResponse.newContinuationRequest(callback);

    skipIfSpace();
    String rest = readStringUntilEndOfLine();
    response.add(rest);
  }
  private void readTokens(ImapResponse response) throws IOException {
    response.clear();

    Object firstToken = readToken(response);

    checkTokenIsString(firstToken);
    String symbol = (String) firstToken;

    response.add(symbol);

    if (isStatusResponse(symbol)) {
      parseResponseText(response);
    } else if (equalsIgnoreCase(symbol, Responses.LIST)
        || equalsIgnoreCase(symbol, Responses.LSUB)) {
      parseListResponse(response);
    } else {
      Object token;
      while ((token = readToken(response)) != null) {
        if (!(token instanceof ImapList)) {
          response.add(token);
        }
      }
    }
  }
  /**
   * Parse {@code resp-text} tokens
   *
   * <p>Responses "OK", "PREAUTH", "BYE", "NO", "BAD", and continuation request responses can
   * contain {@code resp-text} tokens. We parse the {@code resp-text-code} part as tokens and read
   * the rest as sequence of characters to avoid the parser interpreting things like "{123}" as
   * start of a literal.
   *
   * <p>Example:
   *
   * <p>{@code * OK [UIDVALIDITY 3857529045] UIDs valid}
   *
   * <p>See RFC 3501, Section 9 Formal Syntax (resp-text)
   *
   * @param parent The {@link ImapResponse} instance that holds the parsed tokens of the response.
   * @throws IOException If there's a network error.
   * @see #isStatusResponse(String)
   */
  private void parseResponseText(ImapResponse parent) throws IOException {
    skipIfSpace();

    int next = inputStream.peek();
    if (next == '[') {
      parseList(parent, '[', ']');
      skipIfSpace();
    }

    String rest = readStringUntilEndOfLine();

    if (rest != null && !rest.isEmpty()) {
      // The rest is free-form text.
      parent.add(rest);
    }
  }
  /** Parse and return the response line. */
  private ImapResponse parseResponse() throws IOException, MessagingException {
    // We need to destroy the response if we get an exception.
    // So, we first store the response that's being built in responseToDestroy, until it's
    // completely built, at which point we copy it into responseToReturn and null out
    // responseToDestroyt.
    // If responseToDestroy is not null in finally, we destroy it because that means
    // we got an exception somewhere.
    ImapResponse responseToDestroy = null;
    final ImapResponse responseToReturn;

    try {
      final int ch = peek();
      if (ch == '+') { // Continuation request
        readByte(); // skip +
        expect(' ');
        responseToDestroy = new ImapResponse(null, true);

        // If it's continuation request, we don't really care what's in it.
        responseToDestroy.add(new ImapSimpleString(readUntilEol()));

        // Response has successfully been built.  Let's return it.
        responseToReturn = responseToDestroy;
        responseToDestroy = null;
      } else {
        // Status response or response data
        final String tag;
        if (ch == '*') {
          tag = null;
          readByte(); // skip *
          expect(' ');
        } else {
          tag = readUntil(' ');
        }
        responseToDestroy = new ImapResponse(tag, false);

        final ImapString firstString = parseBareString();
        responseToDestroy.add(firstString);

        // parseBareString won't eat a space after the string, so we need to skip it,
        // if exists.
        // If the next char is not ' ', it should be EOL.
        if (peek() == ' ') {
          readByte(); // skip ' '

          if (responseToDestroy.isStatusResponse()) { // It's a status response

            // Is there a response code?
            final int next = peek();
            if (next == '[') {
              responseToDestroy.add(parseList('[', ']'));
              if (peek() == ' ') { // Skip following space
                readByte();
              }
            }

            String rest = readUntilEol();
            if (!TextUtils.isEmpty(rest)) {
              // The rest is free-form text.
              responseToDestroy.add(new ImapSimpleString(rest));
            }
          } else { // It's a response data.
            parseElements(responseToDestroy, '\0');
          }
        } else {
          expect('\r');
          expect('\n');
        }

        // Response has successfully been built.  Let's return it.
        responseToReturn = responseToDestroy;
        responseToDestroy = null;
      }
    } finally {
      if (responseToDestroy != null) {
        // We get an exception.
        responseToDestroy.destroy();
      }
    }

    return responseToReturn;
  }