UNPKG

rhombic

Version:

SQL parsing, lineage extraction and manipulation

147 lines 6.56 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateDefinitionTypes = exports.generateContextTypes = void 0; const fs_1 = require("fs"); const chalk_1 = __importDefault(require("chalk")); const path_1 = require("path"); const case_1 = require("case"); const isEmpty_1 = __importDefault(require("lodash/isEmpty")); const alternationLink = `}) & {`; /** * Script to generate context types from the grammar. * * Result: * `src/Context.ts` */ function generateContextTypes(grammar) { let types = `// Auto-generated by generateContextTypes.ts import { IToken } from "chevrotain"; `; const IContext = []; // Improve the type safety with our own types, `RuleNode[]` is a better version of `ISerializedGast[]` grammar.forEach(rule => { const def = generateDefinitionTypes(rule.definition); IContext.push(`${case_1.pascal(rule.name)}Context`); types += def.includes("|") ? `\nexport type ${case_1.pascal(rule.name)}Context = \n ${def.includes(alternationLink) ? "(" : ""} | {\n` : `\nexport interface ${case_1.pascal(rule.name)}Context {`; types += def; types += "\n}\n\n"; }); types += `export type IContext = ${IContext.join(" | ")}\n`; fs_1.writeFileSync(path_1.join(__dirname, "../Context.ts"), types); console.log(chalk_1.default.green("✔") + " context types generated!"); } exports.generateContextTypes = generateContextTypes; function generateDefinitionTypes(definition, options) { const { indent, optional, keys } = Object.assign({ keys: [], indent: 2, optional: false }, options); return definition.reduce(({ output, isAfterAlternation }, node) => { // Avoid the next node to be inside the Alternation union if (isAfterAlternation && output.includes("} | {")) { output += alternationLink; } switch (node.type) { case "Terminal": if (keys.includes(node.name)) { if (!optional) { // Remove optional from definition return { output: output.replace(`${node.name}?: IToken[];`, `${node.name}: IToken[];`), isAfterAlternation: false }; } return { output, isAfterAlternation: false }; } keys.push(node.name); return { output: `${output}\n${" ".repeat(indent)}${node.name}${optional ? "?" : ""}: IToken[];`, isAfterAlternation: false }; case "NonTerminal": if (keys.includes(node.name)) return { output, isAfterAlternation: false }; keys.push(node.name); return { output: `${output}\n${" ".repeat(indent)}${node.name}${optional ? "?" : ""}: Array<{\n${" ".repeat(indent + 2)}name: "${node.name}";\n${" ".repeat(indent + 2)}children: ${case_1.pascal(node.name)}Context;\n${" ".repeat(indent)}}>;`, isAfterAlternation: false }; case "Option": return { output: output + generateDefinitionTypes(node.definition, { indent, optional: true, keys }), isAfterAlternation: false }; case "RepetitionMandatoryWithSeparator": return { output: output + generateDefinitionTypes(node.definition, { indent: indent + 2, keys }) + generateDefinitionTypes([node.separator], { indent: indent + 2, optional: true, keys }), isAfterAlternation: false }; case "Repetition": return { output: output + generateDefinitionTypes(node.definition, { indent: indent + 2, optional: true, keys }), isAfterAlternation: false }; case "Alternation": { const isTerminalOnly = !JSON.stringify(node.definition).includes("NonTerminal"); const entries = new Set(); return { output: output + "\n" + (isTerminalOnly ? node.definition .map(i => generateDefinitionTypes(i.definition, { indent: 0, optional: true, keys })) .join("") .split("\n") .filter((j) => { const isAlreadyDefined = entries.has(j); if (!j.includes("}>;")) { entries.add(j); } return !isEmpty_1.default(j) && !isAlreadyDefined; }) .join("\n") : node.definition .map(i => generateDefinitionTypes(i.definition, { indent: 0 }).replace("\n", "")) .join("} | {")), isAfterAlternation: true }; } case "Flat": return { output: output + generateDefinitionTypes(node.definition).replace(/[\n;]/g, ""), isAfterAlternation: false }; default: return { output, isAfterAlternation: false }; } }, { output: "", isAfterAlternation: false }).output; } exports.generateDefinitionTypes = generateDefinitionTypes; //# sourceMappingURL=generateContextTypes.js.map