/** * Created by Aleksey Chichenkov on 1/28/19. */ var fs = require("fs"); var Lexer = require('./test_lexer.js'); var std = (function () { var protos = "__protos__"; var keys = "__keys__"; /** * Return unique data * * @param {Object[]} _arr - prototypes of inheritance classes * @param {Object} _main - prototype of resulting class * * @return {Object} * */ var unique = function (_arr, _main) { var result = Object.create(null); var to_remove = []; for (var i = 0, e = _arr.length; i != e; ++i) { var item = _arr[i]; for (var key in item) { if (key in result) { to_remove.push(key); continue; } result[key] = item[key]; } if (keys in item) { for (var ii = 0, ee = item[keys].length; ii != ee; ++ii) { var key = item[keys][ii]; if (key in result) { to_remove.push(key); continue; } result[key] = item[key]; } } } for (var i = 0; i != to_remove.length; ++i) { delete result[to_remove[i]]; } for (var key in _main) { result[key] = _main[key]; } return result; }; /** * Create OOP class * * @param {Function[]} _constrs - inheritance classes * @param {Object} _proto - prototype of resulting class * @param {Object?} _static - static data * * @return {Function} * */ var class_creator = function (_constrs, _proto, _static) { _constrs = _constrs || []; _proto = _proto || []; _static = _static || []; var constr; if (_proto && _proto.hasOwnProperty("constructor")) { constr = _proto.constructor; delete _proto.constructor; } else { constr = function () { for (var i = 0; i != _constrs.length; ++i) { _constrs[i].apply(this, arguments); } }; } var proto = Object.create(null); Object.defineProperty(proto, protos, { "value": [] }); Object.defineProperty(proto, keys, { "value": [] }); /************************FOR MEMBERS*******************************/ for (var i = 0, e = _constrs.length; i != e; ++i) { proto[protos].push(_constrs[i].prototype); } var m_un = unique(proto[protos], _proto); for (var key in m_un) { proto[keys].push(key); Object.defineProperty(proto, key, { "value": m_un[key] }); } /************************FOR MEMBERS END***************************/ /************************FOR STATICS*******************************/ var s_un = unique(_constrs, _static); for (var key in s_un) { Object.defineProperty(constr, key, { "value": s_un[key], "enumerable": true }); } /************************FOR STATICS END***************************/ Object.defineProperties(constr, { "pr": { "value": proto }, "prototype": { "value": proto } }); Object.freeze(proto); Object.freeze(constr); return constr; }; /** * Check if target has prototype * * @param {Object} _target - checkable instance * @param {Object} _proto - posible prototype * * */ var check = function (_target, _proto) { for (var i = 0; i != _target[protos].length; ++i) { var t_proto = _target[protos][i]; if (t_proto == _proto) { return true; } if (t_proto[protos]) { if (check(t_proto, _proto)) return true; } } return false; }; /** * Check if target is instance of class * * @param {Object} _target - checkable instance * @param {Function} _constr - posible constructor * * */ var class_check = function (_target, _constr) { if (_target instanceof _constr) { return true; } return check(_target, _constr.prototype); }; return { class: class_creator, class_check: class_check }; })(); var tools = { merge: function (_obj) { var target = Object.create(null); var i = 0, e = arguments.length; for (; i != e; ++i) { var options = arguments[i]; for (var key in options) { if (options[key] === undefined && target === options[key]) continue; target[key] = options[key]; } } return target; } }; var tokens = (function () { var Node = std.class([], { constructor: function Node(_options) { var base = tools.merge({ children: [] }, _options); this.children = base.children; }, add: function (_n) { this.children.push(_n); return this; } }); var Lexeme = std.class([Node], { constructor: function Lexeme(_options) { var base = tools.merge({ start: -1, end: -1, type: null, value: null }, _options); Node.call(this, base); this.start = base.start; this.end = base.end; this.type = base.type; this.value = base.value; } }); var Rule = std.class([Node], { constructor: function NonTerminal(_options) { var base = tools.merge({}, _options); Node.call(this, base); } }); var terminal_literal = std.class([Rule], { constructor: function terminal_literal(_options) { var base = tools.merge({}, _options); Rule.call(this, base); }, position: function () { var first_child = this.children[0]; return { start: first_child.start, end: first_child.end, } } }); var string_literal = std.class([terminal_literal], { constructor: function string_literal(_options) { var base = tools.merge({}, _options); terminal_literal.call(this, base); } }); var integer_literal = std.class([terminal_literal], { constructor: function integer_literal(_options) { var base = tools.merge({}, _options); terminal_literal.call(this, base); } }); var float_literal = std.class([terminal_literal], { constructor: function float_literal(_options) { var base = tools.merge({}, _options); terminal_literal.call(this, base); } }); var bool_literal = std.class([terminal_literal], { constructor: function bool_literal(_options) { var base = tools.merge({}, _options); terminal_literal.call(this, base); } }); var id = std.class([Rule], { constructor: function id(_options) { var base = tools.merge({}, _options); Rule.call(this, base); }, position: function () { var first_child = this.children[0]; if(std.class_check(first_child, Lexeme)){ return { start: first_child.start, end: first_child.end, } } else { return this.position(); } } }); var expr_compares = std.class([Rule], { constructor: function expr_compares(_options) { var base = tools.merge({ lexpr: null, op: null, rexpr: null }, _options); Rule.call(this, base); this.lexpr = base.lexpr; this.op = base.op; this.rexpr = base.rexpr; }, position: function () { return { start: this.lexpr.position().start, end: this.rexpr.position().end, } } }); var and = std.class([Rule], { constructor: function and(_options) { var base = tools.merge({}, _options); expr_compares.call(this, base); } }); var or = std.class([Rule], { constructor: function or(_options) { var base = tools.merge({}, _options); expr_compares.call(this, base); } }); var not = std.class([Rule], { constructor: function not(_options) { var base = tools.merge({ op: null, rexpr: null }, _options); Rule.call(this, base); this.op = base.op; this.rexpr = base.rexpr; }, position: function () { return { start: this.op.start, end: this.rexpr.position().end, } } }); var endpoint_compares = std.class([Rule], { constructor: function endpoint_compares(_options) { var base = tools.merge({ id: null, op: null, literal: null }, _options); Rule.call(this, base); this.id = base.id; this.op = base.op; this.literal = base.literal; }, position: function () { return { start: this.id.start, end: this.literal.end } } }); var eq = std.class([endpoint_compares], { constructor: function eq(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); }, }); var neq = std.class([endpoint_compares], { constructor: function neq(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); }, }); var gt = std.class([endpoint_compares], { constructor: function gt(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var gte = std.class([endpoint_compares], { constructor: function gte(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var lt = std.class([endpoint_compares], { constructor: function lt(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var lte = std.class([endpoint_compares], { constructor: function lte(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var like = std.class([endpoint_compares], { constructor: function like(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var nlike = std.class([endpoint_compares], { constructor: function nlike(_options) { var base = tools.merge({}, _options); endpoint_compares.call(this, base); } }); var sub_expr = std.class([Rule], { constructor: function expr(_options) { var base = tools.merge({ LCB: null, expr: null, RCB: null, }, _options); Rule.call(this, base); this.LCB = base.LCB; this.expr = base.expr; this.RCB = base.RCB; }, position: function () { return { start: this.LCB.start, end: this.RCB.end } } }); var address_literal_content = std.class([Rule], { constructor: function address_literal_content(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); var address_literal = std.class([Rule], { constructor: function address_literal(_options) { var base = tools.merge({ keyword: null, LSB: null, RSB: null, }, _options); Rule.call(this, base); this.keyword = base.keyword; this.LSB = base.LSB; this.RSB = base.RSB; }, position: function () { return { start: this.keyword.start, end: this.RSB.end } } }); var oid_literal = std.class([Rule], { constructor: function oid_literal(_options) { var base = tools.merge({ keyword: null, LSB: null, RSB: null, }, _options); Rule.call(this, base); this.keyword = base.keyword; this.LSB = base.LSB; this.RSB = base.RSB; }, position: function () { var first_child = this.children[0]; return { start: first_child.start, end: first_child.end } } }); var time_diff_literal = std.class([Rule], { constructor: function time_diff_literal(_options) { var base = tools.merge({ keyword: null, LSB: null, RSB: null, days: -1, hours: -1, minutes: -1, seconds: -1, microseconds: -1 }, _options); Rule.call(this, base); this.keyword = base.keyword; this.LSB = base.LSB; this.RSB = base.RSB; this.days = base.days; this.hours = base.hours; this.minutes = base.minutes; this.seconds = base.seconds; this.microseconds = base.microseconds; }, position: function () { return { start: this.keyword.start, end: this.RSB.end } } }); var time_literal = std.class([Rule], { constructor: function time_literal(_options) { var base = tools.merge({ keyword: null, LSB: null, RSB: null, day: -1, month: -1, year: -1, hours: -1, minutes: -1, seconds: -1, microseconds: -1 }, _options); Rule.call(this, base); this.keyword = base.keyword; this.LSB = base.LSB; this.RSB = base.RSB; this.day = base.day; this.month = base.month; this.year = base.year; this.hours = base.hours; this.minutes = base.minutes; this.seconds = base.seconds; this.microseconds = base.microseconds; }, position: function () { return { start: this.keyword.start, end: this.RSB.end } } }); return { // terminal LEXEME: Lexeme, // not terminal id: id, string_literal: string_literal, integer_literal: integer_literal, float_literal: float_literal, bool_literal: bool_literal, address_literal: address_literal, oid_literal: oid_literal, time_diff_literal: time_diff_literal, time_literal: time_literal, or: or, and: and, not: not, eq: eq, neq: neq, gt: gt, gte: gte, lt: lt, lte: lte, like: like, nlike: nlike, // expr: expr, sub_expr: sub_expr, address_literal_content: address_literal_content } })();