@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; }
/* * 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; }
/* * 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(); }
/* * 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; }
/* * 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; } }
// 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; }