Пример #1
0
  /*
   * Parses Groovy-style 'in' clause
   */
  private static boolean forInClauseParse(PsiBuilder builder, GroovyParser parser) {

    PsiBuilder.Marker marker = builder.mark();

    PsiBuilder.Marker declMarker = builder.mark();

    if (ParserUtils.lookAhead(builder, mIDENT, kIN)) {
      ParserUtils.eatElement(builder, PARAMETER);
      declMarker.drop();
      ParserUtils.getToken(builder, kIN);
      if (!ShiftExpression.parse(builder, parser)) {
        builder.error(GroovyBundle.message("expression.expected"));
      }
      marker.done(FOR_IN_CLAUSE);
      return true;
    }

    if (DeclarationStart.parse(builder, parser)) {
      if (Modifiers.parse(builder, parser)) {
        TypeSpec.parse(builder);
        return singleDeclNoInitParse(builder, marker, declMarker, parser);
      }
    }

    if (TypeSpec.parse(builder)) {
      return singleDeclNoInitParse(builder, marker, declMarker, parser);
    }

    declMarker.drop();
    marker.drop();
    return false;
  }
  private void beforeConsume(PsiBuilder builder, IElementType type) {
    if (type.equals(SS_VAR)) {
      varMarker = builder.mark();
      markingVar = true;
    }
    if (type.equals(SS_COMMENT_START)) {
      commentMarker = builder.mark();
      markingComment = true;
    }
    if (type.equals(SS_THEME_VAR)) {
      themeMarker = builder.mark();
      markingTheme = true;
    }

    if (type.equals(SS_BLOCK_START) && !markingBlock) {
      nextToken = getNextToken(builder);
      blockStartTokens = STATEMENT_MAP.get(nextToken);
      blockType = BLOCK_TYPE_MAP.get(nextToken);
      if (blockStartTokens != null) {
        blockTokenText = getNextTokenText(builder);
        blockMarker = builder.mark();
        markingBlock = true;
      }
    }

    if (markingTheme && !type.equals(SS_THEME_VAR) && !type.equals(SS_STRING)) {
      markingTheme = false;
    }
  }
  public static void parse(PsiBuilder builder, GroovyParser parser) {

    PsiBuilder.Marker annArgs = builder.mark();
    if (!ParserUtils.getToken(builder, mLPAREN)) {
      annArgs.done(ANNOTATION_ARGUMENTS);
      return;
    }

    if (ParserUtils.lookAhead(builder, mIDENT, mASSIGN)) {
      if (!parseAnnotationMemberValuePairs(builder, parser)) {
        annArgs.rollbackTo();
        return;
      }
    } else {
      PsiBuilder.Marker pairMarker = builder.mark();
      if (!parseAnnotationMemberValueInitializer(builder, parser)) {
        pairMarker.drop();
      } else {
        pairMarker.done(ANNOTATION_MEMBER_VALUE_PAIR);
      }
    }

    ParserUtils.getToken(builder, mNLS);

    if (!ParserUtils.getToken(builder, mRPAREN)) {
      builder.error(GroovyBundle.message("rparen.expected"));
    }
    annArgs.done(ANNOTATION_ARGUMENTS);
  }
