sepBy package:streamly-core

Apply two parsers alternately to an input stream. Parsing starts at the first parser and stops at the first parser. The output of the first parser is emiited and the output of the second parser is discarded. It can be used to parse a infix style pattern e.g. p1 p2 p1 . Empty input or single parse of the first parser is accepted. Definitions:
>>> sepBy p1 p2 f = Parser.deintercalate p1 p2 (Fold.catLefts f)

>>> sepBy p1 p2 f = Parser.sepBy1 p1 p2 f <|> Parser.fromEffect (Fold.finalM f)
Examples:
>>> p1 = Parser.takeWhile1 (not . (== '+')) Fold.toList

>>> p2 = Parser.satisfy (== '+')

>>> p = Parser.sepBy p1 p2 Fold.toList

>>> Stream.parse p $ Stream.fromList ""
Right []

>>> Stream.parse p $ Stream.fromList "1"
Right ["1"]

>>> Stream.parse p $ Stream.fromList "1+"
Right ["1"]

>>> Stream.parse p $ Stream.fromList "1+2+3"
Right ["1","2","3"]
Like sepBy but requires at least one successful parse. Definition:
>>> sepBy1 p1 p2 f = Parser.deintercalate1 p1 p2 (Fold.catLefts f)
Examples:
>>> p1 = Parser.takeWhile1 (not . (== '+')) Fold.toList

>>> p2 = Parser.satisfy (== '+')

>>> p = Parser.sepBy1 p1 p2 Fold.toList

>>> Stream.parsePos p $ Stream.fromList ""
Left (ParseErrorPos 0 "takeWhile1: end of input")

>>> Stream.parse p $ Stream.fromList "1"
Right ["1"]

>>> Stream.parse p $ Stream.fromList "1+"
Right ["1"]

>>> Stream.parse p $ Stream.fromList "1+2+3"
Right ["1","2","3"]
Non-backtracking version of sepBy. Several times faster.
Like splitSepBy_ but splits the stream on a sequence of elements rather than a single element. Parses a sequence of tokens separated by an infixed separator e.g. a;b;c is parsed as a, b, c. If the pattern is empty then each element is a match, thus the fold is finalized on each element.
>>> splitSepBy p xs = Stream.fold Fold.toList $ Stream.splitSepBySeq_ (Array.fromList p) Fold.toList (Stream.fromList xs)
>>> splitSepBy "" ""
[]
>>> splitSepBy "" "a...b"
["a",".",".",".","b"]
>>> splitSepBy ".." ""
[]
>>> splitSepBy ".." "a...b"
["a",".b"]
>>> splitSepBy ".." "abc"
["abc"]
>>> splitSepBy ".." ".."
["",""]
>>> splitSepBy "." ".a"
["","a"]
>>> splitSepBy "." "a."
["a",""]
Uses Rabin-Karp algorithm for substring search.
Split on an infixed separator element, dropping the separator. The supplied Fold is applied on the split segments. Splits the stream on separator elements determined by the supplied predicate, separator is considered as infixed between two segments: Definition: Usage:
>>> splitOn p xs = Stream.fold Fold.toList $ Stream.splitSepBy_ p Fold.toList (Stream.fromList xs)

>>> splitOn (== '.') "a.b"
["a","b"]
Splitting an empty stream results in an empty stream i.e. zero splits:
>>> splitOn (== '.') ""
[]
If the stream does not contain the separator then it results in a single split:
>>> splitOn (== '.') "abc"
["abc"]
If one or both sides of the separator are missing then the empty segment on that side is folded to the default output of the fold:
>>> splitOn (== '.') "."
["",""]
>>> splitOn (== '.') ".a"
["","a"]
>>> splitOn (== '.') "a."
["a",""]
>>> splitOn (== '.') "a..b"
["a","","b"]
splitSepBy_ is an inverse of unfoldEachSepBy:
Stream.unfoldEachSepBy '.' Unfold.fromList . Stream.splitSepBy_ (== '.') Fold.toList === id
Assuming the input stream does not contain the separator:
Stream.splitSepBy_ (== '.') Fold.toList . Stream.unfoldEachSepBy '.' Unfold.fromList === id
Unfold each element of the stream, separate the successive unfolds by a sequence generated by unfolding the supplied value. Definition:
>>> unfoldEachSepBySeq a u = Stream.unfoldEach u . Stream.intersperse a

