import { createTokenInstance as I, tokenMatcher as S, EOF as d } from "../../../scan/tokens_public.js";
import { MismatchedTokenException as N } from "../../exceptions_public.js";
import { IN as g } from "../../constants.js";
import { DEFAULT_PARSER_CONFIG as E } from "../parser.js";
import F from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/has.js";
import v from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/isEmpty.js";
import p from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/find.js";
import w from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/includes.js";
import k from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/map.js";
import x from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/flatten.js";
import y from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/dropRight.js";
import C from "../../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/clone.js";
const T = {}, L = "InRuleRecoveryException";
class A extends Error {
  constructor(e) {
    super(e), this.name = L;
  }
}
class Y {
  initRecoverable(e) {
    this.firstAfterRepMap = {}, this.resyncFollows = {}, this.recoveryEnabled = F(e, "recoveryEnabled") ? e.recoveryEnabled : E.recoveryEnabled, this.recoveryEnabled && (this.attemptInRepetitionRecovery = M);
  }
  getTokenToInsert(e) {
    const t = I(e, "", NaN, NaN, NaN, NaN, NaN, NaN);
    return t.isInsertedInRecovery = !0, t;
  }
  canTokenTypeBeInsertedInRecovery(e) {
    return !0;
  }
  canTokenTypeBeDeletedInRecovery(e) {
    return !0;
  }
  tryInRepetitionRecovery(e, t, r, n) {
    const o = this.findReSyncTokenType(), a = this.exportLexerState(), c = [];
    let s = !1;
    const i = this.LA(1);
    let l = this.LA(1);
    const u = () => {
      const R = this.LA(0), m = this.errorMessageProvider.buildMismatchTokenMessage({
        expected: n,
        actual: i,
        previous: R,
        ruleName: this.getCurrRuleFullName()
      }), f = new N(m, i, this.LA(0));
      f.resyncedTokens = y(c), this.SAVE_ERROR(f);
    };
    for (; !s; )
      if (this.tokenMatcher(l, n)) {
        u();
        return;
      } else if (r.call(this)) {
        u(), e.apply(this, t);
        return;
      } else this.tokenMatcher(l, o) ? s = !0 : (l = this.SKIP_TOKEN(), this.addToResyncTokens(l, c));
    this.importLexerState(a);
  }
  shouldInRepetitionRecoveryBeTried(e, t, r) {
    return !(r === !1 || this.tokenMatcher(this.LA(1), e) || this.isBackTracking() || this.canPerformInRuleRecovery(e, this.getFollowsForInRuleRecovery(e, t)));
  }
  // Error Recovery functionality
  getFollowsForInRuleRecovery(e, t) {
    const r = this.getCurrentGrammarPath(e, t);
    return this.getNextPossibleTokenTypes(r);
  }
  tryInRuleRecovery(e, t) {
    if (this.canRecoverWithSingleTokenInsertion(e, t))
      return this.getTokenToInsert(e);
    if (this.canRecoverWithSingleTokenDeletion(e)) {
      const r = this.SKIP_TOKEN();
      return this.consumeToken(), r;
    }
    throw new A("sad sad panda");
  }
  canPerformInRuleRecovery(e, t) {
    return this.canRecoverWithSingleTokenInsertion(e, t) || this.canRecoverWithSingleTokenDeletion(e);
  }
  canRecoverWithSingleTokenInsertion(e, t) {
    if (!this.canTokenTypeBeInsertedInRecovery(e) || v(t))
      return !1;
    const r = this.LA(1);
    return p(t, (o) => this.tokenMatcher(r, o)) !== void 0;
  }
  canRecoverWithSingleTokenDeletion(e) {
    return this.canTokenTypeBeDeletedInRecovery(e) ? this.tokenMatcher(this.LA(2), e) : !1;
  }
  isInCurrentRuleReSyncSet(e) {
    const t = this.getCurrFollowKey(), r = this.getFollowSetFromFollowKey(t);
    return w(r, e);
  }
  findReSyncTokenType() {
    const e = this.flattenFollowSet();
    let t = this.LA(1), r = 2;
    for (; ; ) {
      const n = p(e, (o) => S(t, o));
      if (n !== void 0)
        return n;
      t = this.LA(r), r++;
    }
  }
  getCurrFollowKey() {
    if (this.RULE_STACK.length === 1)
      return T;
    const e = this.getLastExplicitRuleShortName(), t = this.getLastExplicitRuleOccurrenceIndex(), r = this.getPreviousExplicitRuleShortName();
    return {
      ruleName: this.shortRuleNameToFullName(e),
      idxInCallingRule: t,
      inRule: this.shortRuleNameToFullName(r)
    };
  }
  buildFullFollowKeyStack() {
    const e = this.RULE_STACK, t = this.RULE_OCCURRENCE_STACK;
    return k(e, (r, n) => n === 0 ? T : {
      ruleName: this.shortRuleNameToFullName(r),
      idxInCallingRule: t[n],
      inRule: this.shortRuleNameToFullName(e[n - 1])
    });
  }
  flattenFollowSet() {
    const e = k(this.buildFullFollowKeyStack(), (t) => this.getFollowSetFromFollowKey(t));
    return x(e);
  }
  getFollowSetFromFollowKey(e) {
    if (e === T)
      return [d];
    const t = e.ruleName + e.idxInCallingRule + g + e.inRule;
    return this.resyncFollows[t];
  }
  // It does not make any sense to include a virtual EOF token in the list of resynced tokens
  // as EOF does not really exist and thus does not contain any useful information (line/column numbers)
  addToResyncTokens(e, t) {
    return this.tokenMatcher(e, d) || t.push(e), t;
  }
  reSyncTo(e) {
    const t = [];
    let r = this.LA(1);
    for (; this.tokenMatcher(r, e) === !1; )
      r = this.SKIP_TOKEN(), this.addToResyncTokens(r, t);
    return y(t);
  }
  attemptInRepetitionRecovery(e, t, r, n, o, a, c) {
  }
  getCurrentGrammarPath(e, t) {
    const r = this.getHumanReadableRuleStack(), n = C(this.RULE_OCCURRENCE_STACK);
    return {
      ruleStack: r,
      occurrenceStack: n,
      lastTok: e,
      lastTokOccurrence: t
    };
  }
  getHumanReadableRuleStack() {
    return k(this.RULE_STACK, (e) => this.shortRuleNameToFullName(e));
  }
}
function M(h, e, t, r, n, o, a) {
  const c = this.getKeyForAutomaticLookahead(r, n);
  let s = this.firstAfterRepMap[c];
  if (s === void 0) {
    const R = this.getCurrRuleFullName(), m = this.getGAstProductions()[R];
    s = new o(m, n).startWalking(), this.firstAfterRepMap[c] = s;
  }
  let i = s.token, l = s.occurrence;
  const u = s.isEndOfRule;
  this.RULE_STACK.length === 1 && u && i === void 0 && (i = d, l = 1), !(i === void 0 || l === void 0) && this.shouldInRepetitionRecoveryBeTried(i, l, a) && this.tryInRepetitionRecovery(h, e, t, i);
}
export {
  T as EOF_FOLLOW_KEY,
  L as IN_RULE_RECOVERY_EXCEPTION,
  A as InRuleRecoveryException,
  Y as Recoverable,
  M as attemptInRepetitionRecovery
};
