Function loop

  • A parser that can loop indefinitely. This can be helpful when parsing repeated structures, like a bunch of statements:

        // Note that we are using a mutable list here. Dangerous but OK in this scenario.
    const statementsHelp = (stmts: Stmt[]): P.Parser<P.Step<Stmt[], Stmt[]>> => {
    return P.oneOf(
    P.succeed((stmt) => {
    stmts.push(stmt);
    return new P.Loop(stmts);
    })
    .apply(statement)
    .skip(P.spaces)
    .skip(P.symbol(";"))
    .skip(P.spaces),
    P.succeed(P.Unit).map(() => new P.Done(stmts))
    );
    };

    const statements: P.Parser<Stmt[]> = P.loop([])(statementsHelp);

    IMPORTANT NOTE: Parsers like succeed(Unit) and chompWhile(isAlpha) can succeed without consuming any characters. So in some cases, you may want to use getOffset to ensure that each step actually consumed characters. Otherwise you could end up in an infinite loop!

    Note: Anything you can write with loop, you can also write as a parser that chomps some characters andThen calls itself with new arguments. The problem with calling andThen recursively is that it grows the stack, so you cannot do it indefinitely. So loop allows us to write more efficient parsers. Of course you could also use the looping constructs built into javascript/typescript itself.

    See

    Type Parameters

    • STATE

    Parameters

    • state: STATE

    Returns (<A>(fn: ((s: STATE) => Simple.Parser<Simple.Step<STATE, A>>)) => Simple.Parser<A>)