import { stream } from "../utils/stream.js";
import { streamAllContents } from "../utils/ast-utils.js";
import { isAbstractParserRule, isKeyword, isTerminalRule } from "../languages/generated/ast.js";
import { escapeRegExp, isWhitespace, partialMatches } from "../utils/regexp-utils.js";
import { getAllReachableRules, terminalRegex } from "../utils/grammar-utils.js";
import { Lexer } from "../../../chevrotain/lib/src/scan/lexer_public.js";
import "../../../chevrotain/lib/src/api.js";
var DefaultTokenBuilder = class {
	constructor() {
		this.diagnostics = [];
	}
	buildTokens(s, c) {
		let l = stream(getAllReachableRules(s, !1)), u = this.buildTerminalTokens(l), d = this.buildKeywordTokens(l, u, c);
		return d.push(...u), d;
	}
	flushLexingReport(e) {
		return { diagnostics: this.popDiagnostics() };
	}
	popDiagnostics() {
		let e = [...this.diagnostics];
		return this.diagnostics = [], e;
	}
	buildTerminalTokens(e) {
		return e.filter(isTerminalRule).filter((e) => !e.fragment).map((e) => this.buildTerminalToken(e)).toArray();
	}
	buildTerminalToken(e) {
		let s = terminalRegex(e), c = this.requiresCustomPattern(s) ? this.regexPatternFunction(s) : s, l = {
			name: e.name,
			PATTERN: c
		};
		return typeof c == "function" && (l.LINE_BREAKS = !0), e.hidden && (l.GROUP = isWhitespace(s) ? Lexer.SKIPPED : "hidden"), l;
	}
	requiresCustomPattern(e) {
		return !!(e.flags.includes("u") || e.flags.includes("s"));
	}
	regexPatternFunction(e) {
		let s = new RegExp(e, e.flags + "y");
		return (e, c) => (s.lastIndex = c, s.exec(e));
	}
	buildKeywordTokens(e, u, d) {
		return e.filter(isAbstractParserRule).flatMap((e) => streamAllContents(e).filter(isKeyword)).distinct((e) => e.value).toArray().sort((e, s) => s.value.length - e.value.length).map((e) => this.buildKeywordToken(e, u, !!d?.caseInsensitive));
	}
	buildKeywordToken(e, s, c) {
		let l = this.buildKeywordPattern(e, c), u = {
			name: e.value,
			PATTERN: l,
			LONGER_ALT: this.findLongerAlt(e, s)
		};
		return typeof l == "function" && (u.LINE_BREAKS = !0), u;
	}
	buildKeywordPattern(e, s) {
		return s ? new RegExp(escapeRegExp(e.value), "i") : e.value;
	}
	findLongerAlt(e, s) {
		return s.reduce((s, c) => {
			let l = c?.PATTERN;
			return l?.source && partialMatches("^" + l.source + "$", e.value) && s.push(c), s;
		}, []);
	}
};
export { DefaultTokenBuilder };