>>> unfoldEachSepBySeq a u = Stream.intercalateSepBy u (Stream.repeat a) u
Idioms:
>>> intersperse x = Stream.unfoldEachSepBySeq x Unfold.identity

>>> unwords = Stream.unfoldEachSepBySeq " " Unfold.fromList
Usage:
>>> input = Stream.fromList ["abc", "def", "ghi"]

>>> Stream.toList $ Stream.unfoldEachSepBySeq " " Unfold.fromList input
"abc def ghi"
Split a stream of byte arrays on a given separator byte, dropping the separator and coalescing all the arrays between two separators into a single array.
Insert the given element between arrays and flatten.
>>> concatSepBy x = Stream.unfoldEachSepBy x Array.reader
Split a stream of arrays on a given separator byte, dropping the separator and coalescing all the arrays between two separators into a single array.
Take either the separator or the token. Separator is a Left value and token is Right value. Unimplemented
Apply fold f1 infix separated by fold f2. Unimplemented
The first stream Stream m b is turned into a stream of streams by unfolding each element using the first unfold, similarly Stream m a is also turned into a stream of streams. The second stream of streams is interspersed with the streams from the first stream in an infix manner and then the resulting stream is flattened. You can think of this as interleaveSepBy on the stream of streams followed by concat. Same as the following but more efficient:
>>> intercalateSepBy u1 s1 u2 s2 = Stream.concat $ Stream.interleaveSepBy (fmap (Stream.unfold u1) s1) (fmap (Stream.unfold u2) s2)
If the separator stream consists of nil streams then it becomes equivalent to unfoldEach:
>>> unfoldEach = Stream.intercalateSepBy (Unfold.nilM (const (return ()))) (Stream.repeat ())
Pre-release
Like interleaveSepBy' but interleaving stops when and only when the second stream is exhausted. Shortfall of the infix stream is ignored and excess is discarded.
(. . .) (a b c) => a . b . c    -- additional . is discarded
(. .  ) (a b c) => a . b . c
(.    ) (a b c) => a . b c      -- missing . is ignored
Examples:
>>> f x y = Stream.toList $ Stream.interleaveSepBy (Stream.fromList x) (Stream.fromList y)

>>> f "..." "abc"
"a.b.c"

>>> f ".." "abc"
"a.b.c"

>>> f "." "abc"
"a.bc"
Interleave the two streams such that the elements of the first stream are infixed between the elements of the second stream. If one of the streams is exhausted then interleaving stops.
(. . .) (a b c) => a . b . c    -- additional . is discarded
(. .  ) (a b c) => a . b . c
(.    ) (a b c) => a . b        -- c is discarded
>>> f x y = Stream.toList $ Stream.interleaveSepBy' (Stream.fromList x) (Stream.fromList y)

>>> f "..." "abc"
"a.b.c"

>>> f ".." "abc"
"a.b.c"

>>> f "." "abc"
"a.b"
Split on any one of the given patterns. Unimplemented
Unfold the elements of a stream, intersperse the given element between the unfolded streams and then concat them into a single stream. Definition:
>>> unfoldEachSepBy x = Stream.unfoldEachSepByM (return x)

>>> unfoldEachSepBy x = Stream.intercalateSepBy Unfold.identity (Stream.repeat x)
Usage:
>>> unwords = Stream.unfoldEachSepBy ' '
Pre-release
Monadic variant of unfoldEachSepBy. Definition:
>>> unfoldEachSepByM x = Stream.intercalateSepBy Unfold.identity (Stream.repeatM x)