@Nullable
  public PsiBuilder.Marker parseConditional(final PsiBuilder builder) {
    final PsiBuilder.Marker condition = parseExpression(builder, ExprType.CONDITIONAL_OR);
    if (condition == null) return null;

    if (builder.getTokenType() != JavaTokenType.QUEST) return condition;
    final PsiBuilder.Marker ternary = condition.precede();
    builder.advanceLexer();

    final PsiBuilder.Marker truePart = parse(builder);
    if (truePart == null) {
      error(builder, JavaErrorMessages.message("expected.expression"));
      ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
      return ternary;
    }

    if (builder.getTokenType() != JavaTokenType.COLON) {
      error(builder, JavaErrorMessages.message("expected.colon"));
      ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
      return ternary;
    }
    builder.advanceLexer();

    final PsiBuilder.Marker falsePart = parseConditional(builder);
    if (falsePart == null) {
      error(builder, JavaErrorMessages.message("expected.expression"));
      ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
      return ternary;
    }

    ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
    return ternary;
  }
  @Nullable
  private static PsiBuilder.Marker parseBinary(
      final PsiBuilder builder, final ExprType type, final TokenSet ops) {
    PsiBuilder.Marker left = parseExpression(builder, type);
    if (left == null) return null;

    while (true) {
      final IElementType tokenType = getGtTokenType(builder);
      if (tokenType == null || !ops.contains(tokenType)) break;

      final PsiBuilder.Marker binary = left.precede();
      advanceGtToken(builder, tokenType);

      final PsiBuilder.Marker right = parseExpression(builder, type);
      if (right == null) {
        error(builder, JavaErrorMessages.message("expected.expression"));
        binary.done(JavaElementType.BINARY_EXPRESSION);
        return binary;
      }

      binary.done(JavaElementType.BINARY_EXPRESSION);
      left = binary;
    }

    return left;
  }
  @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;
  }
  @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;
  }
  @Nullable
  private PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
    PsiBuilder.Marker operand = parsePrimary(builder, null, -1);
    if (operand == null) return null;

    while (POSTFIX_OPS.contains(builder.getTokenType())) {
      final PsiBuilder.Marker postfix = operand.precede();
      builder.advanceLexer();
      postfix.done(JavaElementType.POSTFIX_EXPRESSION);
      operand = postfix;
    }

    return operand;
  }
示例#6
0
  /*
   * import
   *   : "import" ("namespace" ".")? SimpleName{"."} ("." "*" | "as" SimpleName)? SEMI?
   *   ;
   */
  private void parseImportDirective() {
    assert _at(IMPORT_KEYWORD);
    PsiBuilder.Marker importDirective = mark();
    advance(); // IMPORT_KEYWORD

    PsiBuilder.Marker qualifiedName = mark();
    if (at(PACKAGE_KEYWORD)) {
      advance(); // PACKAGE_KEYWORD
      expect(DOT, "Expecting '.'", TokenSet.create(IDENTIFIER, MUL, SEMICOLON));
    }

    PsiBuilder.Marker reference = mark();
    expect(IDENTIFIER, "Expecting qualified name");
    reference.done(REFERENCE_EXPRESSION);

    while (at(DOT) && lookahead(1) != MUL) {
      advance(); // DOT

      reference = mark();
      if (expect(
          IDENTIFIER,
          "Qualified name must be a '.'-separated identifier list",
          IMPORT_RECOVERY_SET)) {
        reference.done(REFERENCE_EXPRESSION);
      } else {
        reference.drop();
      }

      PsiBuilder.Marker precede = qualifiedName.precede();
      qualifiedName.done(DOT_QUALIFIED_EXPRESSION);
      qualifiedName = precede;
    }
    qualifiedName.drop();

    if (at(DOT)) {
      advance(); // DOT
      assert _at(MUL);
      advance(); // MUL
      handleUselessRename();
    }
    if (at(AS_KEYWORD)) {
      advance(); // AS_KEYWORD
      expect(IDENTIFIER, "Expecting identifier", TokenSet.create(SEMICOLON));
    }
    consumeIf(SEMICOLON);
    importDirective.done(IMPORT_DIRECTIVE);
  }
  /*
   * postfixUnaryExpression
   *   : atomicExpression postfixUnaryOperation*
   *   : callableReference postfixUnaryOperation*
   *   ;
   *
   * postfixUnaryOperation
   *   : "++" : "--" : "!!"
   *   : typeArguments? valueArguments (getEntryPoint? functionLiteral)
   *   : typeArguments (getEntryPoint? functionLiteral)
   *   : arrayAccess
   *   : memberAccessOperation postfixUnaryExpression // TODO: Review
   *   ;
   */
  private void parsePostfixExpression() {
    PsiBuilder.Marker expression = mark();

    boolean firstExpressionParsed;
    boolean doubleColonExpression = parseDoubleColonExpression();
    if (!doubleColonExpression) {
      firstExpressionParsed = parseAtomicExpression();
    } else {
      firstExpressionParsed = true;
    }

    while (true) {
      if (interruptedWithNewLine()) {
        break;
      } else if (at(LBRACKET)) {
        parseArrayAccess();
        expression.done(ARRAY_ACCESS_EXPRESSION);
      } else if (!doubleColonExpression && parseCallSuffix()) {
        expression.done(CALL_EXPRESSION);
      } else if (at(DOT) || at(SAFE_ACCESS)) {
        IElementType expressionType = at(DOT) ? DOT_QUALIFIED_EXPRESSION : SAFE_ACCESS_EXPRESSION;
        advance(); // DOT or SAFE_ACCESS

        if (!firstExpressionParsed) {
          expression.drop();
          expression = mark();
        }

        parseCallExpression();

        if (firstExpressionParsed) {
          expression.done(expressionType);
        } else {
          firstExpressionParsed = true;
          continue;
        }
      } else if (atSet(Precedence.POSTFIX.getOperations())) {
        parseOperationReference();
        expression.done(POSTFIX_EXPRESSION);
      } else {
        break;
      }
      expression = expression.precede();
    }
    expression.drop();
  }
  private boolean parseANDTestExpression(boolean stopOnIn, boolean isTargetExpression) {
    PsiBuilder.Marker expr = myBuilder.mark();
    if (!parseNOTTestExpression(stopOnIn, isTargetExpression)) {
      expr.drop();
      return false;
    }
    while (myBuilder.getTokenType() == PyTokenTypes.AND_KEYWORD) {
      myBuilder.advanceLexer();
      if (!parseNOTTestExpression(stopOnIn, isTargetExpression)) {
        myBuilder.error(message("PARSE.expected.expression"));
      }
      expr.done(PyElementTypes.BINARY_EXPRESSION);
      expr = expr.precede();
    }

    expr.drop();
    return true;
  }
  private boolean parseAdditiveExpression(final PsiBuilder myBuilder, boolean isTargetExpression) {
    PsiBuilder.Marker expr = myBuilder.mark();
    if (!parseMultiplicativeExpression(isTargetExpression)) {
      expr.drop();
      return false;
    }
    while (PyTokenTypes.ADDITIVE_OPERATIONS.contains(myBuilder.getTokenType())) {
      myBuilder.advanceLexer();
      if (!parseMultiplicativeExpression(isTargetExpression)) {
        myBuilder.error(message("PARSE.expected.expression"));
      }
      expr.done(PyElementTypes.BINARY_EXPRESSION);
      expr = expr.precede();
    }

    expr.drop();
    return true;
  }
  private boolean parseBitwiseANDExpression(boolean isTargetExpression) {
    PsiBuilder.Marker expr = myBuilder.mark();
    if (!parseShiftExpression(isTargetExpression)) {
      expr.drop();
      return false;
    }
    while (atToken(PyTokenTypes.AND)) {
      myBuilder.advanceLexer();
      if (!parseShiftExpression(isTargetExpression)) {
        myBuilder.error(message("PARSE.expected.expression"));
      }
      expr.done(PyElementTypes.BINARY_EXPRESSION);
      expr = expr.precede();
    }

    expr.drop();
    return true;
  }
