-- |
-- Vector-specialised combinators often used for parsing.
module VectorExtras.Combinators where

import Data.Vector.Generic (Vector)
import qualified Data.Vector.Generic as Vector
import VectorExtras.Accumulator (Accumulator)
import qualified VectorExtras.Accumulator as Acc
import VectorExtras.Combinators.Helpers
import VectorExtras.Prelude

-- * Common

many :: (MonadPlus m, Vector v a) => m a -> m (v a)
many :: m a -> m (v a)
many m a
getElement =
  Accumulator a -> m a -> m (Accumulator a)
forall (m :: * -> *) a.
MonadPlus m =>
Accumulator a -> m a -> m (Accumulator a)
accMany Accumulator a
forall a. Accumulator a
Acc.init m a
getElement m (Accumulator a) -> (Accumulator a -> v a) -> m (v a)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Accumulator a -> v a
forall (v :: * -> *) a. Vector v a => Accumulator a -> v a
Acc.toVector

sepBy :: (MonadPlus m, Vector v a) => m a -> m sep -> m (v a)
sepBy :: m a -> m sep -> m (v a)
sepBy = (m sep -> m a -> m (v a)) -> m a -> m sep -> m (v a)
forall a b c. (a -> b -> c) -> b -> a -> c
flip m sep -> m a -> m (v a)
forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m sep -> m a -> m (v a)
sep

sepBy1 :: (MonadPlus m, Vector v a) => m a -> m sep -> m (v a)
sepBy1 :: m a -> m sep -> m (v a)
sepBy1 = (m sep -> m a -> m (v a)) -> m a -> m sep -> m (v a)
forall a b c. (a -> b -> c) -> b -> a -> c
flip m sep -> m a -> m (v a)
forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m sep -> m a -> m (v a)
sep1

-- |
-- Same as 'sepBy' but with arguments flipped.
-- Because the order of arguments in 'sepBy' does not feel right.
sep :: (MonadPlus m, Vector v a) => m sep -> m a -> m (v a)
sep :: m sep -> m a -> m (v a)
sep m sep
getSeparator m a
getElement =
  v a -> m (v a) -> m (v a)
forall (m :: * -> *) a. Alternative m => a -> m a -> m a
orPure v a
forall (v :: * -> *) a. Vector v a => v a
Vector.empty (m (v a) -> m (v a)) -> m (v a) -> m (v a)
forall a b. (a -> b) -> a -> b
$ m sep -> m a -> m (v a)
forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m sep -> m a -> m (v a)
sep1 m sep
getSeparator m a
getElement

-- |
-- Same as 'sepBy1' but with arguments flipped.
-- Because the order of arguments in 'sepBy1' does not feel right.
sep1 :: (MonadPlus m, Vector v a) => m sep -> m a -> m (v a)
sep1 :: m sep -> m a -> m (v a)
sep1 m sep
getSeparator m a
getElement =
  do
    a
element <- m a
getElement
    Accumulator a -> v a
forall (v :: * -> *) a. Vector v a => Accumulator a -> v a
Acc.toVector (Accumulator a -> v a) -> m (Accumulator a) -> m (v a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Accumulator a -> m a -> m (Accumulator a)
forall (m :: * -> *) a.
MonadPlus m =>
Accumulator a -> m a -> m (Accumulator a)
accMany (a -> Accumulator a -> Accumulator a
forall a. a -> Accumulator a -> Accumulator a
Acc.add a
element Accumulator a
forall a. Accumulator a
Acc.init) (m sep
getSeparator m sep -> m a -> m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m a
getElement)

sepEnd :: (MonadPlus m, Vector v a) => m sep -> m end -> m a -> m (v a)
sepEnd :: m sep -> m end -> m a -> m (v a)
sepEnd m sep
getSeparator m end
getEnd m a
getElement =
  v a -> m (v a) -> m (v a)
forall (m :: * -> *) a. Alternative m => a -> m a -> m a
orPure v a
forall (v :: * -> *) a. Vector v a => v a
Vector.empty (m (v a) -> m (v a)) -> m (v a) -> m (v a)
forall a b. (a -> b) -> a -> b
$ m sep -> m end -> m a -> m (v a)
forall (m :: * -> *) (v :: * -> *) a sep end.
(MonadPlus m, Vector v a) =>
m sep -> m end -> m a -> m (v a)
sepEnd1 m sep
getSeparator m end
getEnd m a
getElement

sepEnd1 :: (MonadPlus m, Vector v a) => m sep -> m end -> m a -> m (v a)
sepEnd1 :: m sep -> m end -> m a -> m (v a)
sepEnd1 m sep
getSeparator m end
getEnd m a
getElement =
  do
    a
element <- m a
getElement
    Accumulator a
acc <- Accumulator a -> m (Accumulator a)
collect (a -> Accumulator a -> Accumulator a
forall a. a -> Accumulator a -> Accumulator a
Acc.add a
element Accumulator a
forall a. Accumulator a
Acc.init)
    v a -> m (v a)
forall (m :: * -> *) a. Monad m => a -> m a
return (v a -> m (v a)) -> v a -> m (v a)
forall a b. (a -> b) -> a -> b
$ Accumulator a -> v a
forall (v :: * -> *) a. Vector v a => Accumulator a -> v a
Acc.toVector Accumulator a
acc
  where
    collect :: Accumulator a -> m (Accumulator a)
collect !Accumulator a
acc =
      m end
getEnd m end -> Accumulator a -> m (Accumulator a)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Accumulator a
acc m (Accumulator a) -> m (Accumulator a) -> m (Accumulator a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (m sep
getSeparator m sep -> m a -> m a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m a
getElement m a -> (a -> m (Accumulator a)) -> m (Accumulator a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
e -> Accumulator a -> m (Accumulator a)
collect (a -> Accumulator a -> Accumulator a
forall a. a -> Accumulator a -> Accumulator a
Acc.add a
e Accumulator a
acc))