public static void exit_section_( PsiBuilder builder, int level, PsiBuilder.Marker marker, @Nullable IElementType elementType, boolean result, boolean pinned, @Nullable Parser eatMore) { ErrorState state = ErrorState.get(builder); Frame frame = state.frameStack.pollLast(); if (frame == null || level != frame.level) { LOG.error("Unbalanced error section: got " + frame + ", expected level " + level); if (frame != null) state.FRAMES.recycle(frame); close_marker_impl_(frame, marker, elementType, result); return; } if (((frame.modifiers & _AND_) | (frame.modifiers & _NOT_)) != 0) { close_marker_impl_(frame, marker, null, false); state.predicateCount--; if ((frame.modifiers & _NOT_) != 0) state.predicateSign = !state.predicateSign; state.FRAMES.recycle(frame); return; } close_frame_impl_(state, frame, builder, marker, elementType, result, pinned); exit_section_impl_(state, frame, builder, elementType, result, pinned, eatMore); state.FRAMES.recycle(frame); }
private static void enter_section_impl_( PsiBuilder builder, int level, int modifiers, @Nullable String frameName) { ErrorState state = ErrorState.get(builder); Frame frame = state.FRAMES.alloc().init(builder, state, level, modifiers, frameName); Frame prevFrame = state.frameStack.peekLast(); if (prevFrame != null && prevFrame.errorReportedAt > frame.position) { // report error for previous unsuccessful frame reportError(builder, state, frame, null, true, false); } if (((frame.modifiers & _LEFT_) | (frame.modifiers & _LEFT_INNER_)) != 0) { PsiBuilder.Marker left = (PsiBuilder.Marker) builder.getLatestDoneMarker(); if (invalid_left_marker_guard_(builder, left, frameName)) { frame.leftMarker = left; } } state.frameStack.add(frame); if ((modifiers & _AND_) != 0) { if (state.predicateCount == 0 && !state.predicateSign) { throw new AssertionError("Incorrect false predicate sign"); } state.predicateCount++; } else if ((modifiers & _NOT_) != 0) { if (state.predicateCount == 0) { state.predicateSign = false; } else { state.predicateSign = !state.predicateSign; } state.predicateCount++; } }
public static void enterErrorRecordingSection( PsiBuilder builder_, int level, @NotNull String sectionType, @Nullable String frameName) { ErrorState state = ErrorState.get(builder_); Frame frame = state .FRAMES .alloc() .init( builder_.getCurrentOffset(), level, sectionType, frameName, state.variants.size()); state.levelCheck.add(frame); if (sectionType == _SECTION_AND_) { if (state.predicateCount == 0 && !state.predicateSign) { throw new AssertionError("Incorrect false predicate sign"); } state.predicateCount++; } else if (sectionType == _SECTION_NOT_) { if (state.predicateCount == 0) { state.predicateSign = false; } else { state.predicateSign = !state.predicateSign; } state.predicateCount++; } }
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; }