{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | Example instantiations of the unified parser over different base monads.
--
-- The primitives in "Circuit.Parser" are polymorphic in the base monad
-- @m@. This module shows how to run the same parser syntax under two
-- different interpretations:
--
--   * 'Identity' — attoparsec-style pure parser
--   * @StateT st (ExceptT e n)@ — megaparsec-style state + errors
module Circuit.Parser.Examples
  ( -- * Runners
    runMega,

    -- * Example parsers
    abOrA,
  )
where

import Circuit.Parser
import Control.Monad.Except (ExceptT, runExceptT)
import Control.Monad.State (StateT, runStateT)

-- | A parser that accepts "ab" or "a".
--
-- Defined once, runnable under any base monad.
abOrA :: (Monad m, Uncons f Char) => Parser m f Char String
abOrA :: forall (m :: * -> *) f.
(Monad m, Uncons f Char) =>
Parser m f Char String
abOrA = String -> Parser m f Char String
forall (m :: * -> *) f s.
(Monad m, Uncons f s, Eq s) =>
[s] -> Parser m f s [s]
string String
"ab" Parser m f Char String
-> Parser m f Char String -> Parser m f Char String
forall a.
Parser m f Char a -> Parser m f Char a -> Parser m f Char a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Parser m f Char String
forall (m :: * -> *) f s.
(Monad m, Uncons f s, Eq s) =>
[s] -> Parser m f s [s]
string String
"a"

-- | Megaparsec-style runner: stateful, error-aware.
--
-- The state @st@ can hold offset, tab width, etc. Errors are returned via
-- @ExceptT e n@.
runMega ::
  forall e st n f a.
  (Monad n, Uncons f Char) =>
  Parser (StateT st (ExceptT e n)) f Char a ->
  f ->
  st ->
  n (Either e (These a f, st))
runMega :: forall e st (n :: * -> *) f a.
(Monad n, Uncons f Char) =>
Parser (StateT st (ExceptT e n)) f Char a
-> f -> st -> n (Either e (These a f, st))
runMega Parser (StateT st (ExceptT e n)) f Char a
p f
f st
st0 = ExceptT e n (These a f, st) -> n (Either e (These a f, st))
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (StateT st (ExceptT e n) (These a f)
-> st -> ExceptT e n (These a f, st)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (Parser (StateT st (ExceptT e n)) f Char a
-> f -> StateT st (ExceptT e n) (These a f)
forall {k} (m :: * -> *) f (s :: k) a.
Monad m =>
Parser m f s a -> f -> m (These a f)
runParser Parser (StateT st (ExceptT e n)) f Char a
p f
f) st
st0)