UNPKG

rhombic

Version:

SQL parsing, lineage extraction and manipulation

139 lines 4.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatCst = exports.prettifyCst = void 0; const chevrotain_1 = require("chevrotain"); const isCstNode_1 = require("./isCstNode"); /** * Pretty output for cst for easy specifications * * @param cst */ function prettifyCst(cst) { let output = ""; Object.entries(cst).forEach(([_, elements]) => { elements.forEach((node, i, nodes) => { if (isCstNode_1.isCstNode(node)) { output += node.name + "(" + prettifyCst(node.children) + ")"; } else { if (i === 0 && node.tokenType) output += node.tokenType.tokenName; if (i === 0) output += "("; output += `"${node.image}"`; if (i === nodes.length - 1) output += ")"; else output += ","; } }); }); return output; } exports.prettifyCst = prettifyCst; /** * Indent the prettify version of the cst for more visibility * * @param cst output of `prettifyCst()` */ function formatCst(prettifiedCst) { const lexResult = PrettyCstLexer.tokenize(prettifiedCst); parser.input = lexResult.tokens; const cst = parser.node(); if (parser.errors.length + lexResult.errors.length > 0) { throw new Error(`PrettifyCst Error: \n - ${[...parser.errors.map(i => i.message), ...lexResult.errors.map(i => i.message)].join("\n - ")}`); } const visitor = new PrettyCstVisitor(); visitor.visit(cst); return visitor.output .split("\n") .filter(i => i) .join("\n"); } exports.formatCst = formatCst; // Lexer/Parser/Visitor to support `formatCst()` const Identifier = chevrotain_1.createToken({ name: "Identifier", pattern: /[a-zA-Z_]+/ }); const Value = chevrotain_1.createToken({ name: "Value", pattern: /((""[^"\\]*(?:\\.[^"\\]*)*(""))+)|(("[^"\\]*(?:\\.[^"\\]*)*("))+)/ }); const LParen = chevrotain_1.createToken({ name: "LParen", pattern: /\(/ }); const RParen = chevrotain_1.createToken({ name: "RParen", pattern: /\)/ }); const Comma = chevrotain_1.createToken({ name: "Comma", pattern: /,/ }); const WhiteSpace = chevrotain_1.createToken({ name: "WhiteSpace", pattern: /\s+/, group: chevrotain_1.Lexer.SKIPPED }); const allTokens = [WhiteSpace, Identifier, Value, LParen, RParen, Comma]; const PrettyCstLexer = new chevrotain_1.Lexer(allTokens, { lineTerminatorCharacters: ["\n"] }); class PrettyCstParser extends chevrotain_1.CstParser { constructor() { super(allTokens); this.node = this.RULE("node", () => { this.CONSUME(Identifier); this.CONSUME(LParen); this.OR([ { ALT: () => { // Should be `AT_LEAST_ONE_SEP` but strange error with chevrotain… // this.AT_LEAST_ONE_SEP({ // DEF: () => this.CONSUME(Value), // SEP: Comma // }); this.CONSUME(Value); this.OPTION(() => { this.CONSUME(Comma); this.CONSUME1(Value); }); this.OPTION1(() => { this.CONSUME1(Comma); this.CONSUME2(Value); }); this.OPTION2(() => { this.CONSUME2(Comma); this.CONSUME3(Value); }); this.OPTION3(() => { this.CONSUME3(Comma); this.CONSUME4(Value); }); } }, { ALT: () => this.AT_LEAST_ONE(() => this.SUBRULE(this.node)) } ]); this.CONSUME(RParen); }); this.performSelfAnalysis(); } } const parser = new PrettyCstParser(); const Visitor = parser.getBaseCstVisitorConstructorWithDefaults(); class PrettyCstVisitor extends Visitor { constructor() { super(); this.output = ""; this.indent = ""; this.validateVisitor(); } node(ctx) { this.output += this.indent + ctx.Identifier[0].image + ctx.LParen[0].image; if (ctx.Value) { this.output += ctx.Value.map(v => v.image).join(", ") + ctx.RParen[0].image + "\n"; } else if (ctx.node) { this.output += "\n"; this.indent += " "; ctx.node.forEach(i => this.node(i.children)); this.output += "\n"; this.indent = this.indent.slice(0, -2); this.output += this.indent + ctx.RParen[0].image + "\n"; } } } //# sourceMappingURL=prettifyCst.js.map