import { isCompositeCstNode as e } from "../syntax-tree.js";
import { getContainerOfType as t, streamAllContents as n } from "./ast-utils.js";
import { isAbstractParserRule as r, isAction as i, isAssignment as a, isCharacterRange as o, isInferredType as s, isInfixRule as c, isInterface as l, isKeyword as u, isNegatedToken as ee, isParserRule as d, isRegexToken as f, isReturnType as p, isRuleCall as m, isSimpleType as h, isTerminalAlternatives as g, isTerminalGroup as _, isTerminalRule as v, isTerminalRuleCall as y, isType as b, isUntilToken as x, isWildcard as S } from "../languages/generated/ast.js";
import { streamCst as C } from "./cst-utils.js";
import { assertUnreachable as w } from "./errors.js";
import { escapeRegExp as T, isWhitespace as te } from "./regexp-utils.js";
//#region ../../node_modules/langium/lib/utils/grammar-utils.js
function E(e) {
	return e.rules.find((e) => d(e) && e.entry);
}
function D(e) {
	return e.rules.filter((e) => v(e) && e.hidden);
}
function O(e, t) {
	let n = /* @__PURE__ */ new Set(), r = E(e);
	if (!r) return new Set(e.rules);
	let i = [r].concat(D(e));
	for (let e of i) k(e, n, t);
	let a = /* @__PURE__ */ new Set();
	for (let t of e.rules) (n.has(t.name) || v(t) && t.hidden) && a.add(t);
	return a;
}
function k(e, t, r) {
	t.add(e.name), n(e).forEach((e) => {
		if (m(e) || r && y(e)) {
			let n = e.rule.ref;
			n && !t.has(n.name) && k(n, t, r);
		}
	});
}
function A(e) {
	if (e.terminal) return e.terminal;
	if (e.type.ref) return R(e.type.ref)?.terminal;
}
function j(e) {
	return e.hidden && !te(K(e));
}
function M(e, t) {
	return !e || !t ? [] : P(e, t, e.astNode, !0);
}
function N(e, t, n) {
	if (!e || !t) return;
	let r = P(e, t, e.astNode, !0);
	if (r.length !== 0) return n = n === void 0 ? 0 : Math.max(0, Math.min(n, r.length - 1)), r[n];
}
function P(n, r, i, o) {
	if (!o) {
		let e = t(n.grammarSource, a);
		if (e && e.feature === r) return [n];
	}
	return e(n) && n.astNode === i ? n.content.flatMap((e) => P(e, r, i, !1)) : [];
}
function F(e, t, n) {
	if (!e) return;
	let r = I(e, t, e?.astNode);
	if (r.length !== 0) return n = n === void 0 ? 0 : Math.max(0, Math.min(n, r.length - 1)), r[n];
}
function I(e, t, n) {
	if (e.astNode !== n) return [];
	if (u(e.grammarSource) && e.grammarSource.value === t) return [e];
	let r = C(e).iterator(), i, a = [];
	do
		if (i = r.next(), !i.done) {
			let e = i.value;
			e.astNode === n ? u(e.grammarSource) && e.grammarSource.value === t && a.push(e) : r.prune();
		}
	while (!i.done);
	return a;
}
function L(e) {
	let n = e.astNode;
	for (; n === e.container?.astNode;) {
		let n = t(e.grammarSource, a);
		if (n) return n;
		e = e.container;
	}
}
function R(e) {
	let t = e;
	return s(t) && (i(t.$container) ? t = t.$container.$container : r(t.$container) ? t = t.$container : w(t.$container)), z(e, t, /* @__PURE__ */ new Map());
}
function z(e, r, i) {
	function o(n, r) {
		let o;
		return t(n, a) || (o = z(r, r, i)), i.set(e, o), o;
	}
	if (i.has(e)) return i.get(e);
	i.set(e, void 0);
	for (let t of n(r)) if (a(t) && t.feature.toLowerCase() === "name") return i.set(e, t), t;
	else if (m(t) && d(t.rule.ref)) return o(t, t.rule.ref);
	else if (h(t) && t.typeRef?.ref) return o(t, t.typeRef.ref);
}
function B(e) {
	return V(e, /* @__PURE__ */ new Set());
}
function V(e, t) {
	if (t.has(e)) return !0;
	t.add(e);
	for (let r of n(e)) if (m(r)) {
		if (!r.rule.ref || d(r.rule.ref) && !V(r.rule.ref, t) || c(r.rule.ref)) return !1;
	} else if (a(r)) return !1;
	else if (i(r)) return !1;
	return !!e.definition;
}
function H(e) {
	if (!v(e)) {
		if (e.inferredType) return e.inferredType.name;
		if (e.dataType) return e.dataType;
		if (e.returnType) {
			let t = e.returnType.ref;
			if (t) return t.name;
		}
	}
}
function U(e) {
	if (r(e)) return d(e) && B(e) ? e.name : H(e) ?? e.name;
	if (l(e) || b(e) || p(e)) return e.name;
	if (i(e)) {
		let t = W(e);
		if (t) return t;
	} else if (s(e)) return e.name;
	throw Error("Cannot get name of Unknown Type");
}
function W(e) {
	if (e.inferredType) return e.inferredType.name;
	if (e.type?.ref) return U(e.type.ref);
}
function G(e) {
	return v(e) ? e.type?.name ?? "string" : H(e) ?? e.name;
}
function K(e) {
	let t = {
		s: !1,
		i: !1,
		u: !1
	}, n = J(e.definition, t), r = Object.entries(t).filter(([, e]) => e).map(([e]) => e).join("");
	return new RegExp(n, r);
}
var q = "[\\s\\S]";
function J(e, t) {
	if (g(e)) return Y(e);
	if (_(e)) return X(e);
	if (o(e)) return re(e);
	if (y(e)) {
		let t = e.rule.ref;
		if (!t) throw Error("Missing rule reference.");
		return $(J(t.definition), {
			cardinality: e.cardinality,
			lookahead: e.lookahead,
			parenthesized: e.parenthesized
		});
	} else if (ee(e)) return ne(e);
	else if (x(e)) return Z(e);
	else if (f(e)) {
		let n = e.regex.lastIndexOf("/"), r = e.regex.substring(1, n), i = e.regex.substring(n + 1);
		return t && (t.i = i.includes("i"), t.s = i.includes("s"), t.u = i.includes("u")), $(r, {
			cardinality: e.cardinality,
			lookahead: e.lookahead,
			parenthesized: e.parenthesized,
			wrap: !1
		});
	} else if (S(e)) return $(q, {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized
	});
	else throw Error(`Invalid terminal element: ${e?.$type}, ${e?.$cstNode?.text}`);
}
function Y(e) {
	return $(e.elements.map((e) => J(e)).join("|"), {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized,
		wrap: !1
	});
}
function X(e) {
	return $(e.elements.map((e) => J(e)).join(""), {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized,
		wrap: !1
	});
}
function Z(e) {
	return $(`${q}*?${J(e.terminal)}`, {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized
	});
}
function ne(e) {
	return $(`(?!${J(e.terminal)})${q}*?`, {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized
	});
}
function re(e) {
	return e.right ? $(`[${Q(e.left)}-${Q(e.right)}]`, {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized,
		wrap: !1
	}) : $(Q(e.left), {
		cardinality: e.cardinality,
		lookahead: e.lookahead,
		parenthesized: e.parenthesized,
		wrap: !1
	});
}
function Q(e) {
	return T(e.value);
}
function $(e, t) {
	return (t.parenthesized || t.lookahead || t.wrap !== !1) && (e = `(${t.lookahead ?? (t.parenthesized ? "" : "?:")}${e})`), t.cardinality ? `${e}${t.cardinality}` : e;
}
//#endregion
export { L as findAssignment, R as findNameAssignment, F as findNodeForKeyword, N as findNodeForProperty, M as findNodesForProperty, O as getAllReachableRules, A as getCrossReferenceTerminal, G as getRuleType, U as getTypeName, j as isCommentTerminal, B as isDataTypeRule, K as terminalRegex };
