@VisibleForTesting
  @NotNull
  static MessageHolder parseMessageHolder(@NotNull String pattern) {
    MessageHolder holder = new MessageHolder(pattern);
    while (!holder.hasRuntimeError && holder.hasNext()) {
      char ch = holder.nextPool();
      if (holder.getLastPart().getParsedType() == MessageFormatParsedType.STRING) {
        if (ch == '\'') {
          if (holder.hasNext() && holder.nextPeek() == '\'') {
            holder.addChar(ch);
            holder.nextPool();
          }
          else {
            holder.inQuote = !holder.inQuote;
            holder.lastQuoteIndex = holder.current;
          }
        }
        else if (ch == '{') {
          if (holder.inQuote) {
            int end = findEndOfQuotedPlaceholder(pattern, holder.current);
            if (end != -1) {
              holder.addError(MessageFormatErrorType.QUOTED_PLACEHOLDER, holder.current, end);
            }
            holder.addChar(ch);
          }
          else {
            holder.startFormatElement(ch);
          }
        }
        else {
          holder.addChar(ch);
        }
      }
      else {
        if (holder.inQuote) {
          if (ch == '\'') {
            holder.inQuote = false;
          }
          holder.addChar(ch);
        }
        else {
          switch (ch) {
            case ',' -> {
              if (!holder.moveSegmentOfFormatElement()) {
                holder.addChar(ch);
              }
            }
            case '{' -> {
              holder.braceStack++;
              holder.addChar(ch);
            }
            case ' ' -> {
              MessageFormatPart part = holder.getLastPart();
              if (!(part.getMessageFormatElement() != null &&
                    part.getMessageFormatElement().currentPart == MessageFormatElementPart.FORMAT_TYPE &&
                    part.getMessageFormatElement().formatTypeSegment.length() == 0)) {
                holder.addChar(ch);
              }
            }
            case '}' -> {
              if (holder.braceStack != 0) {
                holder.braceStack--;
                holder.addChar(ch);
              }
              else {
                holder.finishFormatElement(ch);
              }
            }
            case '\'' -> {
              holder.inQuote = true;
              holder.lastQuoteIndex = holder.current;
              holder.addChar(ch);
            }
            default -> holder.addChar(ch);
          }
        }
      }
    }

    MessageFormatPart lastPart = holder.getLastPart();
    if (holder.inQuote) {
      holder.addError(MessageFormatErrorType.UNPAIRED_QUOTE, holder.lastQuoteIndex, holder.lastQuoteIndex + 1);
    }
    if (lastPart.getMessageFormatElement() != null &&
        holder.braceStack == 0 &&
        holder.getLastPart().parsedType != MessageFormatParsedType.STRING) {
      holder.addError(MessageFormatErrorType.UNMATCHED_BRACE,
                      lastPart.getMessageFormatElement().indexSegmentStart - 1,
                      lastPart.getMessageFormatElement().indexSegmentStart);
    }
    else if (lastPart.getMessageFormatElement() != null && !lastPart.getMessageFormatElement().finished) {
      holder.addError(MessageFormatErrorType.UNCLOSED_BRACE_PLACEHOLDER,
                      lastPart.getMessageFormatElement().indexSegmentStart - 1,
                      lastPart.getMessageFormatElement().indexSegmentStart);
    }

    return holder;
  }
@VisibleForTesting
  @NotNull
  static MessageHolder parseMessageHolder(@NotNull String pattern)