import isEmpty_default from "../../../../../../lodash-es/isEmpty.js";
import flatten_default from "../../../../../../lodash-es/flatten.js";
import clone_default from "../../../../../../lodash-es/clone.js";
import dropRight_default from "../../../../../../lodash-es/dropRight.js";
import find_default from "../../../../../../lodash-es/find.js";
import map_default from "../../../../../../lodash-es/map.js";
import has_default from "../../../../../../lodash-es/has.js";
import includes_default from "../../../../../../lodash-es/includes.js";
import { IN } from "../../constants.js";
import { EOF, createTokenInstance, tokenMatcher } from "../../../scan/tokens_public.js";
import { MismatchedTokenException } from "../../exceptions_public.js";
import { DEFAULT_PARSER_CONFIG } from "../parser.js";
const EOF_FOLLOW_KEY = {}, IN_RULE_RECOVERY_EXCEPTION = "InRuleRecoveryException";
var InRuleRecoveryException = class extends Error {
	constructor(e) {
		super(e), this.name = IN_RULE_RECOVERY_EXCEPTION;
	}
}, Recoverable = class {
	initRecoverable(e) {
		this.firstAfterRepMap = {}, this.resyncFollows = {}, this.recoveryEnabled = has_default(e, "recoveryEnabled") ? e.recoveryEnabled : DEFAULT_PARSER_CONFIG.recoveryEnabled, this.recoveryEnabled && (this.attemptInRepetitionRecovery = attemptInRepetitionRecovery);
	}
	getTokenToInsert(e) {
		let s = createTokenInstance(e, "", NaN, NaN, NaN, NaN, NaN, NaN);
		return s.isInsertedInRecovery = !0, s;
	}
	canTokenTypeBeInsertedInRecovery(e) {
		return !0;
	}
	canTokenTypeBeDeletedInRecovery(e) {
		return !0;
	}
	tryInRepetitionRecovery(e, s, c, u) {
		let d = this.findReSyncTokenType(), f = this.exportLexerState(), p = [], m = !1, h = this.LA(1), g = this.LA(1), _ = () => {
			let e = this.LA(0), s = new MismatchedTokenException(this.errorMessageProvider.buildMismatchTokenMessage({
				expected: u,
				actual: h,
				previous: e,
				ruleName: this.getCurrRuleFullName()
			}), h, this.LA(0));
			s.resyncedTokens = dropRight_default(p), this.SAVE_ERROR(s);
		};
		for (; !m;) if (this.tokenMatcher(g, u)) {
			_();
			return;
		} else if (c.call(this)) {
			_(), e.apply(this, s);
			return;
		} else this.tokenMatcher(g, d) ? m = !0 : (g = this.SKIP_TOKEN(), this.addToResyncTokens(g, p));
		this.importLexerState(f);
	}
	shouldInRepetitionRecoveryBeTried(e, s, c) {
		return !(c === !1 || this.tokenMatcher(this.LA(1), e) || this.isBackTracking() || this.canPerformInRuleRecovery(e, this.getFollowsForInRuleRecovery(e, s)));
	}
	getFollowsForInRuleRecovery(e, s) {
		let c = this.getCurrentGrammarPath(e, s);
		return this.getNextPossibleTokenTypes(c);
	}
	tryInRuleRecovery(e, s) {
		if (this.canRecoverWithSingleTokenInsertion(e, s)) return this.getTokenToInsert(e);
		if (this.canRecoverWithSingleTokenDeletion(e)) {
			let e = this.SKIP_TOKEN();
			return this.consumeToken(), e;
		}
		throw new InRuleRecoveryException("sad sad panda");
	}
	canPerformInRuleRecovery(e, s) {
		return this.canRecoverWithSingleTokenInsertion(e, s) || this.canRecoverWithSingleTokenDeletion(e);
	}
	canRecoverWithSingleTokenInsertion(s, c) {
		if (!this.canTokenTypeBeInsertedInRecovery(s) || isEmpty_default(c)) return !1;
		let l = this.LA(1);
		return find_default(c, (e) => this.tokenMatcher(l, e)) !== void 0;
	}
	canRecoverWithSingleTokenDeletion(e) {
		return this.canTokenTypeBeDeletedInRecovery(e) ? this.tokenMatcher(this.LA(2), e) : !1;
	}
	isInCurrentRuleReSyncSet(e) {
		let s = this.getCurrFollowKey();
		return includes_default(this.getFollowSetFromFollowKey(s), e);
	}
	findReSyncTokenType() {
		let e = this.flattenFollowSet(), s = this.LA(1), c = 2;
		for (;;) {
			let l = find_default(e, (e) => tokenMatcher(s, e));
			if (l !== void 0) return l;
			s = this.LA(c), c++;
		}
	}
	getCurrFollowKey() {
		if (this.RULE_STACK.length === 1) return EOF_FOLLOW_KEY;
		let e = this.getLastExplicitRuleShortName(), s = this.getLastExplicitRuleOccurrenceIndex(), c = this.getPreviousExplicitRuleShortName();
		return {
			ruleName: this.shortRuleNameToFullName(e),
			idxInCallingRule: s,
			inRule: this.shortRuleNameToFullName(c)
		};
	}
	buildFullFollowKeyStack() {
		let e = this.RULE_STACK, s = this.RULE_OCCURRENCE_STACK;
		return map_default(e, (c, l) => l === 0 ? EOF_FOLLOW_KEY : {
			ruleName: this.shortRuleNameToFullName(c),
			idxInCallingRule: s[l],
			inRule: this.shortRuleNameToFullName(e[l - 1])
		});
	}
	flattenFollowSet() {
		return flatten_default(map_default(this.buildFullFollowKeyStack(), (e) => this.getFollowSetFromFollowKey(e)));
	}
	getFollowSetFromFollowKey(e) {
		if (e === EOF_FOLLOW_KEY) return [EOF];
		let s = e.ruleName + e.idxInCallingRule + IN + e.inRule;
		return this.resyncFollows[s];
	}
	addToResyncTokens(e, s) {
		return this.tokenMatcher(e, EOF) || s.push(e), s;
	}
	reSyncTo(e) {
		let s = [], c = this.LA(1);
		for (; this.tokenMatcher(c, e) === !1;) c = this.SKIP_TOKEN(), this.addToResyncTokens(c, s);
		return dropRight_default(s);
	}
	attemptInRepetitionRecovery(e, s, c, l, u, d, f) {}
	getCurrentGrammarPath(e, s) {
		return {
			ruleStack: this.getHumanReadableRuleStack(),
			occurrenceStack: clone_default(this.RULE_OCCURRENCE_STACK),
			lastTok: e,
			lastTokOccurrence: s
		};
	}
	getHumanReadableRuleStack() {
		return map_default(this.RULE_STACK, (e) => this.shortRuleNameToFullName(e));
	}
};
function attemptInRepetitionRecovery(e, s, c, l, u, d, f) {
	let p = this.getKeyForAutomaticLookahead(l, u), m = this.firstAfterRepMap[p];
	if (m === void 0) {
		let e = this.getCurrRuleFullName(), s = this.getGAstProductions()[e];
		m = new d(s, u).startWalking(), this.firstAfterRepMap[p] = m;
	}
	let g = m.token, _ = m.occurrence, v = m.isEndOfRule;
	this.RULE_STACK.length === 1 && v && g === void 0 && (g = EOF, _ = 1), !(g === void 0 || _ === void 0) && this.shouldInRepetitionRecoveryBeTried(g, _, f) && this.tryInRepetitionRecovery(e, s, c, g);
}
export { IN_RULE_RECOVERY_EXCEPTION, Recoverable };
