on master help sign in
Implement sepBy more efficiently
1c81cd7Harendra Kumar
core/src/Streamly/Internal/Data/Parser.hs+14−4
@@ -219,7 +219,6 @@ module Streamly.Internal.Data.Parser
219 )
219 )
220where
220where
221
221
222−import Control.Applicative ((<|>))
223import Control.Monad.Catch (MonadCatch, MonadThrow)
222import Control.Monad.Catch (MonadCatch, MonadThrow)
224import Data.Functor (($>))
223import Data.Functor (($>))
225import Prelude hiding
224import Prelude hiding
@@ -238,6 +237,7 @@ import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
238-- >>> :m
237-- >>> :m
239-- >>> :set -package streamly
238-- >>> :set -package streamly
240-- >>> import Prelude hiding (any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either, filter)
239-- >>> import Prelude hiding (any, all, dropWhile, take, takeWhile, sequence, concatMap, maybe, either, filter)
240+-- >>> import Control.Applicative ((<|>))
241-- >>> import qualified Streamly.Prelude as Stream
241-- >>> import qualified Streamly.Prelude as Stream
242-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (parse, parseMany)
242-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (parse, parseMany)
243-- >>> import qualified Streamly.Data.Fold as Fold
243-- >>> import qualified Streamly.Data.Fold as Fold
@@ -1276,6 +1276,10 @@ deintercalate = undefined
1276
1276
1277-- | Parse items separated by a separator parsed by the supplied parser. At
1277-- | Parse items separated by a separator parsed by the supplied parser. At
1278-- least one item must be present for the parser to succeed.
1278-- least one item must be present for the parser to succeed.
1279+--
1280+-- Note that this can go in infinite loop if both the parsers fail on some
1281+-- input. Detection of that would make the implementation more complex.
1282+--
1279{-# INLINE sepBy1 #-}
1283{-# INLINE sepBy1 #-}
1280sepBy1 :: MonadCatch m =>
1284sepBy1 :: MonadCatch m =>
1281 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1285 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
@@ -1285,11 +1289,17 @@ sepBy1 sink p sep = do
1285 f1 <- fromEffect $ FL.snoc f x
1289 f1 <- fromEffect $ FL.snoc f x
1286 many (sep >> p) f1
1290 many (sep >> p) f1
1287
1291
1288−-- | sepBy1 or empty, does not fail.
1292+-- | Run the content parser first, when it is done, the separator parser is
1293+-- run, when it is done content parser is run again and so on. If none of the
1294+-- parsers consumes an input then parser returns a failure.
1295+--
1296+-- >>> sepBy sink content sep = Parser.sepBy1 sink content sep <|> return mempty
1297+--
1289{-# INLINE sepBy #-}
1298{-# INLINE sepBy #-}
1290−sepBy :: (MonadCatch m, Monoid c) =>
1299+sepBy :: MonadCatch m =>
1291 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1300 Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1292−sepBy sink p sep = sepBy1 sink p sep <|> return mempty
1301+sepBy sink content sep =
1302+ D.toParserK $ D.sepBy sink (D.fromParserK content) (D.fromParserK sep)
1293
1303
1294-------------------------------------------------------------------------------
1304-------------------------------------------------------------------------------
1295-- Interleaving a collection of parsers
1305-- Interleaving a collection of parsers
core/src/Streamly/Internal/Data/Parser/ParserD.hs+71
@@ -111,6 +111,7 @@ module Streamly.Internal.Data.Parser.ParserD
111 -- Use two folds, run a primary parser, its rejected values go to the
111 -- Use two folds, run a primary parser, its rejected values go to the
112 -- secondary parser.
112 -- secondary parser.
113 , deintercalate
113 , deintercalate
114+ , sepBy
114
115
115 -- ** Sequential Alternative
116 -- ** Sequential Alternative
116 , alt
117 , alt
@@ -1258,6 +1259,76 @@ deintercalate ::
1258 -> Parser m x (y, z)
1259 -> Parser m x (y, z)
1259deintercalate = undefined
1260deintercalate = undefined
1260
1261
1262+data SepByState fs sp ss =
1263+ SepByInit fs sp
1264+ | SepBySeparator fs ss Bool
1265+
1266+{-# INLINE sepBy #-}
1267+sepBy :: MonadCatch m =>
1268+ Fold m b c -> Parser m a b -> Parser m a x -> Parser m a c
1269+sepBy
1270+ (Fold fstep finitial fextract)
1271+ (Parser pstep pinitial pextract)
1272+ (Parser sstep sinitial _) = Parser step initial extract
1273+
1274+ where
1275+
1276+ errMsg p status =
1277+ error $ "sepBy: " ++ p ++ " parser cannot "
1278+ ++ status ++ " without input"
1279+
1280+ initial = do
1281+ res <- finitial
1282+ case res of
1283+ FL.Partial fs -> do
1284+ resP <- pinitial
1285+ case resP of
1286+ IPartial sp -> return $ IPartial $ SepByInit fs sp
1287+ IDone _ -> errMsg "content" "succeed"
1288+ IError _ -> errMsg "content" "fail"
1289+ FL.Done b -> return $ IDone b
1290+
1291+ step (SepByInit fs sp) a = do
1292+ r <- pstep sp a
1293+ case r of
1294+ Partial n s -> return $ Partial n (SepByInit fs s)
1295+ Continue n s -> return $ Continue n (SepByInit fs s)
1296+ Done n b -> do
1297+ fres <- fstep fs b
1298+ case fres of
1299+ FL.Partial fs1 -> do
1300+ resS <- sinitial
1301+ case resS of
1302+ IPartial ss ->
1303+ return $ Partial n (SepBySeparator fs1 ss False)
1304+ IDone _ -> errMsg "separator" "succeed"
1305+ IError _ -> errMsg "separator" "fail"
1306+ FL.Done c -> return $ Done n c
1307+ Error err -> return $ Error err
1308+ step (SepBySeparator fs ss consumed) a = do
1309+ r <- sstep ss a
1310+ case r of
1311+ Partial n s -> return $ Partial n (SepBySeparator fs s True)
1312+ Continue n s -> return $ Continue n (SepBySeparator fs s True)
1313+ Done n _ ->
1314+ if consumed
1315+ then do
1316+ resP <- pinitial
1317+ case resP of
1318+ IPartial sp -> return $ Partial n $ SepByInit fs sp
1319+ IDone _ -> errMsg "content" "succeed"
1320+ IError _ -> errMsg "content" "fail"
1321+ else return $ Error "sepBy: infinite loop"
1322+ Error err -> return $ Error err
1323+
1324+ extract (SepByInit fs sp) = do
1325+ r <- pextract sp
1326+ res <- fstep fs r
1327+ case res of
1328+ FL.Partial fs1 -> fextract fs1
1329+ FL.Done c -> return c
1330+ extract (SepBySeparator fs _ _) = fextract fs
1331+
1261-------------------------------------------------------------------------------
1332-------------------------------------------------------------------------------
1262-- Sequential Collection
1333-- Sequential Collection
1263-------------------------------------------------------------------------------
1334-------------------------------------------------------------------------------