Files
infocom-systems-design/node_modules/@chevrotain/gast/lib/src/model.js
2025-10-03 22:27:28 +03:00

225 lines
6.6 KiB
JavaScript

import { assign, forEach, isRegExp, isString, map, pickBy } from "lodash-es";
// TODO: duplicated code to avoid extracting another sub-package -- how to avoid?
function tokenLabel(tokType) {
if (hasTokenLabel(tokType)) {
return tokType.LABEL;
}
else {
return tokType.name;
}
}
// TODO: duplicated code to avoid extracting another sub-package -- how to avoid?
function hasTokenLabel(obj) {
return isString(obj.LABEL) && obj.LABEL !== "";
}
export class AbstractProduction {
get definition() {
return this._definition;
}
set definition(value) {
this._definition = value;
}
constructor(_definition) {
this._definition = _definition;
}
accept(visitor) {
visitor.visit(this);
forEach(this.definition, (prod) => {
prod.accept(visitor);
});
}
}
export class NonTerminal extends AbstractProduction {
constructor(options) {
super([]);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
set definition(definition) {
// immutable
}
get definition() {
if (this.referencedRule !== undefined) {
return this.referencedRule.definition;
}
return [];
}
accept(visitor) {
visitor.visit(this);
// don't visit children of a reference, we will get cyclic infinite loops if we do so
}
}
export class Rule extends AbstractProduction {
constructor(options) {
super(options.definition);
this.orgText = "";
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class Alternative extends AbstractProduction {
constructor(options) {
super(options.definition);
this.ignoreAmbiguities = false;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class Option extends AbstractProduction {
constructor(options) {
super(options.definition);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class RepetitionMandatory extends AbstractProduction {
constructor(options) {
super(options.definition);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class RepetitionMandatoryWithSeparator extends AbstractProduction {
constructor(options) {
super(options.definition);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class Repetition extends AbstractProduction {
constructor(options) {
super(options.definition);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class RepetitionWithSeparator extends AbstractProduction {
constructor(options) {
super(options.definition);
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class Alternation extends AbstractProduction {
get definition() {
return this._definition;
}
set definition(value) {
this._definition = value;
}
constructor(options) {
super(options.definition);
this.idx = 1;
this.ignoreAmbiguities = false;
this.hasPredicates = false;
assign(this, pickBy(options, (v) => v !== undefined));
}
}
export class Terminal {
constructor(options) {
this.idx = 1;
assign(this, pickBy(options, (v) => v !== undefined));
}
accept(visitor) {
visitor.visit(this);
}
}
export function serializeGrammar(topRules) {
return map(topRules, serializeProduction);
}
export function serializeProduction(node) {
function convertDefinition(definition) {
return map(definition, serializeProduction);
}
/* istanbul ignore else */
if (node instanceof NonTerminal) {
const serializedNonTerminal = {
type: "NonTerminal",
name: node.nonTerminalName,
idx: node.idx,
};
if (isString(node.label)) {
serializedNonTerminal.label = node.label;
}
return serializedNonTerminal;
}
else if (node instanceof Alternative) {
return {
type: "Alternative",
definition: convertDefinition(node.definition),
};
}
else if (node instanceof Option) {
return {
type: "Option",
idx: node.idx,
definition: convertDefinition(node.definition),
};
}
else if (node instanceof RepetitionMandatory) {
return {
type: "RepetitionMandatory",
idx: node.idx,
definition: convertDefinition(node.definition),
};
}
else if (node instanceof RepetitionMandatoryWithSeparator) {
return {
type: "RepetitionMandatoryWithSeparator",
idx: node.idx,
separator: (serializeProduction(new Terminal({ terminalType: node.separator }))),
definition: convertDefinition(node.definition),
};
}
else if (node instanceof RepetitionWithSeparator) {
return {
type: "RepetitionWithSeparator",
idx: node.idx,
separator: (serializeProduction(new Terminal({ terminalType: node.separator }))),
definition: convertDefinition(node.definition),
};
}
else if (node instanceof Repetition) {
return {
type: "Repetition",
idx: node.idx,
definition: convertDefinition(node.definition),
};
}
else if (node instanceof Alternation) {
return {
type: "Alternation",
idx: node.idx,
definition: convertDefinition(node.definition),
};
}
else if (node instanceof Terminal) {
const serializedTerminal = {
type: "Terminal",
name: node.terminalType.name,
label: tokenLabel(node.terminalType),
idx: node.idx,
};
if (isString(node.label)) {
serializedTerminal.terminalLabel = node.label;
}
const pattern = node.terminalType.PATTERN;
if (node.terminalType.PATTERN) {
serializedTerminal.pattern = isRegExp(pattern)
? pattern.source
: pattern;
}
return serializedTerminal;
}
else if (node instanceof Rule) {
return {
type: "Rule",
name: node.name,
orgText: node.orgText,
definition: convertDefinition(node.definition),
};
/* c8 ignore next 3 */
}
else {
throw Error("non exhaustive match");
}
}
//# sourceMappingURL=model.js.map