private void parseFStringFragment() {
    final SyntaxTreeBuilder builder = myContext.getBuilder();
    if (atToken(PyTokenTypes.FSTRING_FRAGMENT_START)) {
      final SyntaxTreeBuilder.Marker marker = builder.mark();
      nextToken();
      SyntaxTreeBuilder.Marker recoveryMarker = builder.mark();
      final boolean parsedExpression = myContext.getExpressionParser().parseExpressionOptional();
      if (parsedExpression) {
        recoveryMarker.drop();
        recoveryMarker = builder.mark();
      }
      boolean recovery = !parsedExpression;
      while (!builder.eof() && !atAnyOfTokens(PyTokenTypes.FSTRING_FRAGMENT_TYPE_CONVERSION,
                                              PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START,
                                              PyTokenTypes.FSTRING_FRAGMENT_END,
                                              PyTokenTypes.FSTRING_END,
                                              PyTokenTypes.STATEMENT_BREAK,
                                              PyTokenTypes.EQ)) {
        nextToken();
        recovery = true;
      }
      if (recovery) {
        recoveryMarker.error(parsedExpression ? message("unexpected.expression.part") : message("PARSE.expected.expression"));
        recoveryMarker.setCustomEdgeTokenBinders(null, CONSUME_COMMENTS_AND_SPACES_TO_LEFT);
      }
      else {
        recoveryMarker.drop();
      }

      matchToken(PyTokenTypes.EQ);
      final boolean hasTypeConversion = matchToken(PyTokenTypes.FSTRING_FRAGMENT_TYPE_CONVERSION);
      final boolean hasFormatPart = atToken(PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START);
      if (hasFormatPart) {
        parseFStringFragmentFormatPart();
      }
      @ParsingError String errorMessage = message("PARSE.expected.fstring.rbrace");
      if (!hasFormatPart && !atToken(PyTokenTypes.FSTRING_END)) {
        errorMessage = message("PARSE.expected.fstring.colon.or.rbrace");
        if (!hasTypeConversion) {
          errorMessage = message("PARSE.expected.fstring.type.conversion.or.colon.or.rbrace");
        }
      }

      checkMatches(PyTokenTypes.FSTRING_FRAGMENT_END, errorMessage);
      marker.setCustomEdgeTokenBinders(null, CONSUME_COMMENTS_AND_SPACES_TO_LEFT);
      marker.done(PyElementTypes.FSTRING_FRAGMENT);
    }
  }
private void parseFStringFragment()