UNPKG

cbon

Version:
89 lines (88 loc) 2.29 kB
import { isVoid } from "./utils"; import { TkPos, TkRange } from "./pos"; export const ReDo = Symbol('ReDo'); export class WhenError extends Error { constructor(err) { super(); this.err = err; } } export class State { constructor(show_all_err) { this.count = 0; this.char = 0; this.line = 0; this.states = []; this.lines = []; this.errors = []; this.queue = []; this.show_all_err = show_all_err; } push(unit) { this.states.push(unit); } pop() { return this.states.pop(); } call(c) { const r = this.states[this.states.length - 1](c); if (!isVoid(r)) { if (r === ReDo) { this.queue.push(() => this.call(c)); } else { const { fn, ignoreFirst } = r; this.push(fn); if (!ignoreFirst) this.queue.push(() => this.call(c)); } } } get pos() { return new TkPos(this.count, this.char, this.line); } get lastPos() { const np = new TkPos(this.count, this.char, this.line); np.count--; if (np.char === 0) { np.line--; np.char = this.lines[np.line]; } else np.char--; return np; } } export class Context { constructor(state) { this.state = state; } end() { this.state.pop(); } call(f, ...p) { return { fn: f(new Context(this.state), ...p), ignoreFirst: false }; } callNoFirst(f, ...p) { return { fn: f(new Context(this.state), ...p), ignoreFirst: true }; } flag() { this.last_flag = this.state.pos; } range(last = false) { var _a; const n = last ? this.state.lastPos : this.state.pos; return new TkRange((_a = this.last_flag, (_a !== null && _a !== void 0 ? _a : n)), n); } error(range, msg) { if (!this.state.show_all_err) throw new WhenError({ range, msg }); this.state.errors.push({ range, msg }); } }