mrkkrp / parser-combinators

Lightweight package providing commonly useful parser combinators
Other
52 stars 15 forks source link

Like manyTIll but does not throw away the end? #22

Closed kindaro closed 4 years ago

kindaro commented 5 years ago

Hi. Thank you for your great work on this project.

I notice manyTill will consume and throw away the result of end.

λ parseTest @Void (someTill anySingle (single '$') <* eof) ("mika$" :: Text)
"mika"

Notice there is no $ sign in the output.

This is the relevant code from the latest Hackage release:

manyTill :: MonadPlus m => m a -> m end -> m [a]
manyTill p end = go id
  where
    go f = do
      done <- option False (re True end)  -- `re` for "replace", right?
      if done
        then return (f [])
        else do
          x <- p
          go (f . (x:))
{-# INLINE manyTill #-}

I would like there to be a function like this one, but preserving every bit of input, including the end. Can we add it, under, say, the name manyTill_ ? Or is there a better way to achieve what I want?

mrkkrp commented 4 years ago

re is there for compatibility with older GHCs, which is btw no longer a problem because we dropped support for all but 3 latest versions of GHC.

To answer your question, I think the way it's typically done is that you wrap with the end parser with lookAhead so it doesn't get consumed when it matches. After that you can consume it "manually" once again. This is a bit less efficient than having manyTill_ though.

I'd accept a PR adding manyTill_ and someTill_.

mrkkrp commented 4 years ago

I removed re to avoid confusing future readers.

kindaro commented 4 years ago

I will take a shot at that feature, but if you do not hear from me within a week that would mean I had no success.

mrkkrp commented 4 years ago

Resolved in #24.