import { Parser, Output } from '../parser';
import { always } from '../control/state';
import { min } from 'spica/alias';
export function recursion
(index: number, parser: P): P;
export function recursion(index: number, parser: Parser): Parser {
assert(index >= 0);
return always([
(input, output) => {
const resources = input.resources ?? { clock: 1, recursions: [1] };
const { recursions } = resources;
recur(output, recursions, index, 1);
return output.context;
},
parser,
(input, output) => {
const resources = input.resources ?? { clock: 1, recursions: [1] };
const { recursions } = resources;
recur(output, recursions, index, -1);
return output.context;
},
]);
}
export function recur(output: Output, recursions: number[], index: number, size: number, force: boolean = false): void {
index = min(index, recursions.length && recursions.length - 1);
if (recursions[index] < size - +force) {
output.error ??= new Error('Too much recursion');
}
recursions[index] -= size;
}