module
Test.Chuchu.Types
(ChuchuParser (..), Chuchu, ChuchuM (Given, When, Then, And, But), runChuchu)
where
import Control.Applicative (Applicative((<*)), Alternative((<|>)), (<$>))
import Control.Monad (MonadPlus)
import Data.String (IsString(..))
import qualified Text.Parsec as P
import qualified Text.Parsec.Text as P (Parser)
newtype ChuchuParser a = ChuchuParser (P.Parser a)
deriving (Functor, Applicative, Alternative, Monad, MonadPlus)
instance (a ~ ()) => IsString (ChuchuParser a) where
fromString s = ChuchuParser (P.try (P.string s) >> return ())
type Chuchu m = ChuchuM m ()
data ChuchuM m a where
Given :: ChuchuParser a -> (a -> m ()) -> ChuchuM m ()
When :: ChuchuParser a -> (a -> m ()) -> ChuchuM m ()
Then :: ChuchuParser a -> (a -> m ()) -> ChuchuM m ()
And :: ChuchuParser a -> (a -> m ()) -> ChuchuM m ()
But :: ChuchuParser a -> (a -> m ()) -> ChuchuM m ()
Nil :: ChuchuM m a
Cons :: ChuchuM m b -> ChuchuM m a -> ChuchuM m a
instance Monad (ChuchuM m) where
return _ = Nil
step >>= k = Cons step $ k $ error "(>>=): ChuchuM does not support 'return'."
runChuchu :: ChuchuM m a -> P.Parser (m ())
runChuchu Nil = P.unexpected "Unknown step"
runChuchu (Cons cc1 cc2) = runChuchu cc1 <|> runChuchu cc2
runChuchu (Given p f) = apply p f
runChuchu (When p f) = apply p f
runChuchu (Then p f) = apply p f
runChuchu (And p f) = apply p f
runChuchu (But p f) = apply p f
apply :: ChuchuParser a -> (a -> m ()) -> P.Parser (m ())
apply (ChuchuParser p) f = P.try $ f <$> p <* P.eof