import { stream as e } from "../utils/stream.js";
import { isAbstractParserRule as t, isAction as n, isAlternatives as r, isAssignment as i, isBooleanLiteral as a, isConjunction as o, isCrossReference as s, isDisjunction as c, isEndOfFile as l, isGroup as u, isInfixRule as d, isKeyword as f, isNegation as p, isParameterReference as m, isParserRule as h, isRuleCall as g, isTerminalRule as _, isUnorderedGroup as v } from "../languages/generated/ast.js";
import { ErrorWithLocation as y, assertUnreachable as b } from "../utils/errors.js";
import { findNameAssignment as x, getAllReachableRules as S, getTypeName as C } from "../utils/grammar-utils.js";
import { EOF as w } from "../../../chevrotain/lib/src/scan/tokens_public.js";
import { EMPTY_ALT as T } from "../../../chevrotain/lib/src/parse/parser/parser.js";
import "../../../chevrotain/lib/src/api.js";
//#region ../../node_modules/langium/lib/parser/parser-builder-base.js
function E(e, t, n) {
	return D({
		parser: t,
		tokens: n,
		ruleNames: /* @__PURE__ */ new Map()
	}, e), t;
}
function D(t, n) {
	let r = S(n, !1), i = e(n.rules).filter(h).filter((e) => r.has(e));
	for (let e of i) {
		let n = {
			...t,
			consume: 1,
			optional: 1,
			subrule: 1,
			many: 1,
			or: 1
		};
		t.parser.rule(e, k(n, e.definition));
	}
	let a = e(n.rules).filter(d).filter((e) => r.has(e));
	for (let e of a) t.parser.rule(e, O(t, e));
}
function O(e, t) {
	let n = t.call.rule.ref;
	if (!n) throw Error("Could not resolve reference to infix operator rule: " + t.call.rule.$refText);
	if (_(n)) throw Error("Cannot use terminal rule in infix expression");
	let r = t.operators.precedences.flatMap((e) => e.operators), i = {
		$type: "Group",
		elements: []
	}, a = {
		$container: i,
		$type: "Assignment",
		feature: "parts",
		operator: "+=",
		terminal: t.call
	}, o = {
		$container: i,
		$type: "Group",
		elements: [],
		cardinality: "*"
	};
	i.elements.push(a, o);
	let s = {
		$container: o,
		$type: "Assignment",
		feature: "operators",
		operator: "+=",
		terminal: {
			$type: "Alternatives",
			elements: r
		}
	}, c = {
		...a,
		$container: o
	};
	o.elements.push(s, c);
	let l = r.map((t) => e.tokens[t.value]).map((t, n) => ({ ALT: () => e.parser.consume(n, t, s) })), u;
	return (t) => {
		u ??= V(e, n), e.parser.subrule(0, u, !1, a, t), e.parser.many(0, { DEF: () => {
			e.parser.alternatives(0, l), e.parser.subrule(1, u, !1, c, t);
		} });
	};
}
function k(e, t, a = !1) {
	let o;
	if (f(t)) o = z(e, t);
	else if (n(t)) o = A(e, t);
	else if (i(t)) o = k(e, t.terminal);
	else if (s(t)) o = R(e, t);
	else if (g(t)) o = j(e, t);
	else if (r(t)) o = P(e, t);
	else if (v(t)) o = F(e, t);
	else if (u(t)) o = I(e, t);
	else if (l(t)) {
		let n = e.consume++;
		o = () => e.parser.consume(n, w, t);
	} else throw new y(t.$cstNode, `Unexpected element type: ${t.$type}`);
	return B(e, a ? void 0 : L(t), o, t.cardinality);
}
function A(e, t) {
	let n = C(t);
	return () => e.parser.action(n, t);
}
function j(e, n) {
	let r = n.rule.ref;
	if (t(r)) {
		let t = e.subrule++, i = h(r) && r.fragment, a = n.arguments.length > 0 ? M(r, n.arguments) : () => ({}), o;
		return (s) => {
			o ??= V(e, r), e.parser.subrule(t, o, i, n, a(s));
		};
	} else if (_(r)) {
		let t = e.consume++, i = U(e, r.name);
		return () => e.parser.consume(t, i, n);
	} else if (r) b(r);
	else throw new y(n.$cstNode, `Undefined rule: ${n.rule.$refText}`);
}
function M(e, t) {
	if (t.some((e) => e.calledByName)) {
		let e = t.map((e) => ({
			parameterName: e.parameter?.ref?.name,
			predicate: N(e.value)
		}));
		return (t) => {
			let n = {};
			for (let { parameterName: r, predicate: i } of e) r && (n[r] = i(t));
			return n;
		};
	} else {
		let n = t.map((e) => N(e.value));
		return (t) => {
			let r = {};
			for (let i = 0; i < n.length; i++) if (i < e.parameters.length) {
				let a = e.parameters[i].name, o = n[i];
				r[a] = o(t);
			}
			return r;
		};
	}
}
function N(e) {
	if (c(e)) {
		let t = N(e.left), n = N(e.right);
		return (e) => t(e) || n(e);
	} else if (o(e)) {
		let t = N(e.left), n = N(e.right);
		return (e) => t(e) && n(e);
	} else if (p(e)) {
		let t = N(e.value);
		return (e) => !t(e);
	} else if (m(e)) {
		let t = e.parameter.ref.name;
		return (e) => e !== void 0 && e[t] === !0;
	} else if (a(e)) {
		let t = !!e.true;
		return () => t;
	}
	b(e);
}
function P(e, t) {
	if (t.elements.length === 1) return k(e, t.elements[0]);
	{
		let n = [];
		for (let r of t.elements) {
			let t = { ALT: k(e, r, !0) }, i = L(r);
			i && (t.GATE = N(i)), n.push(t);
		}
		let r = e.or++;
		return (t) => e.parser.alternatives(r, n.map((e) => {
			let n = { ALT: () => e.ALT(t) }, r = e.GATE;
			return r && (n.GATE = () => r(t)), n;
		}));
	}
}
function F(e, t) {
	if (t.elements.length === 1) return k(e, t.elements[0]);
	let n = [];
	for (let r of t.elements) {
		let t = { ALT: k(e, r, !0) }, i = L(r);
		i && (t.GATE = N(i)), n.push(t);
	}
	let r = e.or++, i = (e, t) => `uGroup_${e}_${t.getRuleStack().join("-")}`, a = B(e, L(t), (t) => e.parser.alternatives(r, n.map((n, a) => {
		let o = { ALT: () => !0 }, s = e.parser;
		o.ALT = () => {
			if (n.ALT(t), !s.isRecording()) {
				let e = i(r, s);
				s.unorderedGroups.get(e) || s.unorderedGroups.set(e, []);
				let t = s.unorderedGroups.get(e);
				t?.[a] === void 0 && (t[a] = !0);
			}
		};
		let c = n.GATE;
		return c ? o.GATE = () => c(t) : o.GATE = () => !s.unorderedGroups.get(i(r, s))?.[a], o;
	})), "*");
	return (t) => {
		a(t), e.parser.isRecording() || e.parser.unorderedGroups.delete(i(r, e.parser));
	};
}
function I(e, t) {
	let n = t.elements.map((t) => k(e, t));
	return (e) => n.forEach((t) => t(e));
}
function L(e) {
	if (u(e)) return e.guardCondition;
}
function R(e, t, n = t.terminal) {
	if (!n) {
		if (!t.type.ref) throw Error("Could not resolve reference to type: " + t.type.$refText);
		let n = x(t.type.ref)?.terminal;
		if (!n) throw Error("Could not find name assignment for type: " + C(t.type.ref));
		return R(e, t, n);
	} else if (g(n) && h(n.rule.ref)) {
		let r = n.rule.ref, i = e.subrule++, a;
		return (n) => {
			a ??= V(e, r), e.parser.subrule(i, a, !1, t, n);
		};
	} else if (g(n) && _(n.rule.ref)) {
		let r = e.consume++, i = U(e, n.rule.ref.name);
		return () => e.parser.consume(r, i, t);
	} else if (f(n)) {
		let r = e.consume++, i = U(e, n.value);
		return () => e.parser.consume(r, i, t);
	} else throw Error("Could not build cross reference parser");
}
function z(e, t) {
	let n = e.consume++, r = e.tokens[t.value];
	if (!r) throw Error("Could not find token for keyword: " + t.value);
	return () => e.parser.consume(n, r, t);
}
function B(e, t, n, r) {
	let i = t && N(t);
	if (!r) if (i) {
		let t = e.or++;
		return (r) => e.parser.alternatives(t, [{
			ALT: () => n(r),
			GATE: () => i(r)
		}, {
			ALT: T(),
			GATE: () => !i(r)
		}]);
	} else return n;
	if (r === "*") {
		let t = e.many++;
		return (r) => e.parser.many(t, {
			DEF: () => n(r),
			GATE: i ? () => i(r) : void 0
		});
	} else if (r === "+") {
		let t = e.many++;
		if (i) {
			let r = e.or++;
			return (a) => e.parser.alternatives(r, [{
				ALT: () => e.parser.atLeastOne(t, { DEF: () => n(a) }),
				GATE: () => i(a)
			}, {
				ALT: T(),
				GATE: () => !i(a)
			}]);
		} else return (r) => e.parser.atLeastOne(t, { DEF: () => n(r) });
	} else if (r === "?") {
		let t = e.optional++;
		return (r) => e.parser.optional(t, {
			DEF: () => n(r),
			GATE: i ? () => i(r) : void 0
		});
	} else b(r);
}
function V(e, t) {
	let n = H(e, t), r = e.parser.getRule(n);
	if (!r) throw Error(`Rule "${n}" not found."`);
	return r;
}
function H(e, n) {
	if (t(n)) return n.name;
	if (e.ruleNames.has(n)) return e.ruleNames.get(n);
	{
		let t = n, i = t.$container, a = n.$type;
		for (; !h(i);) (u(i) || r(i) || v(i)) && (a = i.elements.indexOf(t).toString() + ":" + a), t = i, i = i.$container;
		return a = i.name + ":" + a, e.ruleNames.set(n, a), a;
	}
}
function U(e, t) {
	let n = e.tokens[t];
	if (!n) throw Error(`Token "${t}" not found."`);
	return n;
}
//#endregion
export { E as createParser };
