UNPKG

@allgemein/expressions

Version:
303 lines 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExpressionInterpreter = void 0; const LikeDesc_1 = require("../descriptors/LikeDesc"); const LtDesc_1 = require("../descriptors/LtDesc"); const GtDesc_1 = require("../descriptors/GtDesc"); const InDesc_1 = require("../descriptors/InDesc"); const NeqDesc_1 = require("../descriptors/NeqDesc"); const EqDesc_1 = require("../descriptors/EqDesc"); const LeDesc_1 = require("../descriptors/LeDesc"); const KeyDesc_1 = require("../descriptors/KeyDesc"); const ValueDesc_1 = require("../descriptors/ValueDesc"); const GeDesc_1 = require("../descriptors/GeDesc"); const GroupDesc_1 = require("../descriptors/GroupDesc"); const AndDesc_1 = require("../descriptors/AndDesc"); const OrDesc_1 = require("../descriptors/OrDesc"); const lodash_1 = require("lodash"); class ExpressionInterpreter { constructor() { //rootEntityDef:EntityDef; this.groupLevel = 0; this.ops = [ { name: 'visitGroup', regex: /\(/, method: this.visitGroup, after: [null, 'visitGroup', 'onBool'] }, { name: 'leaveGroup', regex: /\)/, method: this.leaveGroup, condition: () => { return this.groupLevel > 0; }, after: ['onValue', 'leaveGroup'] }, { name: 'onKey', regex: /('[^']+')|("[^"]+")|(\w|\.|\d)+/, method: this.onKey, skipIndex: 3, after: [null, 'visitGroup', 'onBool'] }, { name: 'onBool', regex: / (and|AND|or|OR) /, method: this.onBool, skipIndex: 1, after: ['leaveGroup', 'onValue'] }, { name: 'onOperator', regex: /(>=|<=|<>|>|<|=| in | IN | like | LIKE )/, method: this.onOperator, skipIndex: 1, after: ['onKey'] }, { name: 'onValue', regex: /('[^']*')|("[^"]*")|\d+|\d+.\d+|(\(((('[^']*')|("[^"]*")|\d+|\d+.\d+)\s*,?\s*)+\))/, method: this.onValue, skipIndex: 7, after: ['onOperator'] }, ]; this.res = []; this.queue = []; //this.rootEntityDef = entityDef; } interprete(str) { this.fragmentize(str); return (0, lodash_1.first)(this.res); } fragmentize(str) { let lastState = (0, lodash_1.last)(this.queue); let currentOps = this.ops.filter(x => { let _true = true; if (x.condition) { _true = x.condition(); } if ((0, lodash_1.isEmpty)(x.after)) { return _true; } if (!lastState) { return _true && x.after.indexOf(null) > -1; } else { return _true && x.after.indexOf(lastState.state) > -1; } }); //console.log(currentOps.map(x => x.name)); let inc = 0; let map = {}; currentOps.map((x, index) => { map[inc] = index; inc = x.skipIndex ? inc + x.skipIndex : inc + 1; }); const regex = new RegExp('^\\s*' + currentOps.map(x => '(' + x.regex.source + ')').join('|'), 'gim'); let arr = regex.exec(str); if (arr) { // let index = arr.findIndex(x => !isUndefined(x)); let index = (0, lodash_1.findIndex)(arr, x => !(0, lodash_1.isUndefined)(x), 1) - 1; if (index > -1) { let opId = map[index]; let op = currentOps[opId]; // console.log(map, regex, arr, regex.lastIndex,op.name); op.method.apply(this, [arr[index + 1], str]); const nextStr = str.substring(regex.lastIndex); if (!(0, lodash_1.isEmpty)(nextStr)) { this.fragmentize(nextStr); } } else { throw new Error('no match found at "' + JSON.stringify(arr) + '"'); } } else { throw new Error('nothing found at "' + str + '" with regex ' + regex.source); } } /* escape(x: string) { const specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ]; const regex = new RegExp('(\\' + specials.join('|\\') + ')', 'gim'); return x.replace(regex, '\\$1'); } */ onKey(match, str) { let key = match.replace(/^('|")|('|")$/g, ''); this.queue.push({ group: this.groupLevel, value: key, state: 'onKey' }); } onOperator(match, str) { this.queue.push({ group: this.groupLevel, value: match, state: 'onOperator' }); } onValue(match, str) { let value; if (/^('|")|('|")$/.test(match)) { value = match.replace(/^('|")|('|")$/g, ''); } else if (/^\d+$/.test(match)) { value = parseInt(match); } else if (/^\d+\.\d+$/.test(match)) { value = parseFloat(match); } else if (/^\(.*\)$/.test(match)) { value = match.replace(/^\(|\)$/g, '').split(',').map(x => x.trim()) .map(x => { let value2 = x; if (/^('|")|('|")$/.test(x)) { value2 = x.replace(/^('|")|('|")$/g, ''); } else if (/^\d+$/.test(x)) { value2 = parseInt(x); } else if (/^\d+\.\d+$/.test(x)) { value2 = parseFloat(x); } return value2; }); } let op = this.queue.pop(); let key = this.queue.pop(); let erg; if (op.state == 'onOperator' && key && key.state == 'onKey') { switch (op.value.trim().toLowerCase()) { case '=': erg = (0, EqDesc_1.Eq)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case 'like': erg = (0, LikeDesc_1.Like)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case '<=': erg = (0, LeDesc_1.Le)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case '>=': erg = (0, GeDesc_1.Ge)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case '<': erg = (0, LtDesc_1.Lt)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case '>': erg = (0, GtDesc_1.Gt)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case 'in': erg = (0, InDesc_1.In)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; case '<>': erg = (0, NeqDesc_1.Neq)((0, KeyDesc_1.Key)(key.value), (0, ValueDesc_1.Value)(value)); break; default: throw new Error('operator not found'); } } else { throw new Error('operator not found'); } this.queue.push({ group: this.groupLevel, value: value, state: 'onValue', op: op, key: key, desc: erg }); let res = (0, lodash_1.last)(this.res); if (res instanceof GroupDesc_1.GroupDesc) { res.values.push(erg); } else { this.res.push(erg); } } visitGroup() { this.groupLevel++; let groupDesc = new GroupDesc_1.GroupDesc(); groupDesc.id = this.groupLevel; this.res.push(groupDesc); this.queue.push({ group: this.groupLevel, desc: groupDesc, state: 'visitGroup' }); } leaveGroup() { let group = this.res.find(g => g instanceof GroupDesc_1.GroupDesc ? g.id == this.groupLevel : false); if (group && group.type == 'group') { (0, lodash_1.remove)(this.res, g => g instanceof GroupDesc_1.GroupDesc ? g.id == this.groupLevel : false); // embedded withotu bool let prevGid = this.groupLevel - 1; let prevGroup = this.res.find(g => g instanceof GroupDesc_1.GroupDesc ? g.id == prevGid : false); if (prevGroup) { group.values.forEach((v) => prevGroup.values.push(v)); group.values = []; } else { throw new Error('cant find previous group to move values to ... '); } } this.queue.push({ group: this.groupLevel, state: 'leaveGroup', desc: group }); //this. this.groupLevel--; } onBool(match) { let bool = match.trim().toLocaleUpperCase(); let last = this.res.pop(); let group; if (last instanceof GroupDesc_1.GroupDesc && last.id == this.groupLevel && last.type.toLowerCase() == bool.toLowerCase()) { // DO NOTTING group = last; this.res.push(group); } else if (last instanceof GroupDesc_1.GroupDesc && last.type == 'group') { // undefined switch (bool) { case 'AND': group = (0, AndDesc_1.And)(...last.values); break; case 'OR': group = (0, OrDesc_1.Or)(...last.values); break; } group.id = this.groupLevel; this.res.push(group); } else { switch (bool) { case 'AND': group = (0, AndDesc_1.And)(last); break; case 'OR': group = (0, OrDesc_1.Or)(last); break; } group.id = this.groupLevel; this.res.push(group); } this.queue.push({ group: this.groupLevel, value: match.trim().toLocaleUpperCase(), state: 'onBool', desc: group }); } } exports.ExpressionInterpreter = ExpressionInterpreter; //# sourceMappingURL=ExpressionInterpreter.js.map