import { Parser, Result, Input } from '../parser'; import { always } from '../control/state'; export class State { constructor(private readonly initial: T) { } private readonly stack: T[] = []; public get(): T { return this.stack.at(-1) ?? this.initial; } public put(state: T): void { this.stack.push(state); } public delete(): T { assert(this.stack.length > 0); const state = this.stack.pop()!; return state; } } export function state

(state: number, parser: P): P; export function state

(state: number, positive: boolean, parser: P): P; export function state(state: number, positive: boolean | Parser, parser?: Parser): Parser { if (typeof positive === 'function') { parser = positive; positive = true; } assert(state); assert(parser = parser!); interface Memory { readonly state: number; } return always>>([ (input, output) => { const s = input.state; input.state = positive ? s | state : s & ~state; input.memory = { state: s, }; return output.context; }, parser, (input, output) => { input.state = input.memory.state; return output.context; }, ]); } export function constraint

(state: number, parser: P): P; //export function constraint

(state: number, positive: boolean, parser: P): P; export function constraint(state: number, positive: boolean | Parser, parser?: Parser): Parser { if (typeof positive === 'function') { parser = positive; positive = false; } assert(state); assert(parser = parser!); return always([ (input, output) => { const s = positive ? state & input.state : state & ~input.state; return s === state ? output.context : Result.skip; }, parser, ]); }