public String getExpectedText(PsiBuilder builder) { int position = builder.rawTokenIndex(); StringBuilder sb = new StringBuilder(); if (addExpected(sb, position, true)) { sb.append(" expected, "); } return sb.toString(); }
private static void addVariant(PsiBuilder builder, ErrorState state, Object o) { builder.eof(); // skip whitespaces addVariantInner(state, builder.rawTokenIndex(), o); CompletionState completionState = state.completionState; if (completionState != null && state.predicateSign) { addCompletionVariant(builder, completionState, o); } }
public static void report_error_(PsiBuilder builder, ErrorState state, boolean advance) { Frame frame = state.frameStack.isEmpty() ? null : state.frameStack.getLast(); if (frame == null) { LOG.error("unbalanced enter/exit section call: got null"); return; } int position = builder.rawTokenIndex(); if (frame.errorReportedAt < position && getLastVariantPos(state, position + 1) <= position) { reportError(builder, state, frame, null, true, advance); } }
public Frame init( PsiBuilder builder, ErrorState state, int level_, int modifiers_, String name_) { offset = builder.getCurrentOffset(); position = builder.rawTokenIndex(); level = level_; modifiers = modifiers_; name = name_; variantCount = state.variants.size(); errorReportedAt = -1; Frame prev = state.frameStack.peekLast(); errorReportedAtPrev = prev == null ? -1 : prev.errorReportedAt; leftMarker = null; return this; }
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; }
public static boolean nextTokenIs(PsiBuilder builder, String frameName, IElementType... tokens) { ErrorState state = ErrorState.get(builder); if (state.completionState != null) return true; boolean track = !state.suppressErrors && state.predicateCount < 2 && state.predicateSign; if (!track) return nextTokenIsFast(builder, tokens); IElementType tokenType = builder.getTokenType(); if (StringUtil.isNotEmpty(frameName)) { addVariantInner(state, builder.rawTokenIndex(), frameName); } else { for (IElementType token : tokens) { addVariant(builder, state, token); } } if (tokenType == null) return false; for (IElementType token : tokens) { if (tokenType == token) return true; } return false; }
public Frame init( PsiBuilder builder, ErrorState state, int level_, int modifiers_, IElementType elementType_, String name_) { parentFrame = state.currentFrame; elementType = elementType_; offset = builder.getCurrentOffset(); position = builder.rawTokenIndex(); level = level_; modifiers = modifiers_; name = name_; variantCount = state.variants.size(); errorReportedAt = -1; leftMarker = null; return this; }
public static int current_position_(PsiBuilder builder) { return builder.rawTokenIndex(); }
private static void exit_section_impl_( ErrorState state, Frame frame, PsiBuilder builder, @Nullable IElementType elementType, boolean result, boolean pinned, @Nullable Parser eatMore) { int initialPos = builder.rawTokenIndex(); boolean willFail = !result && !pinned; if (willFail && initialPos == frame.position && state.lastExpectedVariantPos == frame.position && frame.name != null && state.variants.size() - frame.variantCount > 1) { state.clearVariants(true, frame.variantCount); addVariantInner(state, initialPos, frame.name); } int lastErrorPos = getLastVariantPos(state, initialPos); if (!state.suppressErrors && eatMore != null) { state.suppressErrors = true; final boolean eatMoreFlagOnce = !builder.eof() && eatMore.parse(builder, frame.level + 1); boolean eatMoreFlag = eatMoreFlagOnce || !result && frame.position == initialPos && lastErrorPos > frame.position; PsiBuilderImpl.ProductionMarker latestDoneMarker = (pinned || result) && (state.altMode || elementType != null) && eatMoreFlagOnce ? (PsiBuilderImpl.ProductionMarker) builder.getLatestDoneMarker() : null; PsiBuilder.Marker extensionMarker = null; IElementType extensionTokenType = null; // whitespace prefix makes the very first frame offset bigger than marker start offset which // is always 0 if (latestDoneMarker != null && frame.position >= latestDoneMarker.getStartIndex() && frame.position <= latestDoneMarker.getEndIndex()) { 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 || parenCount > 0) && builder.rawTokenIndex() < 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 = eatMore.parse(builder, frame.level + 1); } boolean errorReported = frame.errorReportedAt == initialPos || !result && frame.errorReportedAt >= frame.position; if (errorReported) { if (eatMoreFlag) { builder.advanceLexer(); parseAsTree(state, builder, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } } else if (eatMoreFlag) { errorReported = reportError(builder, state, frame, null, true, true); parseAsTree(state, builder, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } else if (eatMoreFlagOnce || (!result && frame.position != builder.rawTokenIndex()) || frame.errorReportedAt > initialPos) { errorReported = reportError(builder, state, frame, null, true, false); } if (extensionMarker != null) { extensionMarker.done(extensionTokenType); } state.suppressErrors = false; if (errorReported || result) { state.clearVariants(true, 0); state.clearVariants(false, 0); state.lastExpectedVariantPos = -1; } } else if (!result && pinned && frame.errorReportedAt < 0) { // do not report if there are errors beyond current position if (lastErrorPos == initialPos) { // do not force, inner recoverRoot might have skipped some tokens reportError(builder, state, frame, elementType, false, false); } else if (lastErrorPos > initialPos) { // set error pos here as if it is reported for future reference frame.errorReportedAt = lastErrorPos; } } // propagate errorReportedAt up the stack to avoid duplicate reporting Frame prevFrame = willFail && eatMore == null ? null : state.frameStack.peekLast(); if (prevFrame != null && prevFrame.errorReportedAt < frame.errorReportedAt) { prevFrame.errorReportedAt = frame.errorReportedAt; } }