Пример #4
0
  private static boolean tradForClauseParse(PsiBuilder builder, GroovyParser parser) {

    PsiBuilder.Marker marker = builder.mark();

    if (ParserUtils.getToken(builder, mSEMI)
        || (Declaration.parse(builder, false, parser) && ParserUtils.getToken(builder, mSEMI))) {
      StrictContextExpression.parse(builder, parser);
      ParserUtils.getToken(builder, mSEMI, GroovyBundle.message("semi.expected"));
      ParserUtils.getToken(builder, mNLS);
      if (!mRPAREN.equals(builder.getTokenType())) {
        controlExpressionListParse(builder, parser);
      }
    } else {
      marker.rollbackTo();
      marker = builder.mark();
      controlExpressionListParse(builder, parser);
      ParserUtils.getToken(builder, mSEMI, GroovyBundle.message("semi.expected"));
      StrictContextExpression.parse(builder, parser);
      ParserUtils.getToken(builder, mSEMI, GroovyBundle.message("semi.expected"));
      ParserUtils.getToken(builder, mNLS);
      if (!mRPAREN.equals(builder.getTokenType())) {
        controlExpressionListParse(builder, parser);
      }
    }

    marker.done(FOR_TRADITIONAL_CLAUSE);
    return true;
  }
  public static boolean parseMasonMethod(
      PsiBuilder b, int l, IElementType closeToken, IElementType statementTokenType) {
    boolean r = false;

    PsiBuilder.Marker methodMarker = b.mark();
    b.advanceLexer();
    PsiBuilder.Marker subMarker = b.mark();
    if (PerlParserUtil.consumeToken(b, IDENTIFIER)) {
      subMarker.collapse(SUB);
      PerlParserImpl.method_signature(b, l);
      if (PerlParserUtil.consumeToken(b, MASON_TAG_CLOSER)) {
        PsiBuilder.Marker blockMarker = b.mark();
        PerlParserImpl.block_content(b, l);

        if (b.getTokenType() == closeToken) {
          blockMarker.done(BLOCK);
          blockMarker.setCustomEdgeTokenBinders(
              WhitespacesBinders.GREEDY_LEFT_BINDER, WhitespacesBinders.GREEDY_RIGHT_BINDER);
          b.advanceLexer();
          methodMarker.done(statementTokenType);
          r = true;
        }
      }
    }

    if (!r) {
      methodMarker.rollbackTo();
    }

    return r || recoverToGreedy(b, closeToken, "Error");
  }
  public static void parseDefine(PsiBuilder builder) {
    PsiBuilder.Marker maker = builder.mark();

    // #define
    advanceLexerAndSkipLines(builder);

    // var name
    doneOneToken(builder, CPsiCompilerVariable.class);

    PsiBuilder.Marker valueMarker = builder.mark();

    while (!builder.eof()) {
      if (builder.getTokenType() == NEW_LINE) break;

      if (builder.getTokenType() == NEXT_LINE) builder.advanceLexer();

      builder.advanceLexer();
    }

    done(valueMarker, CPsiSharpDefineValue.class);

    done(maker, CPsiSharpDefine.class);

    skipLines(builder);
  }
  @Nullable
  private PsiBuilder.Marker parseUnary(final PsiBuilder builder) {
    final IElementType tokenType = builder.getTokenType();

    if (PREFIX_OPS.contains(tokenType)) {
      final PsiBuilder.Marker unary = builder.mark();
      builder.advanceLexer();

      final PsiBuilder.Marker operand = parseUnary(builder);
      if (operand == null) {
        error(builder, JavaErrorMessages.message("expected.expression"));
      }

      unary.done(JavaElementType.PREFIX_EXPRESSION);
      return unary;
    } else if (tokenType == JavaTokenType.LPARENTH) {
      final PsiBuilder.Marker typeCast = builder.mark();
      builder.advanceLexer();

      ReferenceParser.TypeInfo typeInfo =
          myParser
              .getReferenceParser()
              .parseTypeInfo(
                  builder,
                  ReferenceParser.EAT_LAST_DOT
                      | ReferenceParser.WILDCARD
                      | ReferenceParser.CONJUNCTIONS
                      | ReferenceParser.INCOMPLETE_ANNO);
      if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) {
        typeCast.rollbackTo();
        return parsePostfix(builder);
      }

      if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType()) && !typeInfo.isPrimitive) {
        typeCast.rollbackTo();
        return parsePostfix(builder);
      }

      final PsiBuilder.Marker expr = parseUnary(builder);
      if (expr == null) {
        if (!typeInfo
            .isParameterized) { // cannot parse correct parenthesized expression after correct
                                // parameterized type
          typeCast.rollbackTo();
          return parsePostfix(builder);
        } else {
          error(builder, JavaErrorMessages.message("expected.expression"));
        }
      }

      typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION);
      return typeCast;
    } else {
      return parsePostfix(builder);
    }
  }
  @Nullable
  private PsiBuilder.Marker parseArrayInitializer(final PsiBuilder builder) {
    if (builder.getTokenType() != JavaTokenType.LBRACE) return null;

    final PsiBuilder.Marker arrayInit = builder.mark();
    builder.advanceLexer();

    boolean expressionMissed = false;
    PsiBuilder.Marker lastComma = null;
    while (true) {
      if (builder.getTokenType() == JavaTokenType.RBRACE) {
        builder.advanceLexer();
        break;
      }

      if (builder.getTokenType() == null) {
        error(builder, JavaErrorMessages.message("expected.rbrace"));
        break;
      }

      if (expressionMissed && lastComma != null) {
        // before comma must be an expression
        lastComma
            .precede()
            .errorBefore(JavaErrorMessages.message("expected.expression"), lastComma);
        lastComma.drop();
        lastComma = null;
      }

      final PsiBuilder.Marker arg = parse(builder);
      if (arg == null) {
        if (builder.getTokenType() == JavaTokenType.COMMA) {
          expressionMissed = true;
          lastComma = builder.mark();
        } else {
          error(builder, JavaErrorMessages.message("expected.rbrace"));
          break;
        }
      }

      final IElementType tokenType = builder.getTokenType();
      if (tokenType == JavaTokenType.COMMA) {
        builder.advanceLexer();
      } else if (tokenType != JavaTokenType.RBRACE) {
        error(builder, JavaErrorMessages.message("expected.comma"));
      }
    }

    if (lastComma != null) {
      lastComma.drop();
    }

    arrayInit.done(JavaElementType.ARRAY_INITIALIZER_EXPRESSION);
    return arrayInit;
  }
 /**
  * @param root The file currently being parsed
  * @param builder used to build the parse tree
  * @return parsed tree
  */
 @NotNull
 @Override
 public ASTNode parse(IElementType root, PsiBuilder builder) {
   PsiBuilder.Marker rootMarker = builder.mark();
   PsiBuilder.Marker wrapperMarker = builder.mark();
   builder.setDebugMode(true);
   // Process all tokens
   parseTree(builder);
   wrapperMarker.done(SS_STATEMENTS);
   rootMarker.done(root);
   return builder.getTreeBuilt();
 }
 private void getNextTokenValue(PsiBuilder builder) {
   PsiBuilder.Marker rb = builder.mark();
   builder.advanceLexer();
   nextToken = builder.getTokenType();
   nextTokenText = builder.getTokenText();
   rb.rollbackTo();
 }
