/** * Created by Aleksey Chichenkov on 1/28/19. */ var fs = require("fs"); var Lexer = require('./lexer.js'); var tokens = (function () { 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 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 string_literal = std.class([Rule], { constructor: function string_literal(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); var integer_literal = std.class([Rule], { constructor: function integer_literal(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); var id = std.class([Rule], { constructor: function id(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); var literal = std.class([Rule], { constructor: function literal(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); var eq = std.class([Rule], { constructor: function eq(_options) { var base = tools.merge({ id: null, EQ: null, literal: null }, _options); Rule.call(this, base); this.id = base.id; this.EQ = base.EQ; this.literal = base.literal; }, set_id: function (_n) { this._id = _n; }, set_EQ: function (_n) { this._EQ = _n; }, set_literal: function (_n) { this._literal = _n; } }); var and = std.class([Rule], { constructor: function and(_options) { var base = tools.merge({ lexpr: null, AND: null, rexpr: null }, _options); Rule.call(this, base); this.lexpr = base.lexpr; this.AND = base.AND; this.rexpr = base.rexpr; }, set_lexpr: function (_n) { this._lexpr = _n; }, set_AND: function (_n) { this._AND = _n; }, set_rexpr: function (_n) { this._rexpr = _n; } }); var expr = std.class([Rule], { constructor: function expr(_options) { var base = tools.merge({}, _options); Rule.call(this, base); } }); return { // terminal LEXEME: Lexeme, // non terminal string_literal: string_literal, integer_literal: integer_literal, id: id, literal: literal, eq: eq, and: and, expr: expr, } })(); var _result = {}; var LemonJS = function (_input) { var parser = new Parser(); var lexer = new Lexer(_input); var token; while (token = lexer.next()) { console.log("PARSE", token.lexeme); parser.parse(parser["TOKEN_" + token.lexeme], token); } parser.parse(); return _result; }; fs.mkdirSync("tests"); var test_and = LemonJS("abc == 1 and abc1 == 2 and (bbc == 5)"); fs.writeFileSync("tests/out_test_and.json", JSON.stringify(test_and, true, 3)); var test_address = LemonJS('abc == Address ["a", "b", "c"]'); fs.writeFileSync("tests/out_tree_address.json", JSON.stringify(test_address, true, 3));