UNPKG

cbon

Version:
248 lines (247 loc) 9.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ast_1 = require("./ast"); const state_machine_1 = require("./state_machine"); const token_1 = require("./token"); const utils_1 = require("./utils"); const loop_1 = require("./loop"); const canceller_1 = require("./canceller"); function parser(code, config = { show_all_err: false, async: false, cancel: canceller_1.AlwaysFalse }) { var _a, _b, _c, _d, _e, _f; const cancel = (_b = (_a = config) === null || _a === void 0 ? void 0 : _a.cancel, (_b !== null && _b !== void 0 ? _b : canceller_1.AlwaysFalse)); const state = new state_machine_1.State((_d = (_c = config) === null || _c === void 0 ? void 0 : _c.show_all_err, (_d !== null && _d !== void 0 ? _d : false))); let rootAst; state.push(root(new state_machine_1.Context(state), (d) => { rootAst = d; })); let finish = false; const iter = utils_1.getIterator(code); function* main() { if (state.queue.length != 0) { state.queue.pop()(); return loop_1._continue; } if (finish) return loop_1._break; const c = yield iter.next(); if (c.done === true) { finish = true; return loop_1._continue; } state.call(c.value); } const loop = (_f = (_e = config) === null || _e === void 0 ? void 0 : _e.async, (_f !== null && _f !== void 0 ? _f : false)) ? async function () { while (true) { if (await cancel()) break; const g = main(); let y = g.next(); if (!y.done) { y = g.next(await y.value); } const s = y.value; if (s === loop_1._continue) { await utils_1.next_micro_tick(); continue; } if (s === loop_1._break) break; await utils_1.next_micro_tick(); } return state.errors.length !== 0 ? { err: state.errors, val: rootAst } : { err: state.errors, val: rootAst }; } : function () { while (true) { if (cancel()) break; const g = main(); let y = g.next(); if (!y.done) { y = g.next(y.value); } const s = y.value; if (s === loop_1._continue) continue; if (s === loop_1._break) break; } return state.errors.length !== 0 ? { err: state.errors, val: rootAst } : { err: state.errors, val: rootAst }; }; return loop(); } exports.parser = parser; function root(ctx, finish) { const items = []; return (t) => { if (t instanceof token_1.TEOF) { finish(new ast_1.Docs(items)); } else if (t instanceof token_1.TSObjStart) { return ctx.callNoFirst(block, t, b => items.push(b)); } else if (t instanceof token_1.TSArrStart) { return ctx.callNoFirst(arr, t, a => items.push(a)); } else if (t instanceof token_1.TLineComment) { items.push(new ast_1.LineComment(t.range, t.items)); } else if (t instanceof token_1.TBlockComment) { items.push(new ast_1.BlockComment(t.range, t.items)); } else { ctx.error(t.range, 'File root must have no content other than a document'); } }; } function block(ctx, begin, finish) { const items = []; return (t) => { if (t instanceof token_1.TEOF) { ctx.error(t.range, 'Block is not closed'); ctx.end(); finish(new ast_1.Block(begin.range, t.range, items)); return state_machine_1.ReDo; } else if (t instanceof token_1.TSComma) { items.push(new ast_1.Comma(t.range)); } else if (t instanceof token_1.TSObjEnd) { ctx.end(); finish(new ast_1.Block(begin.range, t.range, items)); } else if (t instanceof token_1.TSObjStart) { ctx.error(t.range, 'Block content must start with a key'); return ctx.callNoFirst(block, t, _ => { }); } else if (t instanceof token_1.TSArrStart) { ctx.error(t.range, 'Block content must start with a key'); return ctx.callNoFirst(arr, t, _ => { }); } else if (t instanceof token_1.TStr || t instanceof token_1.TWord) { return ctx.callNoFirst(key, t, kv => items.push(kv)); } else if (t instanceof token_1.TSArrEnd) { ctx.error(t.range, 'No Array here'); } else { ctx.error(t.range, 'Block content must start with a key'); } }; } function arr(ctx, begin, finish) { const items = []; return (t) => { if (t instanceof token_1.TEOF) { ctx.error(t.range, 'Array is not closed'); ctx.end(); finish(new ast_1.Arr(begin.range, t.range, items)); return state_machine_1.ReDo; } else if (t instanceof token_1.TSComma) { items.push(new ast_1.Comma(t.range)); } else if (t instanceof token_1.TSArrEnd) { ctx.end(); finish(new ast_1.Arr(begin.range, t.range, items)); } else if (t instanceof token_1.TSObjEnd) { ctx.error(t.range, 'No Block here'); } else if (t instanceof token_1.TSSplit) { ctx.error(t.range, 'Array cant have key'); } else { return ctx.call(val, u => items.push(u)); } }; } function key(ctx, k, finish) { return (t) => { if (t instanceof token_1.TEOF) { ctx.error(t.range, 'There should be a key value here'); ctx.end(); return state_machine_1.ReDo; } else if (t instanceof token_1.TSComma) { ctx.error(t.range, 'There should be a key value here'); ctx.end(); return state_machine_1.ReDo; } else if (t instanceof token_1.TSSplit) { ctx.end(); return ctx.callNoFirst(val, u => { const sp = new ast_1.Split(t.range, t.val); const kv = new ast_1.KeyVal(new ast_1.Key(k.range, k instanceof token_1.TStr ? new ast_1.Str(k.range, k.val, k.col) : k.val), u, sp); finish(kv); }); } else { ctx.end(); return ctx.call(val, u => { const kv = new ast_1.KeyVal(new ast_1.Key(k.range, k instanceof token_1.TStr ? new ast_1.Str(k.range, k.val, k.col) : k.val), u); finish(kv); }); } }; } function val(ctx, finish) { return (t) => { if (t instanceof token_1.TEOF) { ctx.error(t.range, 'There should be a value here'); ctx.end(); return state_machine_1.ReDo; } else if (t instanceof token_1.TStr) { ctx.end(); finish(new ast_1.Str(t.range, t.val, t.col)); } else if (t instanceof token_1.TWord) { ctx.end(); return ctx.call(word, t, u => { finish(u); }); } else if (t instanceof token_1.TSComma || t instanceof token_1.TSSplit || t instanceof token_1.TSArrEnd || t instanceof token_1.TSObjEnd) { ctx.error(t.range, 'There should be a value here'); ctx.end(); return state_machine_1.ReDo; } else if (t instanceof token_1.TSObjStart) { ctx.end(); return ctx.callNoFirst(block, t, b => { finish(b); }); } else if (t instanceof token_1.TSArrStart) { ctx.end(); return ctx.callNoFirst(arr, t, a => { finish(a); }); } else { t; //todo ctx.end(); } }; } const reg_Num = /(0x[\da-fA-F_]+)|(([\-]?([\d\_])+)\.([\-]?([\d\_])+([eE]([\-]?)\d+)?))|(([\-]?([\d\_])+)\.([eE]([\-]?)\d+)?)|([\-]?\.(([\d\_])+([eE]([\-]?)\d+)?))|(([\-]?([\d\_])+([eE]([\-]?)\d+)?))/i; function word(ctx, w, finish) { return (t) => { ctx.end(); if (w.val === 'true') { finish(new ast_1.Bool(w.range, true)); } else if (w.val === 'false') { finish(new ast_1.Bool(w.range, false)); } else if (w.val === 'null') { finish(new ast_1.Null(w.range)); } else if (reg_Num.test(w.val)) { finish(new ast_1.Num(w.range, Number(w.val.replace('_', '')))); } else { finish(new ast_1.Str(w.range, w.val, null)); } }; }