chumsky icon indicating copy to clipboard operation
chumsky copied to clipboard

Add a `many_till` combinator

Open mwobat opened this issue 1 year ago • 2 comments

I propose a combinator that repeats the first parser until the second one matches.

nom has an equivalent combinator: https://docs.rs/nom/7.1.1/nom/multi/fn.many_till.html

The output type would be (Vec<A>, B), A and B being the output types of the given parsers.

mwobat avatar Jul 23 '22 17:07 mwobat

I may be misunderstanding you, but wouldn't such a combinator be the equivalent of:

just(A).repeated().then(just(B))

You can see this being used in Zesterer's foo implementation.

Zij-IT avatar Jul 31 '22 20:07 Zij-IT

I may be misunderstanding you, but wouldn't such a combinator be the equivalent of:

just(A).repeated().then(just(B))

I should've explained more clearly.

The docs for nom::multi::many_till say:

Applies the parser f until the parser g produces a result.

I guess the description for the parser you suggested would be: Applies the Parser f any number of times, then applies the parser g.

So while the many_till parser applies f lazily, your one applies it eagerly. I think you can use these two parsers interchangeably, until you have a case where f and g could parse the same input. Then the many_till parser would parse g, and your one would parse f.

If I'm not mistaken, it looks like the examples in the nom docs and for the foo implementation are just such cases where you could use your parser as well.

mwobat avatar Aug 01 '22 09:08 mwobat

So really, you want something like

a.and_is(b.not()).repeated().then(b)?

i.e: lazily consume a, provided it doesn't match b, and then consume a b?

zesterer avatar Aug 21 '22 19:08 zesterer

Yes, exactly 🙂

mwobat avatar Aug 21 '22 20:08 mwobat

Right. In that case, I'll probably close this in favour of #181 because it contains a little more discussion about these.

zesterer avatar Aug 21 '22 21:08 zesterer