import isObject_default from "../../../../../../lodash-es/isObject.js";
import isArray_default from "../../../../../../lodash-es/isArray.js";
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 every_default from "../../../../../../lodash-es/every.js";
import has_default from "../../../../../../lodash-es/has.js";
import values_default from "../../../../../../lodash-es/values.js";
import reduce_default from "../../../../../../lodash-es/reduce.js";
import uniq_default from "../../../../../../lodash-es/uniq.js";
import { augmentTokenTypes, isTokenType, tokenStructuredMatcher, tokenStructuredMatcherNoCategories } from "../../../scan/tokens.js";
import { EOF } from "../../../scan/tokens_public.js";
import { NextTerminalAfterAtLeastOneSepWalker, NextTerminalAfterAtLeastOneWalker, NextTerminalAfterManySepWalker, NextTerminalAfterManyWalker } from "../../grammar/interpreter.js";
import { PROD_TYPE } from "../../grammar/lookahead.js";
import { MismatchedTokenException, NotAllInputParsedException, isRecognitionException } from "../../exceptions_public.js";
import { IN_RULE_RECOVERY_EXCEPTION } from "./recoverable.js";
import { AT_LEAST_ONE_IDX, AT_LEAST_ONE_SEP_IDX, BITS_FOR_METHOD_TYPE, BITS_FOR_OCCURRENCE_IDX, MANY_IDX, MANY_SEP_IDX, OPTION_IDX, OR_IDX } from "../../grammar/keys.js";
import { DEFAULT_RULE_CONFIG } from "../parser.js";
var RecognizerEngine = class {
	initRecognizerEngine(M, N) {
		if (this.className = this.constructor.name, this.shortRuleNameToFull = {}, this.fullRuleNameToShort = {}, this.ruleShortNameIdx = 256, this.tokenMatcher = tokenStructuredMatcherNoCategories, this.subruleIdx = 0, this.definedRulesNames = [], this.tokensMap = {}, this.isBackTrackingStack = [], this.RULE_STACK = [], this.RULE_OCCURRENCE_STACK = [], this.gastProductionsCache = {}, has_default(N, "serializedGrammar")) throw Error("The Parser's configuration can no longer contain a <serializedGrammar> property.\n	See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_6-0-0\n	For Further details.");
		if (isArray_default(M)) {
			if (isEmpty_default(M)) throw Error("A Token Vocabulary cannot be empty.\n	Note that the first argument for the parser constructor\n	is no longer a Token vector (since v4.0).");
			if (typeof M[0].startOffset == "number") throw Error("The Parser constructor no longer accepts a token vector as the first argument.\n	See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_4-0-0\n	For Further details.");
		}
		if (isArray_default(M)) this.tokensMap = reduce_default(M, (l, E) => (l[E.name] = E, l), {});
		else if (has_default(M, "modes") && every_default(flatten_default(values_default(M.modes)), isTokenType)) this.tokensMap = reduce_default(uniq_default(flatten_default(values_default(M.modes))), (l, E) => (l[E.name] = E, l), {});
		else if (isObject_default(M)) this.tokensMap = clone_default(M);
		else throw Error("<tokensDictionary> argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");
		this.tokensMap.EOF = EOF, this.tokenMatcher = every_default(has_default(M, "modes") ? flatten_default(values_default(M.modes)) : values_default(M), (l) => isEmpty_default(l.categoryMatches)) ? tokenStructuredMatcherNoCategories : tokenStructuredMatcher, augmentTokenTypes(values_default(this.tokensMap));
	}
	defineRule(l, E, D) {
		if (this.selfAnalysisDone) throw Error(`Grammar rule <${l}> may not be defined after the 'performSelfAnalysis' method has been called'\nMake sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.`);
		let O = has_default(D, "resyncEnabled") ? D.resyncEnabled : DEFAULT_RULE_CONFIG.resyncEnabled, k = has_default(D, "recoveryValueFunc") ? D.recoveryValueFunc : DEFAULT_RULE_CONFIG.recoveryValueFunc, A = this.ruleShortNameIdx << 12;
		this.ruleShortNameIdx++, this.shortRuleNameToFull[A] = l, this.fullRuleNameToShort[l] = A;
		let j;
		return j = this.outputCst === !0 ? function(...D) {
			try {
				this.ruleInvocationStateUpdate(A, l, this.subruleIdx), E.apply(this, D);
				let O = this.CST_STACK[this.CST_STACK.length - 1];
				return this.cstPostRule(O), O;
			} catch (l) {
				return this.invokeRuleCatch(l, O, k);
			} finally {
				this.ruleFinallyStateUpdate();
			}
		} : function(...D) {
			try {
				return this.ruleInvocationStateUpdate(A, l, this.subruleIdx), E.apply(this, D);
			} catch (l) {
				return this.invokeRuleCatch(l, O, k);
			} finally {
				this.ruleFinallyStateUpdate();
			}
		}, Object.assign(j, {
			ruleName: l,
			originalGrammarAction: E
		});
	}
	invokeRuleCatch(l, E, D) {
		let O = this.RULE_STACK.length === 1, k = E && !this.isBackTracking() && this.recoveryEnabled;
		if (isRecognitionException(l)) {
			let E = l;
			if (k) {
				let O = this.findReSyncTokenType();
				if (this.isInCurrentRuleReSyncSet(O)) if (E.resyncedTokens = this.reSyncTo(O), this.outputCst) {
					let l = this.CST_STACK[this.CST_STACK.length - 1];
					return l.recoveredNode = !0, l;
				} else return D(l);
				else {
					if (this.outputCst) {
						let l = this.CST_STACK[this.CST_STACK.length - 1];
						l.recoveredNode = !0, E.partialCstResult = l;
					}
					throw E;
				}
			} else if (O) return this.moveToTerminatedState(), D(l);
			else throw E;
		} else throw l;
	}
	optionInternal(l, E) {
		let D = this.getKeyForAutomaticLookahead(512, E);
		return this.optionInternalLogic(l, E, D);
	}
	optionInternalLogic(l, E, D) {
		let O = this.getLaFuncFromCache(D), k;
		if (typeof l != "function") {
			k = l.DEF;
			let E = l.GATE;
			if (E !== void 0) {
				let l = O;
				O = () => E.call(this) && l.call(this);
			}
		} else k = l;
		if (O.call(this) === !0) return k.call(this);
	}
	atLeastOneInternal(l, E) {
		let D = this.getKeyForAutomaticLookahead(AT_LEAST_ONE_IDX, l);
		return this.atLeastOneInternalLogic(l, E, D);
	}
	atLeastOneInternalLogic(l, E, D) {
		let O = this.getLaFuncFromCache(D), k;
		if (typeof E != "function") {
			k = E.DEF;
			let l = E.GATE;
			if (l !== void 0) {
				let E = O;
				O = () => l.call(this) && E.call(this);
			}
		} else k = E;
		if (O.call(this) === !0) {
			let l = this.doSingleRepetition(k);
			for (; O.call(this) === !0 && l === !0;) l = this.doSingleRepetition(k);
		} else throw this.raiseEarlyExitException(l, PROD_TYPE.REPETITION_MANDATORY, E.ERR_MSG);
		this.attemptInRepetitionRecovery(this.atLeastOneInternal, [l, E], O, AT_LEAST_ONE_IDX, l, NextTerminalAfterAtLeastOneWalker);
	}
	atLeastOneSepFirstInternal(l, E) {
		let D = this.getKeyForAutomaticLookahead(AT_LEAST_ONE_SEP_IDX, l);
		this.atLeastOneSepFirstInternalLogic(l, E, D);
	}
	atLeastOneSepFirstInternalLogic(l, E, D) {
		let O = E.DEF, k = E.SEP;
		if (this.getLaFuncFromCache(D).call(this) === !0) {
			O.call(this);
			let E = () => this.tokenMatcher(this.LA(1), k);
			for (; this.tokenMatcher(this.LA(1), k) === !0;) this.CONSUME(k), O.call(this);
			this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal, [
				l,
				k,
				E,
				O,
				NextTerminalAfterAtLeastOneSepWalker
			], E, AT_LEAST_ONE_SEP_IDX, l, NextTerminalAfterAtLeastOneSepWalker);
		} else throw this.raiseEarlyExitException(l, PROD_TYPE.REPETITION_MANDATORY_WITH_SEPARATOR, E.ERR_MSG);
	}
	manyInternal(l, E) {
		let D = this.getKeyForAutomaticLookahead(768, l);
		return this.manyInternalLogic(l, E, D);
	}
	manyInternalLogic(l, E, D) {
		let O = this.getLaFuncFromCache(D), k;
		if (typeof E != "function") {
			k = E.DEF;
			let l = E.GATE;
			if (l !== void 0) {
				let E = O;
				O = () => l.call(this) && E.call(this);
			}
		} else k = E;
		let A = !0;
		for (; O.call(this) === !0 && A === !0;) A = this.doSingleRepetition(k);
		this.attemptInRepetitionRecovery(this.manyInternal, [l, E], O, 768, l, NextTerminalAfterManyWalker, A);
	}
	manySepFirstInternal(l, E) {
		let D = this.getKeyForAutomaticLookahead(MANY_SEP_IDX, l);
		this.manySepFirstInternalLogic(l, E, D);
	}
	manySepFirstInternalLogic(l, E, D) {
		let O = E.DEF, k = E.SEP;
		if (this.getLaFuncFromCache(D).call(this) === !0) {
			O.call(this);
			let E = () => this.tokenMatcher(this.LA(1), k);
			for (; this.tokenMatcher(this.LA(1), k) === !0;) this.CONSUME(k), O.call(this);
			this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal, [
				l,
				k,
				E,
				O,
				NextTerminalAfterManySepWalker
			], E, MANY_SEP_IDX, l, NextTerminalAfterManySepWalker);
		}
	}
	repetitionSepSecondInternal(l, E, D, O, k) {
		for (; D();) this.CONSUME(E), O.call(this);
		/* istanbul ignore else */
		this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal, [
			l,
			E,
			D,
			O,
			k
		], D, AT_LEAST_ONE_SEP_IDX, l, k);
	}
	doSingleRepetition(l) {
		let E = this.getLexerPosition();
		return l.call(this), this.getLexerPosition() > E;
	}
	orInternal(l, D) {
		let O = this.getKeyForAutomaticLookahead(256, D), k = isArray_default(l) ? l : l.DEF, A = this.getLaFuncFromCache(O).call(this, k);
		if (A !== void 0) return k[A].ALT.call(this);
		this.raiseNoAltException(D, l.ERR_MSG);
	}
	ruleFinallyStateUpdate() {
		if (this.RULE_STACK.pop(), this.RULE_OCCURRENCE_STACK.pop(), this.cstFinallyStateUpdate(), this.RULE_STACK.length === 0 && this.isAtEndOfInput() === !1) {
			let l = this.LA(1), E = this.errorMessageProvider.buildNotAllInputParsedMessage({
				firstRedundant: l,
				ruleName: this.getCurrRuleFullName()
			});
			this.SAVE_ERROR(new NotAllInputParsedException(E, l));
		}
	}
	subruleInternal(l, E, D) {
		let O;
		try {
			let k = D === void 0 ? void 0 : D.ARGS;
			return this.subruleIdx = E, O = l.apply(this, k), this.cstPostNonTerminal(O, D !== void 0 && D.LABEL !== void 0 ? D.LABEL : l.ruleName), O;
		} catch (E) {
			throw this.subruleInternalError(E, D, l.ruleName);
		}
	}
	subruleInternalError(l, E, D) {
		throw isRecognitionException(l) && l.partialCstResult !== void 0 && (this.cstPostNonTerminal(l.partialCstResult, E !== void 0 && E.LABEL !== void 0 ? E.LABEL : D), delete l.partialCstResult), l;
	}
	consumeInternal(l, E, D) {
		let O;
		try {
			let E = this.LA(1);
			this.tokenMatcher(E, l) === !0 ? (this.consumeToken(), O = E) : this.consumeInternalError(l, E, D);
		} catch (D) {
			O = this.consumeInternalRecovery(l, E, D);
		}
		return this.cstPostTerminal(D !== void 0 && D.LABEL !== void 0 ? D.LABEL : l.name, O), O;
	}
	consumeInternalError(l, E, D) {
		let O, k = this.LA(0);
		throw O = D !== void 0 && D.ERR_MSG ? D.ERR_MSG : this.errorMessageProvider.buildMismatchTokenMessage({
			expected: l,
			actual: E,
			previous: k,
			ruleName: this.getCurrRuleFullName()
		}), this.SAVE_ERROR(new MismatchedTokenException(O, E, k));
	}
	consumeInternalRecovery(l, E, D) {
		if (this.recoveryEnabled && D.name === "MismatchedTokenException" && !this.isBackTracking()) {
			let O = this.getFollowsForInRuleRecovery(l, E);
			try {
				return this.tryInRuleRecovery(l, O);
			} catch (l) {
				throw l.name === "InRuleRecoveryException" ? D : l;
			}
		} else throw D;
	}
	saveRecogState() {
		let l = this.errors, E = clone_default(this.RULE_STACK);
		return {
			errors: l,
			lexerState: this.exportLexerState(),
			RULE_STACK: E,
			CST_STACK: this.CST_STACK
		};
	}
	reloadRecogState(l) {
		this.errors = l.errors, this.importLexerState(l.lexerState), this.RULE_STACK = l.RULE_STACK;
	}
	ruleInvocationStateUpdate(l, E, D) {
		this.RULE_OCCURRENCE_STACK.push(D), this.RULE_STACK.push(l), this.cstInvocationStateUpdate(E);
	}
	isBackTracking() {
		return this.isBackTrackingStack.length !== 0;
	}
	getCurrRuleFullName() {
		let l = this.getLastExplicitRuleShortName();
		return this.shortRuleNameToFull[l];
	}
	shortRuleNameToFullName(l) {
		return this.shortRuleNameToFull[l];
	}
	isAtEndOfInput() {
		return this.tokenMatcher(this.LA(1), EOF);
	}
	reset() {
		this.resetLexerState(), this.subruleIdx = 0, this.isBackTrackingStack = [], this.errors = [], this.RULE_STACK = [], this.CST_STACK = [], this.RULE_OCCURRENCE_STACK = [];
	}
};
export { RecognizerEngine };
