-- |
-- 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 :: forall (m :: * -> *) (v :: * -> *) a.
(MonadPlus m, Vector v a) =>
m a -> m (v a)
many m a
getElement =
  forall (m :: * -> *) a.
MonadPlus m =>
Accumulator a -> m a -> m (Accumulator a)
accMany forall a. Accumulator a
Acc.init m a
getElement forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> 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 :: forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m a -> m sep -> m (v a)
sepBy = forall a b c. (a -> b -> c) -> b -> a -> c
flip 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 :: forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m a -> m sep -> m (v a)
sepBy1 = forall a b c. (a -> b -> c) -> b -> a -> c
flip 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 :: forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m sep -> m a -> m (v a)
sep m sep
getSeparator m a
getElement =
  forall (m :: * -> *) a. Alternative m => a -> m a -> m a
orPure forall (v :: * -> *) a. Vector v a => v a
Vector.empty forall a b. (a -> b) -> a -> b
$ 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 :: forall (m :: * -> *) (v :: * -> *) a sep.
(MonadPlus m, Vector v a) =>
m sep -> m a -> m (v a)
sep1 m sep
getSeparator m a
getElement =
  do
    a
element <- m a
getElement
    forall (v :: * -> *) a. Vector v a => Accumulator a -> v a
Acc.toVector forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a.
MonadPlus m =>
Accumulator a -> m a -> m (Accumulator a)
accMany (forall a. a -> Accumulator a -> Accumulator a
Acc.add a
element forall a. Accumulator a
Acc.init) (m sep
getSeparator 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 :: forall (m :: * -> *) (v :: * -> *) a sep end.
(MonadPlus m, Vector v a) =>
m sep -> m end -> m a -> m (v a)
sepEnd m sep
getSeparator m end
getEnd m a
getElement =
  forall (m :: * -> *) a. Alternative m => a -> m a -> m a
orPure forall (v :: * -> *) a. Vector v a => v a
Vector.empty forall a b. (a -> b) -> a -> b
$ 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 :: 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 =
  do
    a
element <- m a
getElement
    Accumulator a
acc <- Accumulator a -> m (Accumulator a)
collect (forall a. a -> Accumulator a -> Accumulator a
Acc.add a
element forall a. Accumulator a
Acc.init)
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ 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 forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Accumulator a
acc forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (m sep
getSeparator forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m a
getElement forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
e -> Accumulator a -> m (Accumulator a)
collect (forall a. a -> Accumulator a -> Accumulator a
Acc.add a
e Accumulator a
acc))