示例#11
0
  /*
   * element (operation element)*
   *
   * see the precedence table
   */
  private void parseBinaryExpression(Precedence precedence) {
    //        System.out.println(precedence.name() + " at " + myBuilder.getTokenText());

    PsiBuilder.Marker expression = mark();

    precedence.parseHigherPrecedence(this);

    while (!interruptedWithNewLine() && atSet(precedence.getOperations())) {
      IElementType operation = tt();

      parseOperationReference();

      JetNodeType resultType = precedence.parseRightHandSide(operation, this);
      expression.done(resultType);
      expression = expression.precede();
    }

    expression.drop();
  }
示例#12
0
  /*
   * userType
   *   : ("namespace" ".")? simpleUserType{"."}
   *   ;
   */
  void parseUserType() {
    PsiBuilder.Marker userType = mark();

    if (at(PACKAGE_KEYWORD)) {
      advance(); // PACKAGE_KEYWORD
      expect(DOT, "Expecting '.'", TokenSet.create(IDENTIFIER));
    }

    PsiBuilder.Marker reference = mark();
    while (true) {
      if (expect(
          IDENTIFIER,
          "Expecting type name",
          TokenSet.orSet(
              JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW))) {
        reference.done(REFERENCE_EXPRESSION);
      } else {
        reference.drop();
        break;
      }

      parseTypeArgumentList();
      if (!at(DOT)) {
        break;
      }
      if (lookahead(1) == LPAR) {
        // This may be a receiver for a function type
        //   Int.(Int) -> Int
        break;
      }

      PsiBuilder.Marker precede = userType.precede();
      userType.done(USER_TYPE);
      userType = precede;

      advance(); // DOT
      reference = mark();
    }

    userType.done(USER_TYPE);
  }
  @Nullable
  private PsiBuilder.Marker parseAssignment(final PsiBuilder builder) {
    final PsiBuilder.Marker left = parseConditional(builder);
    if (left == null) return null;

    final IElementType tokenType = getGtTokenType(builder);
    if (ASSIGNMENT_OPS.contains(tokenType) && tokenType != null) {
      final PsiBuilder.Marker assignment = left.precede();
      advanceGtToken(builder, tokenType);

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

      assignment.done(JavaElementType.ASSIGNMENT_EXPRESSION);
      return assignment;
    }

    return left;
  }
  @Nullable
  private PsiBuilder.Marker parseRelational(final PsiBuilder builder) {
    PsiBuilder.Marker left = parseExpression(builder, ExprType.SHIFT);
    if (left == null) return null;

    IElementType tokenType;
    while ((tokenType = getGtTokenType(builder)) != null) {
      final IElementType toCreate;
      final ExprType toParse;
      if (RELATIONAL_OPS.contains(tokenType)) {
        toCreate = JavaElementType.BINARY_EXPRESSION;
        toParse = ExprType.SHIFT;
      } else if (tokenType == JavaTokenType.INSTANCEOF_KEYWORD) {
        toCreate = JavaElementType.INSTANCE_OF_EXPRESSION;
        toParse = ExprType.TYPE;
      } else {
        break;
      }

      final PsiBuilder.Marker expression = left.precede();
      advanceGtToken(builder, tokenType);

      final PsiBuilder.Marker right = parseExpression(builder, toParse);
      if (right == null) {
        error(
            builder,
            toParse == ExprType.TYPE
                ? JavaErrorMessages.message("expected.type")
                : JavaErrorMessages.message("expected.expression"));
        expression.done(toCreate);
        return expression;
      }

      expression.done(toCreate);
      left = expression;
    }

    return left;
  }
  private boolean parseComparisonExpression(boolean stopOnIn, boolean isTargetExpression) {
    PsiBuilder.Marker expr = myBuilder.mark();
    if (!parseStarExpression(isTargetExpression)) {
      expr.drop();
      return false;
    }
    if (stopOnIn && atToken(PyTokenTypes.IN_KEYWORD)) {
      expr.drop();
      return true;
    }
    while (PyTokenTypes.COMPARISON_OPERATIONS.contains(myBuilder.getTokenType())) {
      if (atToken(PyTokenTypes.NOT_KEYWORD)) {
        PsiBuilder.Marker notMarker = myBuilder.mark();
        myBuilder.advanceLexer();
        if (!atToken(PyTokenTypes.IN_KEYWORD)) {
          notMarker.rollbackTo();
          break;
        }
        notMarker.drop();
        myBuilder.advanceLexer();
      } else if (atToken(PyTokenTypes.IS_KEYWORD)) {
        myBuilder.advanceLexer();
        if (myBuilder.getTokenType() == PyTokenTypes.NOT_KEYWORD) {
          myBuilder.advanceLexer();
        }
      } else {
        myBuilder.advanceLexer();
      }

      if (!parseBitwiseORExpression(isTargetExpression)) {
        myBuilder.error(message("PARSE.expected.expression"));
      }
      expr.done(PyElementTypes.BINARY_EXPRESSION);
      expr = expr.precede();
    }

    expr.drop();
    return true;
  }
  @Nullable
  private PsiBuilder.Marker parseBinary(
      final PsiBuilder builder, final ExprType type, final TokenSet ops) {
    PsiBuilder.Marker result = parseExpression(builder, type);
    if (result == null) return null;
    int operandCount = 1;

    IElementType tokenType = getGtTokenType(builder);
    IElementType currentExprTokenType = tokenType;
    while (true) {
      if (tokenType == null || !ops.contains(tokenType)) break;

      advanceGtToken(builder, tokenType);

      final PsiBuilder.Marker right = parseExpression(builder, type);
      operandCount++;
      tokenType = getGtTokenType(builder);
      if (tokenType == null
          || !ops.contains(tokenType)
          || tokenType != currentExprTokenType
          || right == null) {
        // save
        result = result.precede();
        if (right == null) {
          error(builder, JavaErrorMessages.message("expected.expression"));
        }
        result.done(
            operandCount > 2
                ? JavaElementType.POLYADIC_EXPRESSION
                : JavaElementType.BINARY_EXPRESSION);
        if (right == null) break;
        currentExprTokenType = tokenType;
        operandCount = 1;
      }
    }

    return result;
  }
