import { Parser, Result, Input } from '../parser'; import { always } from '../control/state'; import { spend } from '../effect/clock'; export function match

(pattern: RegExp, f: (matched: RegExpMatchArray) => P): P; export function match(pattern: RegExp, f: (matched: RegExpMatchArray) => Parser): Parser { assert(!pattern.flags.match(/[gm]/) && pattern.sticky && !pattern.source.startsWith('^')); interface Memory { readonly position: number; readonly range: number; } return always>>([ (input, output) => { const { source, position } = input; if (position === source.length) return Result.skip; pattern.lastIndex = position; const params = pattern.exec(source); if (!params) return Result.skip; assert(source.startsWith(params[0], position)); spend(input, output, params[0].length); input.memory = { position, range: params[0].length, }; return f(params)(input, output); }, (input, output) => { const { position, memory } = input; input.position += output.state ? position === memory.position ? memory.range : 0 : position - memory.position; return output.context; }, ]); }