Пример #11
0
  @Nullable
  private static IElementType getGtTokenType(final PsiBuilder builder) {
    final PsiBuilder.Marker sp = builder.mark();

    IElementType tokenType = builder.getTokenType();
    if (tokenType == JavaTokenType.GT) {
      builder.advanceLexer();
      if (builder.getTokenType() == JavaTokenType.GT) {
        builder.advanceLexer();
        if (builder.getTokenType() == JavaTokenType.GT) {
          builder.advanceLexer();
          if (builder.getTokenType() == JavaTokenType.EQ) {
            tokenType = JavaTokenType.GTGTGTEQ;
          } else {
            tokenType = JavaTokenType.GTGTGT;
          }
        } else if (builder.getTokenType() == JavaTokenType.EQ) {
          tokenType = JavaTokenType.GTGTEQ;
        } else {
          tokenType = JavaTokenType.GTGT;
        }
      } else if (builder.getTokenType() == JavaTokenType.EQ) {
        tokenType = JavaTokenType.GE;
      }
    }

    sp.rollbackTo();
    return tokenType;
  }
Пример #12
0
  @NotNull
  public ASTNode parse(IElementType root, PsiBuilder builder) {
    if (ALLOW_ONLY_ONE_THREAD) {
      try {
        SEMAPHORE.acquire();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    // builder.setDebugMode(true);
    final PsiBuilder.Marker rootMarker = builder.mark();
    if (!builder.eof()) { // Empty file is not an error
      final GLSLParsing theRealParser = new GLSLParsing(builder);

      theRealParser.parseTranslationUnit();
      while (!builder.eof()) // exhaust the file if unable to parse everything
      builder.advanceLexer();
    }

    rootMarker.done(root);

    if (ALLOW_ONLY_ONE_THREAD) {
      SEMAPHORE.release();
    }
    return builder.getTreeBuilt();
  }
  @Nullable
  private PsiBuilder.Marker parseLambdaExpression(
      final PsiBuilder builder, final boolean typed, @Nullable final PsiBuilder.Marker typeList) {
    final PsiBuilder.Marker start = typeList != null ? typeList.precede() : builder.mark();

    myParser.getDeclarationParser().parseLambdaParameterList(builder, typed);

    if (!expect(builder, JavaTokenType.ARROW)) {
      start.rollbackTo();
      return null;
    }

    final PsiBuilder.Marker body;
    if (builder.getTokenType() == JavaTokenType.LBRACE) {
      body = myParser.getStatementParser().parseCodeBlock(builder);
    } else {
      body = parse(builder);
    }

    if (body == null) {
      builder.error(JavaErrorMessages.message("expected.lbrace"));
    }

    start.done(JavaElementType.LAMBDA_EXPRESSION);
    return start;
  }
Пример #14
0
  public static boolean parse(
      PsiBuilder builder, boolean isInClass, boolean isInAnnotation, GroovyParser parser) {
    PsiBuilder.Marker declMarker = builder.mark();
    // allows error messages
    boolean modifiersParsed = Modifiers.parse(builder, parser);

    final boolean methodStart = mLT == builder.getTokenType();
    final IElementType type =
        parseAfterModifiers(
            builder, isInClass, isInAnnotation, parser, declMarker, modifiersParsed);
    if (type == WRONGWAY) {
      if (modifiersParsed && methodStart) {
        declMarker.error(GroovyBundle.message("method.definitions.expected"));
        return false;
      }

      declMarker.rollbackTo();
      if (modifiersParsed) {
        builder.error(GroovyBundle.message("variable.definitions.expected"));
      }

      return false;
    }

    if (type != null) {
      declMarker.done(type);
    } else {
      declMarker.drop();
    }
    return true;
  }
 private void parseListLiteralExpression(final PsiBuilder builder, boolean isTargetExpression) {
   LOG.assertTrue(builder.getTokenType() == PyTokenTypes.LBRACKET);
   final PsiBuilder.Marker expr = builder.mark();
   builder.advanceLexer();
   if (builder.getTokenType() == PyTokenTypes.RBRACKET) {
     builder.advanceLexer();
     expr.done(PyElementTypes.LIST_LITERAL_EXPRESSION);
     return;
   }
   if (!parseSingleExpression(isTargetExpression)) {
     builder.error(message("PARSE.expected.expression"));
   }
   if (builder.getTokenType() == PyTokenTypes.FOR_KEYWORD) {
     parseComprehension(expr, PyTokenTypes.RBRACKET, PyElementTypes.LIST_COMP_EXPRESSION);
   } else {
     while (builder.getTokenType() != PyTokenTypes.RBRACKET) {
       if (!matchToken(PyTokenTypes.COMMA)) {
         builder.error("expected ',' or ']'");
       }
       if (atToken(PyTokenTypes.RBRACKET)) {
         break;
       }
       if (!parseSingleExpression(isTargetExpression)) {
         builder.error(message("PARSE.expected.expr.or.comma.or.bracket"));
         break;
       }
     }
     checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket"));
     expr.done(PyElementTypes.LIST_LITERAL_EXPRESSION);
   }
 }
 public PsiBuilder.Marker mark(boolean couldBeRolledBack) {
   final PsiBuilder.Marker marker = myBuilder.mark();
   if (couldBeRolledBack) {
     myIndents.put(marker, myCurrentIndent);
     myNewLines.put(marker, myNewLine);
   }
   return marker;
 }
 private void parseReprExpression(PsiBuilder builder) {
   LOG.assertTrue(builder.getTokenType() == PyTokenTypes.TICK);
   final PsiBuilder.Marker expr = builder.mark();
   builder.advanceLexer();
   parseExpression();
   checkMatches(PyTokenTypes.TICK, message("PARSE.expected.tick"));
   expr.done(PyElementTypes.REPR_EXPRESSION);
 }
  @Nullable
  private PsiBuilder.Marker parseLambdaAfterParenth(
      final PsiBuilder builder, @Nullable final PsiBuilder.Marker typeList) {
    final boolean isLambda;
    final boolean isTyped;

    final IElementType nextToken1 = builder.lookAhead(1);
    final IElementType nextToken2 = builder.lookAhead(2);
    if (nextToken1 == JavaTokenType.RPARENTH && nextToken2 == JavaTokenType.ARROW) {
      isLambda = true;
      isTyped = false;
    } else if (nextToken1 == JavaTokenType.AT
        || ElementType.MODIFIER_BIT_SET.contains(nextToken1)
        || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(nextToken1)) {
      isLambda = true;
      isTyped = true;
    } else if (nextToken1 == JavaTokenType.IDENTIFIER) {
      if (nextToken2 == JavaTokenType.COMMA
          || nextToken2 == JavaTokenType.RPARENTH && builder.lookAhead(3) == JavaTokenType.ARROW) {
        isLambda = true;
        isTyped = false;
      } else if (nextToken2 == JavaTokenType.ARROW) {
        isLambda = false;
        isTyped = false;
      } else {
        boolean arrow = false;

        final PsiBuilder.Marker marker = builder.mark();
        while (!builder.eof()) {
          builder.advanceLexer();
          final IElementType tokenType = builder.getTokenType();
          if (tokenType == JavaTokenType.ARROW) {
            arrow = true;
            break;
          }
          if (tokenType == JavaTokenType.RPARENTH) {
            arrow = builder.lookAhead(1) == JavaTokenType.ARROW;
            break;
          } else if (tokenType == JavaTokenType.LPARENTH
              || tokenType == JavaTokenType.SEMICOLON
              || tokenType == JavaTokenType.LBRACE
              || tokenType == JavaTokenType.RBRACE) {
            break;
          }
        }
        marker.rollbackTo();

        isLambda = arrow;
        isTyped = true;
      }
    } else {
      isLambda = false;
      isTyped = false;
    }

    return isLambda ? parseLambdaExpression(builder, isTyped, typeList) : null;
  }
Пример #19
0
  @NotNull
  public ASTNode parse(IElementType root, PsiBuilder builder) {

    final PsiBuilder.Marker rootMarker = builder.mark();

    while (!builder.eof()) {
      IElementType token = builder.getTokenType();

      if (token != null) {
        builder.mark().done(token);
      }

      builder.advanceLexer();
    }

    rootMarker.done(root);
    return builder.getTreeBuilt();
  }
  public static void parseIf(PsiBuilder builder) {
    PsiBuilder.Marker marker = builder.mark();

    builder.advanceLexer();

    if (builder.getTokenType() == IDENTIFIER) doneOneToken(builder, CPsiCompilerVariable.class);
    else error(builder, "IDENTIFIER.expected");

    builder.advanceLexer();

    if (builder.getTokenType() == NEW_LINE) builder.advanceLexer();

    skipLines(builder);

    if (builder.getTokenType() != S_ENDIF_KEYWORD) {
      PsiBuilder.Marker bodyMarker = builder.mark();

      while (!builder.eof()) {
        parse(builder, 0);

        if (builder.getTokenType() == S_ENDIF_KEYWORD || builder.getTokenType() == S_ELSE_KEYWORD)
          break;
      }

      done(bodyMarker, CPsiSharpIfBody.class);

      if (builder.getTokenType() == S_ELSE_KEYWORD) {
        builder.advanceLexer();

        PsiBuilder.Marker elseBody = builder.mark();

        while (!builder.eof()) {
          parse(builder, 0);

          if (builder.getTokenType() == S_ENDIF_KEYWORD || builder.getTokenType() == S_ELSE_KEYWORD)
            break;
        }
        done(elseBody, CPsiSharpIfBody.class);
      }
    }
    checkMatchesWithoutLines(builder, S_ENDIF_KEYWORD, "S_END_IF.expected");

    done(marker, CPsiSharpIfDef.class);
  }
Пример #21
0
 /**
  * Checks and parses pragma to package token
  *
  * @param b PerlBuilder
  * @param l parsing level
  * @param sourceTokenType source token type
  * @param targetTokenType token type to collapse to
  * @return result
  */
 public static boolean checkAndCollapseToken(
     PsiBuilder b, int l, IElementType sourceTokenType, IElementType targetTokenType) {
   if (b.getTokenType() == sourceTokenType) {
     PsiBuilder.Marker m = b.mark();
     b.advanceLexer();
     m.collapse(targetTokenType);
     return true;
   }
   return false;
 }
Пример #22
0
 /**
  * Parsing label declaration LABEL:
  *
  * @param b PerlBuilder
  * @param l parsing level
  * @return parsing result
  */
 public static boolean parseLabelDeclaration(PsiBuilder b, int l) {
   if (CONVERTABLE_TOKENS.contains(b.getTokenType()) && b.lookAhead(1) == COLON) {
     PsiBuilder.Marker m = b.mark();
     b.advanceLexer();
     m.collapse(LABEL);
     b.advanceLexer();
     return true;
   }
   return false;
 }
Пример #23
0
 /**
  * Checks for version token and convert if necessary
  *
  * @param b PerlBuilder
  * @param l parsing level
  * @return parsing result
  */
 public static boolean parsePerlVersion(PsiBuilder b, int l) {
   if (b.getTokenType() == NUMBER_VERSION) return consumeToken(b, NUMBER_VERSION);
   else if (VERSION_TOKENS.contains(b.getTokenType())) {
     PsiBuilder.Marker m = b.mark();
     b.advanceLexer();
     m.collapse(NUMBER_VERSION);
     return true;
   }
   return false;
 }
 protected static boolean recoverTo(PsiBuilder b, IElementType toElement, String errorMessage) {
   // recover bad code
   PsiBuilder.Marker errorMarker = b.mark();
   while (!b.eof() && b.getTokenType() != toElement) {
     b.advanceLexer();
     ;
   }
   errorMarker.error(errorMessage);
   return b.eof();
 }
Пример #25
0
 /**
  * Parses parenthesised list or parenthesised list element. To avoid double parenthesised
  * expression parsing
  *
  * @param b PerlBuilder
  * @param l parsing level
  * @return parsing result
  */
 public static boolean parseListOrListElement(PsiBuilder b, int l) {
   PsiBuilder.Marker m = b.mark();
   if (PerlParser.parenthesised_expr(b, l)) {
     if (PerlParser.array_index(b, l)) m.done(ANON_ARRAY_ELEMENT);
     else m.drop();
     return true;
   }
   m.drop();
   return false;
 }
Пример #26
0
  public static boolean convertBracedString(PsiBuilder b, int l) {

    if (CONVERTABLE_TOKENS.contains(b.getTokenType()) && b.lookAhead(1) == RIGHT_BRACE) {
      // fixme shouldn't we add string_sq here?
      PsiBuilder.Marker m = b.mark();
      b.advanceLexer();
      m.collapse(STRING_CONTENT);
      return true;
    }
    return false;
  }
Пример #27
0
  // @todo this is really raw
  public static boolean parseVariableAttributes(PsiBuilder b, int l) {

    PsiBuilder.Marker m = null;
    while (!b.eof() && !VARIABLE_ATTRIBUTE_STOP_TOKENS.contains(b.getTokenType())) {
      if (m == null) m = b.mark();
      b.advanceLexer();
    }
    if (m != null) m.collapse(VAR_ATTRIBUTE);

    return true;
  }
 public static boolean parseTokens(
     PsiBuilder builder, boolean smart, int pin, IElementType... tokens) {
   PsiBuilder.Marker marker = builder.mark();
   boolean result = consumeTokens(builder, smart, pin, tokens);
   if (!result) {
     marker.rollbackTo();
   } else {
     marker.drop();
   }
   return result;
 }
Пример #29
0
  /**
   * Joining several regex tokens into one to lighten PSI tree. Temporary solution, until regex
   * parsing is implemented
   *
   * @param b PerlBuilder
   * @param l parsing level
   * @return parsing result
   */
  public static boolean joinRegexTokens(PsiBuilder b, int l) {
    if (b.getTokenType() == REGEX_TOKEN) {
      PsiBuilder.Marker m = b.mark();

      while (b.getTokenType() == REGEX_TOKEN) b.advanceLexer();

      m.collapse(REGEX_TOKEN);
      return true;
    }
    return false;
  }
 public boolean parseStringLiteralExpression() {
   final PsiBuilder builder = myContext.getBuilder();
   if (PyTokenTypes.STRING_NODES.contains(builder.getTokenType())) {
     final PsiBuilder.Marker marker = builder.mark();
     while (PyTokenTypes.STRING_NODES.contains(builder.getTokenType())) {
       nextToken();
     }
     marker.done(PyElementTypes.STRING_LITERAL_EXPRESSION);
     return true;
   }
   return false;
 }