public static void report_error_(PsiBuilder builder_) {
    ErrorState state = ErrorState.get(builder_);

    Frame frame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast();
    if (frame == null) {
      LOG.error("Unbalanced error section: got null , expected " + frame);
      return;
    }
    int offset = builder_.getCurrentOffset();
    if (frame.errorReportedAt < offset
        && getLastVariantOffset(state, builder_.getCurrentOffset()) <= offset) {
      if (reportError(state, builder_, true)) {
        frame.errorReportedAt = offset;
      }
    }
  }
 public static boolean empty_element_parsed_guard_(PsiBuilder builder, String funcName, int pos) {
   if (pos == current_position_(builder)) {
     builder.error(
         "Empty element parsed in '" + funcName + "' at offset " + builder.getCurrentOffset());
     return false;
   }
   return true;
 }
 public String getExpectedText(PsiBuilder builder_) {
   int offset = builder_.getCurrentOffset();
   StringBuilder sb = new StringBuilder();
   if (addExpected(sb, offset, true)) {
     sb.append(" expected, ");
   } else if (addExpected(sb, offset, false)) sb.append(" unexpected, ");
   return sb.toString();
 }
 public static boolean replaceVariants(PsiBuilder builder_, int variantCount, String frameName) {
   ErrorState state = ErrorState.get(builder_);
   if (!state.suppressErrors && state.predicateCount < 2 && state.predicateSign) {
     state.clearVariants(true, state.variants.size() - variantCount);
     addVariantInner(state, builder_.getCurrentOffset(), frameName);
   }
   return true;
 }
  private static void addVariant(ErrorState state, PsiBuilder builder_, Object o) {
    int offset = builder_.getCurrentOffset();
    addVariantInner(state, offset, o);

    CompletionState completionState = state.completionState;
    if (completionState != null && state.predicateSign) {
      addCompletionVariant(state, completionState, builder_, o, offset);
    }
  }
  public static boolean invalid_left_marker_guard_(
      PsiBuilder builder_, PsiBuilder.Marker marker_, String funcName_) {
    // builder_.error("Invalid left marker encountered in " + funcName_ +" at offset " +
    // builder_.getCurrentOffset());
    boolean goodMarker =
        marker_ != null && ((LighterASTNode) marker_).getTokenType() != TokenType.ERROR_ELEMENT;
    if (!goodMarker) return false;
    ErrorState state = ErrorState.get(builder_);

    Frame frame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast();
    return frame == null || frame.errorReportedAt <= builder_.getCurrentOffset();
  }
    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;
    }
  public static int nextTokenIsFast(PsiBuilder builder, String tokenText, boolean caseSensitive) {
    CharSequence sequence = builder.getOriginalText();
    int offset = builder.getCurrentOffset();
    int endOffset = offset + tokenText.length();
    CharSequence subSequence = sequence.subSequence(offset, Math.min(endOffset, sequence.length()));

    if (!Comparing.equal(subSequence, tokenText, caseSensitive)) return 0;

    int count = 0;
    while (true) {
      int nextOffset = builder.rawTokenTypeStart(++count);
      if (nextOffset > endOffset) {
        return -count;
      } else if (nextOffset == endOffset) {
        break;
      }
    }
    return count;
  }
  private static void addCompletionVariant(
      @NotNull PsiBuilder builder, @NotNull CompletionState completionState, Object o) {
    int offset = builder.getCurrentOffset();
    if (!builder.eof() && offset == builder.rawTokenTypeStart(1))
      return; // suppress for zero-length tokens

    boolean add = false;
    int diff = completionState.offset - offset;
    String text = completionState.convertItem(o);
    int length = text == null ? 0 : text.length();
    if (length == 0) return;
    if (diff == 0) {
      add = true;
    } else if (diff > 0 && diff <= length) {
      CharSequence fragment = builder.getOriginalText().subSequence(offset, completionState.offset);
      add = completionState.prefixMatches(fragment.toString(), text);
    } else if (diff < 0) {
      for (int i = -1; ; i--) {
        IElementType type = builder.rawLookup(i);
        int tokenStart = builder.rawTokenTypeStart(i);
        if (isWhitespaceOrComment(builder, type)) {
          diff = completionState.offset - tokenStart;
        } else if (type != null && tokenStart < completionState.offset) {
          CharSequence fragment =
              builder.getOriginalText().subSequence(tokenStart, completionState.offset);
          if (completionState.prefixMatches(fragment.toString(), text)) {
            diff = completionState.offset - tokenStart;
          }
          break;
        } else break;
      }
      add = diff >= 0 && diff < length;
    }
    add =
        add
            && length > 1
            && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>')
            && !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5);
    if (add) {
      completionState.addItem(builder, text);
    }
  }
    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 boolean consumeTokens(PsiBuilder builder_, int pin_, IElementType... tokens_) {
   ErrorState state = ErrorState.get(builder_);
   if (state.completionState != null && state.predicateSign) {
     addCompletionVariant(
         state, state.completionState, builder_, tokens_, builder_.getCurrentOffset());
   }
   // suppress single token completion
   CompletionState completionState = state.completionState;
   state.completionState = null;
   boolean result_ = true;
   boolean pinned_ = false;
   for (int i = 0, tokensLength = tokens_.length; i < tokensLength; i++) {
     if (pin_ > 0 && i == pin_) pinned_ = result_;
     if ((result_ || pinned_) && !consumeToken(builder_, tokens_[i])) {
       result_ = false;
       if (pin_ < 0 || pinned_) report_error_(builder_);
     }
   }
   state.completionState = completionState;
   return pinned_ || result_;
 }
  public static boolean consumeTokenInner(PsiBuilder builder_, String text, boolean caseSensitive) {
    final CharSequence sequence = builder_.getOriginalText();
    final int offset = builder_.getCurrentOffset();
    final int endOffset = offset + text.length();
    CharSequence tokenText = sequence.subSequence(offset, Math.min(endOffset, sequence.length()));

    if (Comparing.equal(text, tokenText, caseSensitive)) {
      int count = 0;
      while (true) {
        final int nextOffset = builder_.rawTokenTypeStart(++count);
        if (nextOffset > endOffset) {
          return false;
        } else if (nextOffset == endOffset) {
          break;
        }
      }
      while (count-- > 0) builder_.advanceLexer();
      return true;
    }
    return false;
  }
 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++;
   }
 }
 protected int getCurrentOffset() {
   return myBuilder.getCurrentOffset();
 }
  // 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;
      }
    }
  }
  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;
  }