diff --git a/core/src/Streamly/Internal/Data/Parser.hs b/core/src/Streamly/Internal/Data/Parser.hs index e86c56fbb0..cd2b99baf7 100644 --- a/core/src/Streamly/Internal/Data/Parser.hs +++ b/core/src/Streamly/Internal/Data/Parser.hs @@ -2136,9 +2136,7 @@ groupByRollingEither FL.Done b -> return $ FDone 0 (Left b) FL.Partial s11 -> FDone 0 . Left <$> ffinal1 s11 --- XXX use an Unfold instead of a list? --- XXX custom combinators for matching list, array and stream? --- XXX rename to listBy? +-- XXX custom combinator for matching, array as well? -- | Match the given sequence of elements using the given comparison function. -- Returns the original sequence if successful. @@ -2153,11 +2151,11 @@ groupByRollingEither -- Right "string" -- -- >>> Stream.parsePos (Parser.listEqBy (==) "mismatch") $ Stream.fromList "match" --- Left (ParseErrorPos 2 "streamEqBy: mismtach occurred") +-- Left (ParseErrorPos 2 "listEqBy: mismatch after matching 1 elements") -- {-# INLINE listEqBy #-} listEqBy :: Monad m => (a -> a -> Bool) -> [a] -> Parser a m [a] -listEqBy cmp xs = streamEqByInternal cmp (D.fromList xs) *> fromPure xs +listEqBy cmp xs = streamEqByInternal "listEqBy" cmp (D.fromList xs) *> fromPure xs {- listEqBy cmp str = Parser step initial extract @@ -2188,41 +2186,45 @@ listEqBy cmp str = Parser step initial extract -} {-# INLINE streamEqByInternal #-} -streamEqByInternal :: Monad m => (a -> a -> Bool) -> D.Stream m a -> Parser a m () -streamEqByInternal cmp (D.Stream sstep state) = Parser step initial extract +streamEqByInternal :: Monad m => String -> (a -> a -> Bool) -> D.Stream m a -> Parser a m () +streamEqByInternal fname cmp (D.Stream sstep state) = Parser step initial extract where initial = do r <- sstep defState state case r of - D.Yield x s -> return $ IPartial (Just' x, s) + D.Yield x s -> return $ IPartial (Just' x, s, 0 :: Int) D.Stop -> return $ IDone () -- Need Skip/Continue in initial to loop right here - D.Skip s -> return $ IPartial (Nothing', s) + D.Skip s -> return $ IPartial (Nothing', s, 0) - step (Just' x, st) a = + step (Just' x, st, n) a = if x `cmp` a then do r <- sstep defState st return $ case r of - D.Yield x1 s -> SContinue 1 (Just' x1, s) + D.Yield x1 s -> SContinue 1 (Just' x1, s, n + 1) D.Stop -> SDone 1 () - D.Skip s -> SContinue 0 (Nothing', s) - else return $ SError "streamEqBy: mismtach occurred" - step (Nothing', st) a = do + D.Skip s -> SContinue 0 (Nothing', s, n + 1) + else return $ SError + (fname ++ ": mismatch after matching " ++ show n ++ " elements") + step (Nothing', st, n) a = do r <- sstep defState st return $ case r of D.Yield x s -> do if x `cmp` a - then SContinue 1 (Nothing', s) - else SError "streamEqBy: mismatch occurred" + then SContinue 1 (Nothing', s, n + 1) + else SError + (fname ++ ": mismatch after matching " + ++ show n ++ " elements") D.Stop -> SDone 0 () - D.Skip s -> SContinue 0 (Nothing', s) + D.Skip s -> SContinue 0 (Nothing', s, n) - extract _ = return $ FError "streamEqBy: end of input" + extract (_, _, n) = return $ FError + (fname ++ ": end of input after matching " ++ show n ++ " elements") -- | Like 'listEqBy' but uses a stream instead of a list and does not return -- the stream. @@ -2231,7 +2233,7 @@ streamEqByInternal cmp (D.Stream sstep state) = Parser step initial extract streamEqBy :: Monad m => (a -> a -> Bool) -> D.Stream m a -> Parser a m () -- XXX Somehow composing this with "*>" is much faster on the microbenchmark. -- Need to investigate why. -streamEqBy cmp stream = streamEqByInternal cmp stream *> fromPure () +streamEqBy cmp stream = streamEqByInternal "streamEqBy" cmp stream *> fromPure () -- Rename to "list". -- | Match the input sequence with the supplied list and return it if