UNPKG

swift-pattern-compiler

Version:

A compiler which transforms SWIFT patterns to an object representation with additional information's.

235 lines 7.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const interfaces_1 = require("./interfaces"); /** * The object generator takes an ast object and returns a swift object. * * ``` * const ast { * type: "SwiftPattern", * body: [ * { * type: "line", * nodes: [ * { * type: "field", * length: { min: 0, max: 35 }, * char: "a" * }, * ] * } * ] * }; * objectGenerator(ast); * { * linesCount: 1, * lines: [ * { * minChars: 0, * maxChars: 35, * regExp: "[A-Z]{0,35}", * allowedCharsClass: "[A-Z]", * }, * ], * maxChars: 35, * regExp: "[A-Z]{0,35}", * allowedCharsClass: "[A-Z]", * } * ``` */ exports.generator = (ast) => { const swiftObj = { linesCount: 0, lines: [], minChars: 0, maxChars: 0, regExp: "", allowedCharsClass: "", }; ast = ast || { type: "null", body: null }; if (ast.type === "SwiftPattern") { return ast.body.reduce(generate, swiftObj); } throw new Error(`Unsupported AST type "${ast.type}"`); }; /** * Generates a swiftObject by processing the nodeLine. * @param swiftObject * @param nodeLine */ const generate = (swiftObject, nodeLine) => { // tslint:disable-next-line:max-line-length const line = nodeLine.nodes.reduce(generateLine, getEmptySwiftLineObject()); swiftObject.lines.push(line); let newline = "\n"; let rAllowedCharsClass = swiftObject.allowedCharsClass; if (rAllowedCharsClass) { rAllowedCharsClass = combineCharClasses(rAllowedCharsClass, newline); } let lRegExp = line.regExp; if (nodeLine.optional) { lRegExp = `(${lRegExp})?`; newline += "?"; } const rRegExp = swiftObject.regExp; return { linesCount: swiftObject.linesCount + 1, minChars: swiftObject.minChars + line.minChars, maxChars: swiftObject.maxChars + line.maxChars, regExp: rRegExp ? rRegExp + newline + lRegExp : lRegExp, allowedCharsClass: combineCharClasses(rAllowedCharsClass, line.allowedCharsClass), lines: swiftObject.lines, }; }; /** * Generates a line swiftLineObject with the passed lineNode. * @param result * @param node */ const generateLine = (result, node) => { switch (node.type) { case interfaces_1.ENodeType.field: return addField(result, node); case interfaces_1.ENodeType.sign: return addSign(result, node); case interfaces_1.ENodeType.optional: return addOptional(result, node); case interfaces_1.ENodeType.block: return addBlock(result, node); default: throw new Error(`Unsupported node type "${node.type}"`); } }; /** * Returns a new swiftLineObject with the added field values. * @param swiftLineObject * @param field */ const addField = ({ minChars, maxChars, regExp, allowedCharsClass }, field) => { const { char, length: { min, max } } = field; const quantifier = exports.getQuantifier(min, max); const charClass = exports.getCharClass(char); if (charClass === "") { throw new Error(`Unsupported character "${char}" in field`); } return { minChars: minChars + min, maxChars: maxChars + max, regExp: regExp + charClass + quantifier, allowedCharsClass: combineCharClasses(allowedCharsClass, charClass), }; }; /** * Returns a new swiftLineObject with the added sign values. * @param swiftLineObject * @param field */ const addSign = ({ minChars, maxChars, regExp, allowedCharsClass }, { char }) => { return { minChars: minChars + 1, maxChars: maxChars + 1, regExp: regExp + char, allowedCharsClass: combineCharClasses(allowedCharsClass, char), }; }; /** * Returns a new swiftLineObject with the added optional values. * @param swiftLineObject * @param optional */ const addOptional = ({ minChars: sloMinChars, maxChars: sloMaxChars, regExp: sloRegExp, allowedCharsClass: sloAllowedCharsClass, }, { nodes: optionalNodes }) => { const { maxChars, regExp, allowedCharsClass, } = optionalNodes.reduce(generateLine, getEmptySwiftLineObject()); return { minChars: sloMinChars, maxChars: sloMaxChars + maxChars, regExp: sloRegExp + `(${regExp})?`, allowedCharsClass: combineCharClasses(sloAllowedCharsClass, allowedCharsClass), }; }; /** * Returns a new swiftLineObject with the added block values. * @param swiftLineObject * @param block */ const addBlock = ({ minChars: sloMinChars, maxChars: sloMaxChars, regExp: sloRegExp, allowedCharsClass: sloAllowedCharsClass, }, { nodes: blockNodes }) => { const { minChars, maxChars, regExp, allowedCharsClass, } = blockNodes.reduce(generateLine, getEmptySwiftLineObject()); return { minChars: sloMinChars + minChars, maxChars: sloMaxChars + maxChars, regExp: sloRegExp + `(${regExp})`, allowedCharsClass: combineCharClasses(sloAllowedCharsClass, allowedCharsClass), }; }; /** * Returns an emtpy ISwiftLineObject. */ const getEmptySwiftLineObject = () => { return { minChars: 0, maxChars: 0, regExp: "", allowedCharsClass: "", }; }; /** * Contains all available char classes of a SWIFT pattern. */ const charClasses = { a: `[A-Z]`, c: `[A-Z0-9]`, d: `[0-9,]`, e: `[ ]`, h: `[A-F0-9]`, // digits only n: `[0-9]`, // SWIFT Character Set (X Character Set) x: `[A-Za-z0-9\\/\\-\\?\\:\\(\\)\\.\\,\\'\\+\n ]`, // EDIFACT Level A Character Set(Y Character Set) y: `[A-Z0-9\\.\\,\\-\\(\\)\\/\\=\\'\\+\\:\\?\\!\\"\\%\\&\\*\\<\\>\\; ]`, // Information Service Character Set (Z Character Set) // tslint:disable-next-line:max-line-length z: `[A-Za-z0-9\\.\\,\\-\\(\\)\\/\\=\\'\\+\\:\\?\\!\\"\\%\\&\\*\\<\\>\\;\\{\\@\\#\\_\n ]`, }; /** * Returns the char class for the passed char or an empty string * for an unsupported char. * @param char */ exports.getCharClass = (char) => { return charClasses[char] || ""; }; /** * Combines two char classes to one char class. * Duplicated values are not sorted out, but duplicate char classes are. * @param charClass1 * @param charClass2 */ const combineCharClasses = (charClass1, charClass2) => { charClass1 = charClass1.replace(/\[|\]/g, ""); charClass2 = charClass2.replace(/\[|\]/g, ""); if (charClass1.includes(charClass2)) { return `[${charClass1}]`; } else if (charClass2.includes(charClass1)) { return `[${charClass2}]`; } return `[${charClass1}${charClass2}]`; }; /** * Returns a quantifier string for the passed min, max values. * @param min * @param max */ exports.getQuantifier = (min, max) => { if (max < min) { throw new Error(`Invalid quantifier, max "${max}" has to be equal or greater than min "${min}"`); } if (min === 1 && max === 1) { return ""; } if (min === 0 && max === 1) { return "?"; } return `{${min},${max}}`; }; //# sourceMappingURL=generator.js.map