示例#17
0
  /*
   * postfixUnaryExpression
   *   : atomicExpression postfixUnaryOperation*
   *   : callableReference postfixUnaryOperation*
   *   ;
   *
   * postfixUnaryOperation
   *   : "++" : "--" : "!!"
   *   : typeArguments? valueArguments (getEntryPoint? functionLiteral)
   *   : typeArguments (getEntryPoint? functionLiteral)
   *   : arrayAccess
   *   : memberAccessOperation postfixUnaryExpression // TODO: Review
   *   ;
   */
  private void parsePostfixExpression() {
    PsiBuilder.Marker expression = mark();

    boolean doubleColonExpression = parseDoubleColonExpression();
    if (!doubleColonExpression) {
      parseAtomicExpression();
    }

    while (true) {
      if (interruptedWithNewLine()) {
        break;
      } else if (at(LBRACKET)) {
        parseArrayAccess();
        expression.done(ARRAY_ACCESS_EXPRESSION);
      } else if (!doubleColonExpression && parseCallSuffix()) {
        expression.done(CALL_EXPRESSION);
      } else if (at(DOT)) {
        advance(); // DOT

        parseCallExpression();

        expression.done(DOT_QUALIFIED_EXPRESSION);
      } else if (at(SAFE_ACCESS)) {
        advance(); // SAFE_ACCESS

        parseCallExpression();

        expression.done(SAFE_ACCESS_EXPRESSION);
      } else if (atSet(Precedence.POSTFIX.getOperations())) {
        parseOperationReference();
        expression.done(POSTFIX_EXPRESSION);
      } else {
        break;
      }
      expression = expression.precede();
    }
    expression.drop();
  }
  @Override
  public boolean parseStatement(PsiBuilder b, int l) {
    IElementType tokenType = b.getTokenType();

    boolean r = false;
    PsiBuilder.Marker m = b.mark();

    if (tokenType == MASON_BLOCK_OPENER) {
      PsiBuilder.Marker statementMarker = b.mark();
      b.advanceLexer();
      if (PerlParserImpl.expr(b, l, -1)) {
        // parseStatement filter
        if (PerlParserUtil.consumeToken(b, MASON_EXPR_FILTER_PIPE)) {
          while (b.getTokenType() == IDENTIFIER) {
            PsiBuilder.Marker fm = b.mark();
            b.advanceLexer();
            fm.collapse(SUB);
            fm.precede().done(METHOD);

            if (!PerlParserUtil.consumeToken(b, OPERATOR_COMMA)) {
              break;
            }
          }
        }
      }
      if (r = endOrRecover(b, MASON_BLOCK_CLOSER)) {
        statementMarker.done(STATEMENT);
      }
    }
    if (tokenType == MASON_CALL_OPENER) {
      PsiBuilder.Marker statementMarker = b.mark();
      b.advanceLexer();
      PerlParserImpl.expr(b, l, -1);
      if (r = endOrRecover(b, MASON_CALL_CLOSER)) {
        statementMarker.done(MASON_CALL_STATEMENT);
      }
    } else if (tokenType == MASON_CLASS_OPENER) {
      r = parsePerlBlock(b, l, MASON_CLASS_CLOSER);
    } else if (tokenType == MASON_INIT_OPENER) {
      r = parsePerlBlock(b, l, MASON_INIT_CLOSER);
    } else if (tokenType == MASON_PERL_OPENER) {
      r = parsePerlBlock(b, l, MASON_PERL_CLOSER);
    } else if (tokenType == MASON_FLAGS_OPENER) {
      b.advanceLexer();
      PsiBuilder.Marker statementMarker = b.mark();

      while (!b.eof() && b.getTokenType() != MASON_FLAGS_CLOSER) {
        if (!PerlParserImpl.expr(b, l, -1)) {
          break;
        }
      }
      statementMarker.done(MASON_FLAGS_STATEMENT);

      r = endOrRecover(b, MASON_FLAGS_CLOSER);
    } else if (tokenType == MASON_DOC_OPENER) {
      b.advanceLexer();
      PerlParserUtil.consumeToken(b, COMMENT_BLOCK);
      r = endOrRecover(b, MASON_DOC_CLOSER);
    } else if (tokenType == MASON_TEXT_OPENER) {
      b.advanceLexer();
      PsiBuilder.Marker stringMarker = b.mark();
      if (PerlParserUtil.consumeToken(b, STRING_CONTENT)) {
        stringMarker.done(MASON_TEXT_BLOCK);
      } else {
        stringMarker.drop();
      }
      r = endOrRecover(b, MASON_TEXT_CLOSER);
    } else if (tokenType == MASON_METHOD_OPENER) {
      r = parseMasonMethod(b, l, MASON_METHOD_CLOSER, MASON_METHOD_DEFINITION);
    } else if (tokenType == MASON_FILTER_OPENER) {
      r = parseMasonMethod(b, l, MASON_FILTER_CLOSER, MASON_FILTER_DEFINITION);
    } else if (tokenType == MASON_OVERRIDE_OPENER) {
      r = parseMasonMethod(b, l, MASON_OVERRIDE_CLOSER, MASON_OVERRIDE_DEFINITION);
    } else if (SIMPLE_MASON_NAMED_BLOCKS.contains(tokenType)) // simple named blocks
    {
      PsiBuilder.Marker statementMarker = b.mark();
      b.advanceLexer();
      IElementType closeToken = RESERVED_OPENER_TO_CLOSER_MAP.get(tokenType);

      if (PerlParserUtil.convertIdentifier(b, l, MASON_METHOD_MODIFIER_NAME)) {
        if (PerlParserUtil.consumeToken(b, MASON_TAG_CLOSER)) {
          PsiBuilder.Marker blockMarker = b.mark();
          PerlParserImpl.block_content(b, l);
          blockMarker.done(BLOCK);
          blockMarker.setCustomEdgeTokenBinders(
              WhitespacesBinders.GREEDY_LEFT_BINDER, WhitespacesBinders.GREEDY_RIGHT_BINDER);

          if (r = PerlParserUtil.consumeToken(b, closeToken)) {
            statementMarker.done(RESERVED_TO_STATEMENT_MAP.get(tokenType));
            statementMarker = null;
          }
        }
      }

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

      r = r || recoverToGreedy(b, closeToken, "Error");
    }

    if (r) {
      m.drop();
    } else {
      m.rollbackTo();
    }

    return r || super.parseStatement(b, l);
  }
  @Nullable
  private static PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
    IElementType tokenType = builder.getTokenType();

    if (LITERALS.contains(tokenType)) {
      final PsiBuilder.Marker literal = builder.mark();
      builder.advanceLexer();
      literal.done(JavaElementType.LITERAL_EXPRESSION);
      return literal;
    }
    if (tokenType == JavaTokenType.LPARENTH) {
      final PsiBuilder.Marker parenth = builder.mark();
      builder.advanceLexer();

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

      if (!expect(builder, JavaTokenType.RPARENTH)) {
        if (inner != null) {
          error(builder, JavaErrorMessages.message("expected.rparen"));
        }
      }

      parenth.done(JavaElementType.PARENTH_EXPRESSION);
      return parenth;
    }
    if (tokenType == JavaTokenType.LBRACE) {
      return parseArrayInitializer(builder);
    }

    PsiBuilder.Marker annotation = null;
    final PsiBuilder.Marker beforeAnnotation = builder.mark();
    if (tokenType == JavaTokenType.AT) {
      annotation = DeclarationParser.parseAnnotations(builder);
      tokenType = builder.getTokenType();
    }

    if (tokenType == JavaTokenType.IDENTIFIER) {
      final PsiBuilder.Marker refExpr;
      if (annotation != null) {
        final PsiBuilder.Marker refParam = annotation.precede();
        refParam.doneBefore(JavaElementType.REFERENCE_PARAMETER_LIST, annotation);
        refExpr = refParam.precede();
      } else {
        refExpr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }

      builder.advanceLexer();
      refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
      beforeAnnotation.drop();
      return refExpr;
    }

    if (annotation != null) {
      beforeAnnotation.rollbackTo();
      tokenType = builder.getTokenType();
    } else {
      beforeAnnotation.drop();
    }

    PsiBuilder.Marker expr = null;
    if (tokenType == JavaTokenType.LT) {
      expr = builder.mark();

      if (!ReferenceParser.parseReferenceParameterList(builder, false, false)) {
        expr.rollbackTo();
        return null;
      }

      tokenType = builder.getTokenType();
      if (!CONSTRUCTOR_CALL.contains(tokenType)) {
        expr.rollbackTo();
        return null;
      }
    }

    if (CONSTRUCTOR_CALL.contains(tokenType)) {
      if (expr == null) {
        expr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }
      builder.advanceLexer();
      expr.done(
          builder.getTokenType() == JavaTokenType.LPARENTH
              ? JavaElementType.REFERENCE_EXPRESSION
              : tokenType == JavaTokenType.THIS_KEYWORD
                  ? JavaElementType.THIS_EXPRESSION
                  : JavaElementType.SUPER_EXPRESSION);
      return expr;
    }
    if (tokenType == JavaTokenType.NEW_KEYWORD) {
      return parseNew(builder, null);
    }
    if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
      return parseClassObjectAccess(builder);
    }

    return null;
  }
  @NotNull
  private PsiBuilder.Marker parseNew(PsiBuilder builder, @Nullable PsiBuilder.Marker start) {
    PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
    builder.advanceLexer();

    myParser.getReferenceParser().parseReferenceParameterList(builder, false, true);

    PsiBuilder.Marker refOrType;
    PsiBuilder.Marker anno = myParser.getDeclarationParser().parseAnnotations(builder);
    IElementType tokenType = builder.getTokenType();
    if (tokenType == JavaTokenType.IDENTIFIER) {
      if (anno != null) {
        anno.rollbackTo();
      }
      refOrType =
          myParser.getReferenceParser().parseJavaCodeReference(builder, true, true, true, true);
      if (refOrType == null) {
        error(builder, JavaErrorMessages.message("expected.identifier"));
        newExpr.done(JavaElementType.NEW_EXPRESSION);
        return newExpr;
      }
    } else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
      refOrType = null;
      builder.advanceLexer();
    } else {
      error(builder, JavaErrorMessages.message("expected.identifier"));
      newExpr.done(JavaElementType.NEW_EXPRESSION);
      return newExpr;
    }

    if (refOrType != null && builder.getTokenType() == JavaTokenType.LPARENTH) {
      parseArgumentList(builder);
      if (builder.getTokenType() == JavaTokenType.LBRACE) {
        final PsiBuilder.Marker classElement = refOrType.precede();
        myParser.getDeclarationParser().parseClassBodyWithBraces(builder, false, false);
        classElement.done(JavaElementType.ANONYMOUS_CLASS);
      }
      newExpr.done(JavaElementType.NEW_EXPRESSION);
      return newExpr;
    }

    myParser.getDeclarationParser().parseAnnotations(builder);

    if (builder.getTokenType() != JavaTokenType.LBRACKET) {
      error(
          builder,
          refOrType == null
              ? JavaErrorMessages.message("expected.lbracket")
              : JavaErrorMessages.message("expected.lparen.or.lbracket"));
      newExpr.done(JavaElementType.NEW_EXPRESSION);
      return newExpr;
    }

    int bracketCount = 0;
    int dimCount = 0;
    while (true) {
      myParser.getDeclarationParser().parseAnnotations(builder);

      if (builder.getTokenType() != JavaTokenType.LBRACKET) break;
      builder.advanceLexer();

      if (bracketCount == dimCount) {
        final PsiBuilder.Marker dimExpr = parse(builder);
        if (dimExpr != null) {
          dimCount++;
        }
      }
      bracketCount++;

      if (!expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) {
        newExpr.done(JavaElementType.NEW_EXPRESSION);
        return newExpr;
      }
    }

    if (dimCount == 0) {
      if (builder.getTokenType() == JavaTokenType.LBRACE) {
        parseArrayInitializer(builder);
      } else {
        error(builder, JavaErrorMessages.message("expected.array.initializer"));
      }
    }

    newExpr.done(JavaElementType.NEW_EXPRESSION);
    return newExpr;
  }
  @NotNull
  private static PsiBuilder.Marker parseNew(
      final PsiBuilder builder, final PsiBuilder.Marker start) {
    final PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
    builder.advanceLexer();

    final boolean parseDiamonds = areDiamondsSupported(builder);
    ReferenceParser.parseReferenceParameterList(builder, false, parseDiamonds);

    final PsiBuilder.Marker refOrType;
    final boolean parseAnnotations =
        areTypeAnnotationsSupported(builder) && builder.getTokenType() == JavaTokenType.AT;

    final IElementType tokenType = builder.getTokenType();
    if (tokenType == JavaTokenType.IDENTIFIER || parseAnnotations) {
      refOrType =
          ReferenceParser.parseJavaCodeReference(
              builder, true, true, parseAnnotations, true, parseDiamonds);
      if (refOrType == null) {
        error(builder, JavaErrorMessages.message("expected.identifier"));
        newExpr.done(JavaElementType.NEW_EXPRESSION);
        return newExpr;
      }
    } else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
      refOrType = null;
      builder.advanceLexer();
    } else {
      error(builder, JavaErrorMessages.message("expected.identifier"));
      newExpr.done(JavaElementType.NEW_EXPRESSION);
      return newExpr;
    }

    if (refOrType != null && builder.getTokenType() == JavaTokenType.LPARENTH) {
      parseArgumentList(builder);
      if (builder.getTokenType() == JavaTokenType.LBRACE) {
        final PsiBuilder.Marker classElement = refOrType.precede();
        DeclarationParser.parseClassBodyWithBraces(builder, false, false);
        classElement.done(JavaElementType.ANONYMOUS_CLASS);
      }
    } else {
      if (builder.getTokenType() != JavaTokenType.LBRACKET) {
        error(
            builder,
            refOrType == null
                ? JavaErrorMessages.message("expected.lbracket")
                : JavaErrorMessages.message("expected.lparen.or.lbracket"));
        newExpr.done(JavaElementType.NEW_EXPRESSION);
        return newExpr;
      }

      int bracketCount = 0;
      int dimCount = 0;
      while (true) {
        if (builder.getTokenType() != JavaTokenType.LBRACKET) break;
        builder.advanceLexer();

        if (bracketCount == dimCount) {
          final PsiBuilder.Marker dimExpr = parse(builder);
          if (dimExpr != null) {
            dimCount++;
          }
        }
        bracketCount++;

        if (!JavaParserUtil.expectOrError(
            builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) {
          newExpr.done(JavaElementType.NEW_EXPRESSION);
          return newExpr;
        }
      }

      if (dimCount == 0) {
        if (builder.getTokenType() == JavaTokenType.LBRACE) {
          parseArrayInitializer(builder);
        } else {
          error(builder, JavaErrorMessages.message("expected.array.initializer"));
        }
      }
    }

    newExpr.done(JavaElementType.NEW_EXPRESSION);
    return newExpr;
  }
  @Nullable
  private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
    IElementType tokenType = builder.getTokenType();

    if (LITERALS.contains(tokenType)) {
      final PsiBuilder.Marker literal = builder.mark();
      builder.advanceLexer();
      literal.done(JavaElementType.LITERAL_EXPRESSION);
      return literal;
    }

    if (tokenType == JavaTokenType.LBRACE) {
      return parseArrayInitializer(builder);
    }

    if (tokenType == JavaTokenType.NEW_KEYWORD) {
      return parseNew(builder, null);
    }

    if (tokenType == JavaTokenType.LPARENTH) {
      final PsiBuilder.Marker lambda = parseLambdaAfterParenth(builder, null);
      if (lambda != null) {
        return lambda;
      }

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

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

      if (!expect(builder, JavaTokenType.RPARENTH)) {
        if (inner != null) {
          error(builder, JavaErrorMessages.message("expected.rparen"));
        }
      }

      parenth.done(JavaElementType.PARENTH_EXPRESSION);
      return parenth;
    }

    if (TYPE_START.contains(tokenType)) {
      final PsiBuilder.Marker mark = builder.mark();

      final ReferenceParser.TypeInfo typeInfo =
          myParser.getReferenceParser().parseTypeInfo(builder, 0);
      if (typeInfo != null) {
        boolean optionalClassKeyword = typeInfo.isPrimitive || typeInfo.isArray;
        if (optionalClassKeyword || !typeInfo.hasErrors && typeInfo.isParameterized) {
          final PsiBuilder.Marker result =
              continueClassAccessOrMethodReference(builder, mark, optionalClassKeyword);
          if (result != null) {
            return result;
          }
        }
      }

      mark.rollbackTo();
    }

    PsiBuilder.Marker annotation = null;
    if (tokenType == JavaTokenType.AT) {
      annotation = myParser.getDeclarationParser().parseAnnotations(builder);
      tokenType = builder.getTokenType();
    }

    if (tokenType == JavaTokenType.IDENTIFIER) {
      if (builder.lookAhead(1) == JavaTokenType.ARROW) {
        return parseLambdaExpression(builder, false, null);
      }

      final PsiBuilder.Marker refExpr;
      if (annotation != null) {
        final PsiBuilder.Marker refParam = annotation.precede();
        refParam.doneBefore(JavaElementType.REFERENCE_PARAMETER_LIST, annotation);
        refExpr = refParam.precede();
      } else {
        refExpr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }

      builder.advanceLexer();
      refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
      return refExpr;
    }

    if (annotation != null) {
      annotation.rollbackTo();
      tokenType = builder.getTokenType();
    }

    PsiBuilder.Marker expr = null;
    if (tokenType == JavaTokenType.LT) {
      expr = builder.mark();

      if (!myParser.getReferenceParser().parseReferenceParameterList(builder, false, false)) {
        expr.rollbackTo();
        return null;
      }

      tokenType = builder.getTokenType();
      if (!THIS_OR_SUPER.contains(tokenType)) {
        expr.rollbackTo();
        return null;
      }
    }

    if (THIS_OR_SUPER.contains(tokenType)) {
      if (expr == null) {
        expr = builder.mark();
        builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
      }
      builder.advanceLexer();
      expr.done(
          builder.getTokenType() == JavaTokenType.LPARENTH
              ? JavaElementType.REFERENCE_EXPRESSION
              : tokenType == JavaTokenType.THIS_KEYWORD
                  ? JavaElementType.THIS_EXPRESSION
                  : JavaElementType.SUPER_EXPRESSION);
      return expr;
    }

    return null;
  }
  // todo[r.sh] make 'this', 'super' and 'class' reference expressions
  @Nullable
  private PsiBuilder.Marker parsePrimary(
      final PsiBuilder builder, @Nullable final BreakPoint breakPoint, final int breakOffset) {
    PsiBuilder.Marker startMarker = builder.mark();

    PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder);
    if (expr == null) {
      startMarker.drop();
      return null;
    }

    while (true) {
      final IElementType tokenType = builder.getTokenType();
      if (tokenType == JavaTokenType.DOT) {
        final PsiBuilder.Marker dotPos = builder.mark();
        final int dotOffset = builder.getCurrentOffset();
        builder.advanceLexer();

        IElementType dotTokenType = builder.getTokenType();
        if (dotTokenType == JavaTokenType.AT) {
          myParser.getDeclarationParser().parseAnnotations(builder);
          dotTokenType = builder.getTokenType();
        }

        if (dotTokenType == JavaTokenType.CLASS_KEYWORD
            && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
          if (breakPoint == BreakPoint.P1 && builder.getCurrentOffset() == breakOffset) {
            error(builder, JavaErrorMessages.message("expected.identifier"));
            PsiBuilderUtil.drop(startMarker, dotPos);
            return expr;
          }

          final PsiBuilder.Marker copy = startMarker.precede();
          final int offset = builder.getCurrentOffset();
          startMarker.rollbackTo();

          final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
          if (classObjAccess == null || builder.getCurrentOffset() < offset) {
            copy.rollbackTo();
            return parsePrimary(builder, BreakPoint.P1, offset);
          }

          startMarker = copy;
          expr = classObjAccess;
        } else if (dotTokenType == JavaTokenType.NEW_KEYWORD) {
          dotPos.drop();
          expr = parseNew(builder, expr);
        } else if (THIS_OR_SUPER.contains(dotTokenType)
            && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
          if (breakPoint == BreakPoint.P2 && builder.getCurrentOffset() == breakOffset) {
            dotPos.rollbackTo();
            startMarker.drop();
            return expr;
          }

          final PsiBuilder.Marker copy = startMarker.precede();
          final int offset = builder.getCurrentOffset();
          startMarker.rollbackTo();

          final PsiBuilder.Marker ref =
              myParser
                  .getReferenceParser()
                  .parseJavaCodeReference(builder, false, true, false, false);
          if (ref == null
              || builder.getTokenType() != JavaTokenType.DOT
              || builder.getCurrentOffset() != dotOffset) {
            copy.rollbackTo();
            return parsePrimary(builder, BreakPoint.P2, offset);
          }
          builder.advanceLexer();

          if (builder.getTokenType() != dotTokenType) {
            copy.rollbackTo();
            return parsePrimary(builder, BreakPoint.P2, offset);
          }
          builder.advanceLexer();

          startMarker = copy;
          expr = ref.precede();
          expr.done(
              dotTokenType == JavaTokenType.THIS_KEYWORD
                  ? JavaElementType.THIS_EXPRESSION
                  : JavaElementType.SUPER_EXPRESSION);
        } else if (dotTokenType == JavaTokenType.SUPER_KEYWORD) {
          dotPos.drop();
          final PsiBuilder.Marker refExpr = expr.precede();
          builder.advanceLexer();
          refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
          expr = refExpr;
        } else {
          dotPos.drop();
          final PsiBuilder.Marker refExpr = expr.precede();
          myParser.getReferenceParser().parseReferenceParameterList(builder, false, false);

          if (!expectOrError(builder, ID_OR_SUPER, "expected.identifier")) {
            refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
            startMarker.drop();
            return refExpr;
          }

          refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
          expr = refExpr;
        }
      } else if (tokenType == JavaTokenType.LPARENTH) {
        if (exprType(expr) != JavaElementType.REFERENCE_EXPRESSION) {
          if (exprType(expr) == JavaElementType.SUPER_EXPRESSION) {
            if (breakPoint == BreakPoint.P3) {
              startMarker.drop();
              return expr;
            }

            final PsiBuilder.Marker copy = startMarker.precede();
            startMarker.rollbackTo();

            final PsiBuilder.Marker qualifier = parsePrimaryExpressionStart(builder);
            if (qualifier != null) {
              final PsiBuilder.Marker refExpr = qualifier.precede();
              if (builder.getTokenType() == JavaTokenType.DOT) {
                builder.advanceLexer();
                if (builder.getTokenType() == JavaTokenType.SUPER_KEYWORD) {
                  builder.advanceLexer();
                  refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
                  expr = refExpr;
                  startMarker = copy;
                  continue;
                }
              }
            }

            copy.rollbackTo();
            return parsePrimary(builder, BreakPoint.P3, -1);
          } else {
            startMarker.drop();
            return expr;
          }
        }

        final PsiBuilder.Marker callExpr = expr.precede();
        parseArgumentList(builder);
        callExpr.done(JavaElementType.METHOD_CALL_EXPRESSION);
        expr = callExpr;
      } else if (tokenType == JavaTokenType.LBRACKET) {
        if (breakPoint == BreakPoint.P4) {
          startMarker.drop();
          return expr;
        }

        builder.advanceLexer();

        if (builder.getTokenType() == JavaTokenType.RBRACKET
            && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
          final int pos = builder.getCurrentOffset();
          final PsiBuilder.Marker copy = startMarker.precede();
          startMarker.rollbackTo();

          final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
          if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
            copy.rollbackTo();
            return parsePrimary(builder, BreakPoint.P4, -1);
          }

          startMarker = copy;
          expr = classObjAccess;
        } else {
          final PsiBuilder.Marker arrayAccess = expr.precede();

          final PsiBuilder.Marker index = parse(builder);
          if (index == null) {
            error(builder, JavaErrorMessages.message("expected.expression"));
            arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
            startMarker.drop();
            return arrayAccess;
          }

          if (builder.getTokenType() != JavaTokenType.RBRACKET) {
            error(builder, JavaErrorMessages.message("expected.rbracket"));
            arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
            startMarker.drop();
            return arrayAccess;
          }
          builder.advanceLexer();

          arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
          expr = arrayAccess;
        }
      } else if (tokenType == JavaTokenType.DOUBLE_COLON) {
        return parseMethodReference(builder, startMarker);
      } else {
        startMarker.drop();
        return expr;
      }
    }
  }
  private void afterConsume(PsiBuilder builder, IElementType type) {
    if (type.equals(SS_VAR) && markingVar) {
      varMarker.done(NAMED_VAR);
      markingVar = false;
      identifierMarker = null;
    }

    if (markingTheme && type.equals(SS_THEME_VAR)) {
      themeMarker.done(SS_THEME_DIR);
    }

    if (type.equals(SS_STRING) && markingTheme) {
      PsiBuilder.Marker fullTheme = themeMarker.precede();
      fullTheme.done(SS_THEME_FILE_PATH);
      markingTheme = false;
      themeMarker = null;
    }

    if (type.equals(SS_IDENTIFIER)) {
      if (identifierMarker == null) identifierMarker = varMarker.precede();
      else identifierMarker = identifierMarker.precede();
      identifierMarker.done(SS_FIELD_REFERENCE);
    }

    if (type.equals(SS_COMMENT_END)) {
      commentMarker.done(SS_COMMENT_STATEMENT);
      markingComment = false;
    }

    if (markingBlock && type.equals(SS_BLOCK_END)) {
      blockMarker.done(blockType);
      markingBlock = false;
      if (BLOCK_STATEMENTS.contains(blockType)) {
        blockStack.push(Pair.create(blockMarker, blockTokenText));
        statementsStack.push(builder.mark());
      } else if (blockType.equals(SS_ELSE_IF_STATEMENT) || blockType.equals(SS_ELSE_STATEMENT)) {
        if (!statementsStack.isEmpty()) {
          statementsStack.pop().doneBefore(SS_STATEMENTS, blockMarker);
          statementsStack.push(builder.mark());
        }
      } else if (blockType.equals(SS_BLOCK_END_STATEMENT)) {
        PsiBuilder.Marker statementMarker = null;
        if (!statementsStack.isEmpty()) {
          statementMarker = statementsStack.pop();
          statementMarker.doneBefore(SS_STATEMENTS, blockMarker);
        }
        if (!blockStack.isEmpty()) {
          Pair<PsiBuilder.Marker, String> blockLevel = blockStack.peek();
          String endString = "end_" + blockLevel.getSecond();
          if (endString.equals(blockTokenText)) {
            PsiBuilder.Marker blockMarker = blockLevel.getFirst().precede();
            blockMarker.done(SS_BLOCK_STATEMENT);
            blockStack.pop();
          } else {
            blockStack.pop();
            if (statementMarker != null) statementMarker.drop();
          }
        }
      }
    }
    if (markingBlock && !blockStartTokens.contains(type)) {
      blockMarker.drop();
      markingBlock = false;
    }
  }
