/* * declaration * : function * : property * : extension * : class * : typeAlias * : object * ; */ private IElementType parseLocalDeclarationRest(boolean isEnum) { IElementType keywordToken = tt(); IElementType declType = null; if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) { declType = myJetParsing.parseClass(isEnum); } else if (keywordToken == FUN_KEYWORD) { declType = myJetParsing.parseFunction(); } else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) { declType = myJetParsing.parseProperty(true); } else if (keywordToken == TYPE_ALIAS_KEYWORD) { declType = myJetParsing.parseTypeAlias(); } else if (keywordToken == OBJECT_KEYWORD) { // Object expression may appear at the statement position: should parse it // as expression instead of object declaration // sample: // { // object : Thread() { // } // } IElementType lookahead = lookahead(1); if (lookahead == COLON || lookahead == LBRACE) { return null; } myJetParsing.parseObject(NameParsingMode.REQUIRED, true); declType = OBJECT_DECLARATION; } return declType; }
/* * callableReference * : (userType "?"*)? "::" SimpleName * ; */ private boolean parseDoubleColonExpression() { PsiBuilder.Marker expression = mark(); if (!at(COLONCOLON)) { PsiBuilder.Marker typeReference = mark(); myJetParsing.parseUserType(); typeReference = myJetParsing.parseNullableTypeSuffix(typeReference); typeReference.done(TYPE_REFERENCE); if (!at(COLONCOLON)) { expression.rollbackTo(); return false; } } advance(); // COLONCOLON if (at(CLASS_KEYWORD)) { advance(); // CLASS_KEYWORD expression.done(CLASS_LITERAL_EXPRESSION); } else { parseSimpleNameExpression(); expression.done(CALLABLE_REFERENCE_EXPRESSION); } return true; }
/* * try * : "try" block catchBlock* finallyBlock? * ; * catchBlock * : "catch" "(" annotations SimpleName ":" userType ")" block * ; * * finallyBlock * : "finally" block * ; */ private void parseTry() { assert _at(TRY_KEYWORD); PsiBuilder.Marker tryExpression = mark(); advance(); // TRY_KEYWORD myJetParsing.parseBlock(); boolean catchOrFinally = false; while (at(CATCH_KEYWORD)) { catchOrFinally = true; PsiBuilder.Marker catchBlock = mark(); advance(); // CATCH_KEYWORD TokenSet recoverySet = TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD); if (atSet(recoverySet)) { error("Expecting exception variable declaration"); } else { PsiBuilder.Marker parameters = mark(); expect(LPAR, "Expecting '('", recoverySet); if (!atSet(recoverySet)) { myJetParsing.parseValueParameter(/*typeRequired = */ true); expect(RPAR, "Expecting ')'", recoverySet); } else { error("Expecting exception variable declaration"); } parameters.done(VALUE_PARAMETER_LIST); } if (at(LBRACE)) { myJetParsing.parseBlock(); } else { error("Expecting a block: { ... }"); } catchBlock.done(CATCH); } if (at(FINALLY_KEYWORD)) { catchOrFinally = true; PsiBuilder.Marker finallyBlock = mark(); advance(); // FINALLY_KEYWORD myJetParsing.parseBlock(); finallyBlock.done(FINALLY); } if (!catchOrFinally) { error("Expecting 'catch' or 'finally'"); } tryExpression.done(TRY); }
/* * whenCondition * : expression * : ("in" | "!in") expression * : ("is" | "!is") isRHS * ; */ private void parseWhenCondition() { PsiBuilder.Marker condition = mark(); myBuilder.disableNewlines(); if (at(IN_KEYWORD) || at(NOT_IN)) { PsiBuilder.Marker mark = mark(); advance(); // IN_KEYWORD or NOT_IN mark.done(OPERATION_REFERENCE); if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { error("Expecting an element"); } else { parseExpression(); } condition.done(WHEN_CONDITION_IN_RANGE); } else if (at(IS_KEYWORD) || at(NOT_IS)) { advance(); // IS_KEYWORD or NOT_IS if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { error("Expecting a type"); } else { myJetParsing.parseTypeRef(); } condition.done(WHEN_CONDITION_IS_PATTERN); } else { if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW)) { error("Expecting an expression, is-condition or in-condition"); } else { parseExpression(); } condition.done(WHEN_CONDITION_EXPRESSION); } myBuilder.restoreNewlinesState(); }
/* * operation? prefixExpression */ private void parsePrefixExpression() { // System.out.println("pre at " + myBuilder.getTokenText()); if (at(LBRACKET)) { if (!parseLocalDeclaration()) { PsiBuilder.Marker expression = mark(); myJetParsing.parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); parsePrefixExpression(); expression.done(ANNOTATED_EXPRESSION); } } else { myBuilder.disableJoiningComplexTokens(); if (at(LABEL_IDENTIFIER)) { myBuilder.restoreJoiningComplexTokensState(); parseLabeledExpression(); } else if (atSet(Precedence.PREFIX.getOperations())) { PsiBuilder.Marker expression = mark(); parseOperationReference(); myBuilder.restoreJoiningComplexTokensState(); parsePrefixExpression(); expression.done(PREFIX_EXPRESSION); } else { myBuilder.restoreJoiningComplexTokensState(); parsePostfixExpression(); } } }
/* * "this" ("<" type ">")? label? */ private void parseSuperExpression() { assert _at(SUPER_KEYWORD); PsiBuilder.Marker mark = mark(); PsiBuilder.Marker superReference = mark(); advance(); // SUPER_KEYWORD superReference.done(REFERENCE_EXPRESSION); if (at(LT)) { // This may be "super < foo" or "super<foo>", thus the backtracking PsiBuilder.Marker supertype = mark(); myBuilder.disableNewlines(); advance(); // LT myJetParsing.parseTypeRef(); if (at(GT)) { advance(); // GT supertype.drop(); } else { supertype.rollbackTo(); } myBuilder.restoreNewlinesState(); } parseLabelOnTheSameLine(); mark.done(SUPER_EXPRESSION); }
/* * SimpleName{,} */ private void parseFunctionLiteralShorthandParameterList() { PsiBuilder.Marker parameterList = mark(); while (!eof()) { PsiBuilder.Marker parameter = mark(); // int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new // At(IDENTIFIER), new AtOffset(doubleArrowPos))); // createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, // false); expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW)); parameter.done(VALUE_PARAMETER); if (at(COLON)) { PsiBuilder.Marker errorMarker = mark(); advance(); // COLON myJetParsing.parseTypeRef(); errorMarker.error( "To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType -> ...}"); } else if (at(ARROW)) { break; } else if (at(COMMA)) { advance(); // COMMA } else { error("Expecting '->' or ','"); break; } } parameterList.done(VALUE_PARAMETER_LIST); }
/* * "object" (":" delegationSpecifier{","})? classBody // Cannot make class body optional: foo(object : F, A) */ public void parseObjectLiteral() { PsiBuilder.Marker literal = mark(); PsiBuilder.Marker declaration = mark(); myJetParsing.parseObject( NameParsingMode.PROHIBITED, false); // Body is not optional because of foo(object : A, B) declaration.done(OBJECT_DECLARATION); literal.done(OBJECT_LITERAL); }
/* * for * : "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression * ; * * TODO: empty loop body (at the end of the block)? */ private void parseFor() { assert _at(FOR_KEYWORD); PsiBuilder.Marker loop = mark(); advance(); // FOR_KEYWORD if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) { myBuilder.disableNewlines(); if (!at(RPAR)) { PsiBuilder.Marker parameter = mark(); if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD if (at(LPAR)) { myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); parameter.done(MULTI_VARIABLE_DECLARATION); } else { expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD)); if (at(COLON)) { advance(); // COLON myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD)); } parameter.done(VALUE_PARAMETER); } if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) { PsiBuilder.Marker range = mark(); parseExpression(); range.done(LOOP_RANGE); } } else { error("Expecting a variable name"); } expectNoAdvance(RPAR, "Expecting ')'"); myBuilder.restoreNewlinesState(); } parseControlStructureBody(); loop.done(FOR); }
/* * (":" type)? */ private void parseOptionalFunctionLiteralType() { if (at(COLON)) { advance(); // COLON if (at(ARROW)) { error("Expecting a type"); } else { myJetParsing.parseTypeRef(); } } }
/* * when * : "when" ("(" (modifiers "val" SimpleName "=")? element ")")? "{" * whenEntry* * "}" * ; */ private void parseWhen() { assert _at(WHEN_KEYWORD); PsiBuilder.Marker when = mark(); advance(); // WHEN_KEYWORD // Parse condition myBuilder.disableNewlines(); if (at(LPAR)) { advanceAt(LPAR); int valPos = matchTokenStreamPredicate( new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ))); if (valPos >= 0) { PsiBuilder.Marker property = mark(); myJetParsing.parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ALLOW_SHORTS); myJetParsing.parseProperty(true); property.done(PROPERTY); } else { parseExpression(); } expect(RPAR, "Expecting ')'"); } myBuilder.restoreNewlinesState(); // Parse when block myBuilder.enableNewlines(); if (expect(LBRACE, "Expecting '{'")) { while (!eof() && !at(RBRACE)) { parseWhenEntry(); } expect(RBRACE, "Expecting '}'"); } myBuilder.restoreNewlinesState(); when.done(WHEN); }
/** * "(" (modifiers SimpleName (":" type)?){","} ")" * * @return true if at least one comma was found */ private boolean parseFunctionLiteralParameterList() { PsiBuilder.Marker list = mark(); expect(LPAR, "Expecting a parameter list in parentheses (...)", TokenSet.create(ARROW, COLON)); boolean hasComma = false; myBuilder.disableNewlines(); if (!at(RPAR)) { while (true) { if (at(COMMA)) errorAndAdvance("Expecting a parameter declaration"); PsiBuilder.Marker parameter = mark(); int parameterNamePos = matchTokenStreamPredicate( new LastBefore( new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW, RBRACE, LBRACE))); createTruncatedBuilder(parameterNamePos) .parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); expect(IDENTIFIER, "Expecting parameter declaration"); if (at(COLON)) { advance(); // COLON myJetParsing.parseTypeRef(); } parameter.done(VALUE_PARAMETER); if (!at(COMMA)) break; advance(); // COMMA hasComma = true; if (at(RPAR)) { error("Expecting a parameter declaration"); break; } } } myBuilder.restoreNewlinesState(); expect(RPAR, "Expecting ')'", TokenSet.create(ARROW, COLON)); list.done(VALUE_PARAMETER_LIST); return hasComma; }
/* * modifiers declarationRest */ private boolean parseLocalDeclaration() { PsiBuilder.Marker decl = mark(); JetParsing.ModifierDetector detector = new JetParsing.ModifierDetector(); myJetParsing.parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); IElementType declType = parseLocalDeclarationRest(detector.isEnumDetected()); if (declType != null) { // we do not attach preceding comments (non-doc) to local variables because they are likely // commenting a few statements below closeDeclarationWithCommentBinders( decl, declType, declType != JetNodeTypes.PROPERTY && declType != JetNodeTypes.MULTI_VARIABLE_DECLARATION); return true; } else { decl.rollbackTo(); return false; } }
/* * callSuffix * : typeArguments? valueArguments (getEntryPoint? functionLiteral*) * : typeArguments (getEntryPoint? functionLiteral*) * ; */ private boolean parseCallSuffix() { if (parseCallWithClosure()) { parseCallWithClosure(); } else if (at(LPAR)) { parseValueArgumentList(); parseCallWithClosure(); } else if (at(LT)) { PsiBuilder.Marker typeArgumentList = mark(); if (myJetParsing.tryParseTypeArgumentList(TYPE_ARGUMENT_LIST_STOPPERS)) { typeArgumentList.done(TYPE_ARGUMENT_LIST); if (!myBuilder.newlineBeforeCurrentToken() && at(LPAR)) parseValueArgumentList(); parseCallWithClosure(); } else { typeArgumentList.rollbackTo(); return false; } } else { return false; } return true; }
@Override protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) { return myJetParsing.create(builder); }