/* * 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); }
public static boolean parse( PsiBuilder builder, boolean isInClass, boolean isInAnnotation, GroovyParser parser) { PsiBuilder.Marker declMarker = builder.mark(); // allows error messages boolean modifiersParsed = Modifiers.parse(builder, parser); final boolean methodStart = mLT == builder.getTokenType(); final IElementType type = parseAfterModifiers( builder, isInClass, isInAnnotation, parser, declMarker, modifiersParsed); if (type == WRONGWAY) { if (modifiersParsed && methodStart) { declMarker.error(GroovyBundle.message("method.definitions.expected")); return false; } declMarker.rollbackTo(); if (modifiersParsed) { builder.error(GroovyBundle.message("variable.definitions.expected")); } return false; } if (type != null) { declMarker.done(type); } else { declMarker.drop(); } return true; }
private void handleUselessRename() { if (at(AS_KEYWORD)) { PsiBuilder.Marker as = mark(); advance(); // AS_KEYWORD consumeIf(IDENTIFIER); as.error("Cannot rename a all imported items to one identifier"); } }
protected static boolean recoverTo(PsiBuilder b, IElementType toElement, String errorMessage) { // recover bad code PsiBuilder.Marker errorMarker = b.mark(); while (!b.eof() && b.getTokenType() != toElement) { b.advanceLexer(); ; } errorMarker.error(errorMessage); return b.eof(); }
private void eofCleanup() { if (markingBlock) { blockMarker.error(message("ss.parsing.unclosed.statement", blockTokenText)); markingBlock = false; } if (markingComment) { commentMarker.drop(); } while (!statementsStack.isEmpty()) { statementsStack.pop().drop(); } }
@Override public boolean parseTerm(PsiBuilder b, int l) { if (b.getTokenType() == MASON_SELF_POINTER) { PsiBuilder.Marker m = b.mark(); b.advanceLexer(); if (nested_call(b, l)) { m.done(MASON_SIMPLE_DEREF_EXPR); } else { m.error("Error parsing filter expression"); } return true; } return super.parseTerm(b, l); }
private static boolean reportError( PsiBuilder builder, ErrorState state, Frame frame, IElementType elementType, boolean force, boolean advance) { String expectedText = state.getExpectedText(builder); boolean notEmpty = StringUtil.isNotEmpty(expectedText); if (force || notEmpty || advance) { String gotText = builder.eof() ? "unexpected end of file" : notEmpty ? "got '" + builder.getTokenText() + "'" : "'" + builder.getTokenText() + "' unexpected"; String message = expectedText + gotText; if (advance) { PsiBuilder.Marker mark = builder.mark(); builder.advanceLexer(); mark.error(message); } else if (!force) { PsiBuilder.Marker extensionMarker = null; IElementType extensionTokenType = null; PsiBuilderImpl.ProductionMarker latestDoneMarker = elementType == null ? null : (PsiBuilderImpl.ProductionMarker) builder.getLatestDoneMarker(); if (latestDoneMarker != null && frame.position >= latestDoneMarker.getStartIndex() && frame.position <= latestDoneMarker.getEndIndex()) { extensionMarker = ((PsiBuilder.Marker) latestDoneMarker).precede(); extensionTokenType = latestDoneMarker.getTokenType(); ((PsiBuilder.Marker) latestDoneMarker).drop(); } builder.error(message); if (extensionMarker != null) extensionMarker.done(extensionTokenType); } else { builder.error(message); } builder.eof(); // skip whitespaces frame.errorReportedAt = builder.rawTokenIndex(); return true; } return false; }
private boolean parseAwaitExpression(boolean isTargetExpression) { if (atToken(PyTokenTypes.AWAIT_KEYWORD)) { final PsiBuilder.Marker expr = myBuilder.mark(); myBuilder.advanceLexer(); if (!parseMemberExpression(isTargetExpression)) { myBuilder.error(message("PARSE.expected.expression")); expr.done(PyElementTypes.PREFIX_EXPRESSION); } else { if (isTargetExpression) { expr.error("can't assign to await expression"); } else { expr.done(PyElementTypes.PREFIX_EXPRESSION); } } return true; } else { return parseMemberExpression(isTargetExpression); } }
/* * tupleType * : "#" "(" type{","}? ")" * : "#" "(" parameter{","} ")" // tuple with named entries, the names do not affect assignment compatibility * ; */ @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be // removed some time (in Kotlin 1.0?) private void parseTupleType() { assert _at(HASH); PsiBuilder.Marker tuple = mark(); myBuilder.disableNewlines(); advance(); // HASH consumeIf(LPAR); if (!at(RPAR)) { while (true) { if (at(COLON)) { errorAndAdvance("Expecting a name for tuple entry"); } if (at(IDENTIFIER) && lookahead(1) == COLON) { advance(); // IDENTIFIER advance(); // COLON parseTypeRef(); } else if (TYPE_REF_FIRST.contains(tt())) { parseTypeRef(); } else { error("Type expected"); break; } if (!at(COMMA)) break; advance(); // COMMA } } consumeIf(RPAR); myBuilder.restoreNewlinesState(); tuple.error("Tuples are not supported. Use data classes instead."); }
/* * callableReference * : (userType "?"*)? "::" SimpleName typeArguments? * ; */ 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(); if (at(LT)) { PsiBuilder.Marker typeArgumentList = mark(); if (myJetParsing.tryParseTypeArgumentList(TYPE_ARGUMENT_LIST_STOPPERS)) { typeArgumentList.error("Type arguments are not allowed"); } else { typeArgumentList.rollbackTo(); } } expression.done(CALLABLE_REFERENCE_EXPRESSION); } return true; }
/* * tupleLiteral * : "#" "(" (((SimpleName "=")? expression){","})? ")" * ; */ @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be // removed some time (in Kotlin 1.0?) private void parseTupleExpression() { assert _at(HASH); PsiBuilder.Marker mark = mark(); advance(); // HASH advance(); // LPAR myBuilder.disableNewlines(); if (!at(RPAR)) { while (true) { while (at(COMMA)) { advance(); } if (at(IDENTIFIER) && lookahead(1) == EQ) { advance(); // IDENTIFIER advance(); // EQ parseExpression(); } else { parseExpression(); } if (!at(COMMA)) break; advance(); // COMMA if (at(RPAR)) { break; } } } consumeIf(RPAR); myBuilder.restoreNewlinesState(); mark.error("Tuples are not supported. Use data classes instead."); }
protected void errorUntilEol(String message) { PsiBuilder.Marker errorMarker = mark(); advanceUntilEol(); errorMarker.error(message); }
protected void errorUntil(TokenSet tokenSet, String message) { PsiBuilder.Marker errorMarker = mark(); advanceUntil(tokenSet); errorMarker.error(message); }
public static boolean exitErrorRecordingSection( PsiBuilder builder_, int level, boolean result, boolean pinned, @NotNull String sectionType, @Nullable Parser eatMore) { ErrorState state = ErrorState.get(builder_); Frame frame = state.levelCheck.pollLast(); int initialOffset = builder_.getCurrentOffset(); if (frame == null || level != frame.level || !sectionType.equals(frame.section)) { LOG.error( "Unbalanced error section: got " + new Frame().init(initialOffset, level, sectionType, "", 0) + ", expected " + frame); if (frame != null) state.FRAMES.recycle(frame); return result; } if (sectionType == _SECTION_AND_ || sectionType == _SECTION_NOT_) { state.predicateCount--; if (sectionType == _SECTION_NOT_) state.predicateSign = !state.predicateSign; state.FRAMES.recycle(frame); return result; } if (!result && !pinned && initialOffset == frame.offset && state.lastExpectedVariantOffset == frame.offset && frame.name != null && state.variants.size() - frame.variantCount > 1) { state.clearVariants(true, frame.variantCount); addVariantInner(state, initialOffset, frame.name); } if (sectionType == _SECTION_RECOVER_ && !state.suppressErrors && eatMore != null) { state.suppressErrors = true; final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1); final int lastErrorPos = getLastVariantOffset(state, initialOffset); boolean eatMoreFlag = eatMoreFlagOnce || frame.offset == initialOffset && lastErrorPos > frame.offset; final LighterASTNode latestDoneMarker = (pinned || result) && (state.altMode || lastErrorPos > initialOffset) && eatMoreFlagOnce ? builder_.getLatestDoneMarker() : null; PsiBuilder.Marker extensionMarker = null; IElementType extensionTokenType = null; if (latestDoneMarker instanceof PsiBuilder.Marker) { extensionMarker = ((PsiBuilder.Marker) latestDoneMarker).precede(); extensionTokenType = latestDoneMarker.getTokenType(); ((PsiBuilder.Marker) latestDoneMarker).drop(); } // advance to the last error pos // skip tokens until lastErrorPos. parseAsTree might look better here... int parenCount = 0; while (eatMoreFlag && builder_.getCurrentOffset() < lastErrorPos) { if (state.braces != null) { if (builder_.getTokenType() == state.braces[0].getLeftBraceType()) parenCount++; else if (builder_.getTokenType() == state.braces[0].getRightBraceType()) parenCount--; } builder_.advanceLexer(); eatMoreFlag = parenCount != 0 || eatMore.parse(builder_, frame.level + 1); } boolean errorReported = frame.errorReportedAt == initialOffset; if (errorReported) { if (eatMoreFlag) { builder_.advanceLexer(); parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } } else if (eatMoreFlag) { String tokenText = builder_.getTokenText(); String expectedText = state.getExpectedText(builder_); PsiBuilder.Marker mark = builder_.mark(); builder_.advanceLexer(); final String gotText = !expectedText.isEmpty() ? "got '" + tokenText + "'" : "'" + tokenText + "' unexpected"; mark.error(expectedText + gotText); parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); errorReported = true; } else if (eatMoreFlagOnce || (!result && frame.offset != builder_.getCurrentOffset())) { reportError(state, builder_, true); errorReported = true; } if (extensionMarker != null) { extensionMarker.done(extensionTokenType); } state.suppressErrors = false; if (errorReported || result) { state.clearVariants(true, 0); state.clearVariants(false, 0); state.lastExpectedVariantOffset = -1; } if (!result && eatMoreFlagOnce && frame.offset != builder_.getCurrentOffset()) result = true; } else if (!result && pinned && frame.errorReportedAt < 0) { // do not report if there're errors after current offset if (getLastVariantOffset(state, initialOffset) == initialOffset) { // do not force, inner recoverRoot might have skipped some tokens if (reportError(state, builder_, false)) { frame.errorReportedAt = initialOffset; } } } // propagate errorReportedAt up the stack to avoid duplicate reporting Frame prevFrame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast(); if (prevFrame != null && prevFrame.errorReportedAt < frame.errorReportedAt) prevFrame.errorReportedAt = frame.errorReportedAt; state.FRAMES.recycle(frame); return result; }