{-|
MonadPlus utilities.
For instance, they can be applied with parsing libraries.
-}
module VectorBuilder.MonadPlus
where

import VectorBuilder.Prelude
import Data.Vector (Vector)
import qualified VectorBuilder.Builder as A
import qualified VectorBuilder.Vector as B
import qualified Data.Vector.Generic as C


{-# INLINABLE many #-}
many :: (MonadPlus m, C.Vector vector element) => m element -> m (vector element)
many :: m element -> m (vector element)
many m element
m =
  (Builder element -> vector element)
-> m (Builder element) -> m (vector element)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Builder element -> vector element
forall (vector :: * -> *) element.
Vector vector element =>
Builder element -> vector element
B.build (m element -> m (Builder element)
forall (m :: * -> *) element.
MonadPlus m =>
m element -> m (Builder element)
manyBuilder m element
m)

{-# INLINABLE manyBuilder #-}
manyBuilder :: (MonadPlus m) => m element -> m (A.Builder element)
manyBuilder :: m element -> m (Builder element)
manyBuilder m element
m =
  Builder element -> m (Builder element)
loop Builder element
forall a. Monoid a => a
mempty
  where
    loop :: Builder element -> m (Builder element)
loop !Builder element
builder =
      m (Builder element) -> m (Builder element) -> m (Builder element)
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus
        (do
          !element
element <- m element
m
          Builder element -> m (Builder element)
loop (Builder element
builder Builder element -> Builder element -> Builder element
forall a. Semigroup a => a -> a -> a
<> element -> Builder element
forall element. element -> Builder element
A.singleton element
element))
        (Builder element -> m (Builder element)
forall (m :: * -> *) a. Monad m => a -> m a
return Builder element
builder)

{-# INLINABLE many1 #-}
many1 :: (MonadPlus m, C.Vector vector element) => m element -> m (vector element)
many1 :: m element -> m (vector element)
many1 m element
m =
  do
    element
firstElement <- m element
m
    Builder element
builder <- m element -> m (Builder element)
forall (m :: * -> *) element.
MonadPlus m =>
m element -> m (Builder element)
manyBuilder m element
m
    vector element -> m (vector element)
forall (m :: * -> *) a. Monad m => a -> m a
return (Builder element -> vector element
forall (vector :: * -> *) element.
Vector vector element =>
Builder element -> vector element
B.build (element -> Builder element
forall element. element -> Builder element
A.singleton element
firstElement Builder element -> Builder element -> Builder element
forall a. Semigroup a => a -> a -> a
<> Builder element
builder))

{-# INLINABLE sepBy #-}
sepBy :: (MonadPlus m, C.Vector vector element) => m element -> m separator -> m (vector element)
sepBy :: m element -> m separator -> m (vector element)
sepBy m element
elementM m separator
separatorM =
  m (vector element) -> m (vector element) -> m (vector element)
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus (m element -> m separator -> m (vector element)
forall (m :: * -> *) (vector :: * -> *) element separator.
(MonadPlus m, Vector vector element) =>
m element -> m separator -> m (vector element)
sepBy1 m element
elementM m separator
separatorM) (vector element -> m (vector element)
forall (m :: * -> *) a. Monad m => a -> m a
return vector element
forall (v :: * -> *) a. Vector v a => v a
C.empty)

{-# INLINABLE sepBy1 #-}
sepBy1 :: (MonadPlus m, C.Vector vector element) => m element -> m separator -> m (vector element)
sepBy1 :: m element -> m separator -> m (vector element)
sepBy1 m element
elementM m separator
separatorM =
  do
    element
firstElement <- m element
elementM
    Builder element
builder <- Builder element -> m (Builder element)
loop (element -> Builder element
forall element. element -> Builder element
A.singleton element
firstElement)
    vector element -> m (vector element)
forall (m :: * -> *) a. Monad m => a -> m a
return (Builder element -> vector element
forall (vector :: * -> *) element.
Vector vector element =>
Builder element -> vector element
B.build Builder element
builder)
  where
    loop :: Builder element -> m (Builder element)
loop Builder element
builder =
      m (Builder element) -> m (Builder element) -> m (Builder element)
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus
        (do
          m separator
separatorM
          !element
element <- m element
elementM
          Builder element -> m (Builder element)
loop (Builder element
builder Builder element -> Builder element -> Builder element
forall a. Semigroup a => a -> a -> a
<> element -> Builder element
forall element. element -> Builder element
A.singleton element
element))
        (Builder element -> m (Builder element)
forall (m :: * -> *) a. Monad m => a -> m a
return Builder element
builder)