示例#25
0
  // The extraRecoverySet is needed for the foo(bar<x, 1, y>(z)) case, to tell whether we should
  // stop
  // on expression-indicating symbols or not
  private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) {
    // Disabling token merge is required for cases like
    //    Int?.(Foo) -> Bar
    // we don't support this case now
    //        myBuilder.disableJoiningComplexTokens();
    PsiBuilder.Marker typeRefMarker = mark();
    parseAnnotations(false);

    if (at(IDENTIFIER) || at(PACKAGE_KEYWORD)) {
      parseUserType();
    } else if (at(HASH)) {
      parseTupleType();
    } else if (at(LPAR)) {
      PsiBuilder.Marker functionOrParenthesizedType = mark();

      // This may be a function parameter list or just a prenthesized type
      advance(); // LPAR
      parseTypeRefContents(TokenSet.EMPTY)
          .drop(); // parenthesized types, no reference element around it is needed

      if (at(RPAR)) {
        advance(); // RPAR
        if (at(ARROW)) {
          // It's a function type with one parameter specified
          //    (A) -> B
          functionOrParenthesizedType.rollbackTo();
          parseFunctionType();
        } else {
          // It's a parenthesized type
          //    (A)
          functionOrParenthesizedType.drop();
        }
      } else {
        // This must be a function type
        //   (A, B) -> C
        // or
        //   (a : A) -> C
        functionOrParenthesizedType.rollbackTo();
        parseFunctionType();
      }

    } else if (at(CAPITALIZED_THIS_KEYWORD)) {
      parseSelfType();
    } else {
      errorWithRecovery(
          "Type expected",
          TokenSet.orSet(
              TOPLEVEL_OBJECT_FIRST,
              TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON),
              extraRecoverySet));
    }

    while (at(QUEST)) {
      PsiBuilder.Marker precede = typeRefMarker.precede();

      advance(); // QUEST
      typeRefMarker.done(NULLABLE_TYPE);

      typeRefMarker = precede;
    }

    if (at(DOT)) {
      // This is a receiver for a function type
      //  A.(B) -> C
      //   ^

      PsiBuilder.Marker functionType = typeRefMarker.precede();
      PsiBuilder.Marker receiverType = typeRefMarker.precede();
      typeRefMarker.done(TYPE_REFERENCE);
      receiverType.done(FUNCTION_TYPE_RECEIVER);

      advance(); // DOT

      if (at(LPAR)) {
        parseFunctionTypeContents().drop();
      } else {
        error("Expecting function type");
      }
      typeRefMarker = functionType.precede();

      functionType.done(FUNCTION_TYPE);
    }
    //        myBuilder.restoreJoiningComplexTokensState();
    return typeRefMarker;
  }
  public boolean parseMemberExpression(boolean isTargetExpression) {
    // in sequence a.b.... .c all members but last are always references, and the last may be
    // target.
    boolean recastFirstIdentifier = false;
    boolean recastQualifier = false;
    do {
      boolean firstIdentifierIsTarget = isTargetExpression && !recastFirstIdentifier;
      PsiBuilder.Marker expr = myBuilder.mark();
      if (!parsePrimaryExpression(firstIdentifierIsTarget)) {
        expr.drop();
        return false;
      }

      while (true) {
        final IElementType tokenType = myBuilder.getTokenType();
        if (tokenType == PyTokenTypes.DOT) {
          if (firstIdentifierIsTarget) {
            recastFirstIdentifier = true;
            expr.rollbackTo();
            break;
          }
          myBuilder.advanceLexer();
          checkMatches(PyTokenTypes.IDENTIFIER, message("PARSE.expected.name"));
          if (isTargetExpression
              && !recastQualifier
              && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) {
            expr.done(PyElementTypes.TARGET_EXPRESSION);
          } else {
            expr.done(getReferenceType());
          }
          expr = expr.precede();
        } else if (tokenType == PyTokenTypes.LPAR) {
          parseArgumentList();
          expr.done(PyElementTypes.CALL_EXPRESSION);
          expr = expr.precede();
        } else if (tokenType == PyTokenTypes.LBRACKET) {
          myBuilder.advanceLexer();
          PsiBuilder.Marker sliceOrTupleStart = myBuilder.mark();
          PsiBuilder.Marker sliceItemStart = myBuilder.mark();
          if (atToken(PyTokenTypes.COLON)) {
            sliceOrTupleStart.drop();
            PsiBuilder.Marker sliceMarker = myBuilder.mark();
            sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION);
            parseSliceEnd(expr, sliceItemStart);
          } else {
            boolean hadExpression = parseSingleExpression(false);
            if (atToken(PyTokenTypes.COLON)) {
              sliceOrTupleStart.drop();
              parseSliceEnd(expr, sliceItemStart);
            } else if (atToken(PyTokenTypes.COMMA)) {
              sliceItemStart.done(PyElementTypes.SLICE_ITEM);
              if (!parseSliceListTail(expr, sliceOrTupleStart)) {
                sliceOrTupleStart.rollbackTo();
                if (!parseTupleExpression(false, false, false)) {
                  myBuilder.error("tuple expression expected");
                }
                checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket"));
                expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION);
              }
            } else {
              if (!hadExpression) {
                myBuilder.error("expression expected");
              }
              sliceOrTupleStart.drop();
              sliceItemStart.drop();
              checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket"));
              expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION);
            }
          }
          if (isTargetExpression && !recastQualifier) {
            recastFirstIdentifier = true; // subscription is always a reference
            recastQualifier = true; // recast non-first qualifiers too
            expr.rollbackTo();
            break;
          }
          expr = expr.precede();
        } else {
          expr.drop();
          break;
        }
        recastFirstIdentifier =
            false; // it is true only after a break; normal flow always unsets it.
        // recastQualifier is untouched, it remembers whether qualifiers were already recast
      }
    } while (recastFirstIdentifier);

    return true;
  }