Advanced Repetition
If we want nested repetition that doesn't consume the whole input, we need a way to end the scope of a Repeat
. This is accomplished using a special value given to the constructor. We also wrap the repeat into a separate type so we can easily add other array-manipulating functions.
const repeatNumber = new Repeat(value, "-");
const arr = new Type<number[]>("arr");
arr.setDefault(repeatNumber);
We use a -
here as common scope characters like )
,]
and ;
are used by shells like bash and would need to be escaped in a cli.
> mul sum 1 1 1 2
Error: Parser finished but expected type <t.value>.
> mul sum 1 1 1 - 2
6
For fun we add some more array functions.
arr.setFunctions([
Func("repeat")
.arg(value)
.arg(value)
.setExec((amnt, val): number[] => Array<number>(amnt).fill(val)),
Func("range")
.arg(value)
.setExec((max): number[] =>
Array.from({ length: max }, (_, index) => index),
),
Func("double")
.arg(arr)
.setExec((vals) => vals.map((val) => val * 2)),
]);
> mul 2 sum range 5
20
> sum double range 5
20
l.calc:
| <t.value> EOI
t.value:
| "add" <t.value> <t.value>
| "mul" <t.value> <t.value>
| "sum" <t.arr>
| "pi"
| <p.number>
t.arr:
| "repeat" <t.value> <t.value>
| "range" <t.value>
| "double" <t.arr>
| <r.t.value>
r.t.value:
| <t.value> * EOI
| <t.value> * "-"