import assign_default from "../../../../lodash-es/assign.js";
import forEach_default from "../../../../lodash-es/forEach.js";
import map_default from "../../../../lodash-es/map.js";
import isString_default from "../../../../lodash-es/isString.js";
import isRegExp_default from "../../../../lodash-es/isRegExp.js";
import pickBy_default from "../../../../lodash-es/pickBy.js";
function tokenLabel(e) {
	return hasTokenLabel(e) ? e.LABEL : e.name;
}
function hasTokenLabel(e) {
	return isString_default(e.LABEL) && e.LABEL !== "";
}
var AbstractProduction = class {
	get definition() {
		return this._definition;
	}
	set definition(e) {
		this._definition = e;
	}
	constructor(e) {
		this._definition = e;
	}
	accept(e) {
		e.visit(this), forEach_default(this.definition, (y) => {
			y.accept(e);
		});
	}
}, NonTerminal = class extends AbstractProduction {
	constructor(y) {
		super([]), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
	set definition(e) {}
	get definition() {
		return this.referencedRule === void 0 ? [] : this.referencedRule.definition;
	}
	accept(e) {
		e.visit(this);
	}
}, Rule = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.orgText = "", assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, Alternative = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.ignoreAmbiguities = !1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, Option = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, RepetitionMandatory = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, RepetitionMandatoryWithSeparator = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, Repetition = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, RepetitionWithSeparator = class extends AbstractProduction {
	constructor(y) {
		super(y.definition), this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, Alternation = class extends AbstractProduction {
	get definition() {
		return this._definition;
	}
	set definition(e) {
		this._definition = e;
	}
	constructor(y) {
		super(y.definition), this.idx = 1, this.ignoreAmbiguities = !1, this.hasPredicates = !1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
}, Terminal = class {
	constructor(y) {
		this.idx = 1, assign_default(this, pickBy_default(y, (e) => e !== void 0));
	}
	accept(e) {
		e.visit(this);
	}
};
function serializeGrammar(e) {
	return map_default(e, serializeProduction);
}
function serializeProduction(e) {
	function y(e) {
		return map_default(e, serializeProduction);
	}
	/* istanbul ignore else */
	if (e instanceof NonTerminal) {
		let y = {
			type: "NonTerminal",
			name: e.nonTerminalName,
			idx: e.idx
		};
		return isString_default(e.label) && (y.label = e.label), y;
	} else if (e instanceof Alternative) return {
		type: "Alternative",
		definition: y(e.definition)
	};
	else if (e instanceof Option) return {
		type: "Option",
		idx: e.idx,
		definition: y(e.definition)
	};
	else if (e instanceof RepetitionMandatory) return {
		type: "RepetitionMandatory",
		idx: e.idx,
		definition: y(e.definition)
	};
	else if (e instanceof RepetitionMandatoryWithSeparator) return {
		type: "RepetitionMandatoryWithSeparator",
		idx: e.idx,
		separator: serializeProduction(new Terminal({ terminalType: e.separator })),
		definition: y(e.definition)
	};
	else if (e instanceof RepetitionWithSeparator) return {
		type: "RepetitionWithSeparator",
		idx: e.idx,
		separator: serializeProduction(new Terminal({ terminalType: e.separator })),
		definition: y(e.definition)
	};
	else if (e instanceof Repetition) return {
		type: "Repetition",
		idx: e.idx,
		definition: y(e.definition)
	};
	else if (e instanceof Alternation) return {
		type: "Alternation",
		idx: e.idx,
		definition: y(e.definition)
	};
	else if (e instanceof Terminal) {
		let y = {
			type: "Terminal",
			name: e.terminalType.name,
			label: tokenLabel(e.terminalType),
			idx: e.idx
		};
		isString_default(e.label) && (y.terminalLabel = e.label);
		let b = e.terminalType.PATTERN;
		return e.terminalType.PATTERN && (y.pattern = isRegExp_default(b) ? b.source : b), y;
	} else if (e instanceof Rule) return {
		type: "Rule",
		name: e.name,
		orgText: e.orgText,
		definition: y(e.definition)
	};
	else throw Error("non exhaustive match");
}
export { AbstractProduction, Alternation, Alternative, NonTerminal, Option, Repetition, RepetitionMandatory, RepetitionMandatoryWithSeparator, RepetitionWithSeparator, Rule, Terminal, serializeGrammar, serializeProduction };
