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. conststatementsHelp = (stmts: Stmt[]): P.Parser<P.Step<Stmt[], Stmt[]>> => { returnP.oneOf( P.succeed((stmt) => { stmts.push(stmt); returnnewP.Loop(stmts); }) .apply(statement) .skip(P.spaces) .skip(P.symbol(";")) .skip(P.spaces), P.succeed(P.Unit).map(() =>newP.Done(stmts)) ); };
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.
A parser that can loop indefinitely. This can be helpful when parsing repeated structures, like a bunch of statements:
IMPORTANT NOTE: Parsers like
succeed(Unit)
andchompWhile(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 charactersandThen
calls itself with new arguments. The problem with callingandThen
recursively is that it grows the stack, so you cannot do it indefinitely. Soloop
allows us to write more efficient parsers. Of course you could also use the looping constructs built into javascript/typescript itself.See