parsley-core-1.0.0.0: src/ghc/Parsley/Internal/Core/CombinatorAST.hs
{-# LANGUAGE ApplicativeDo,
OverloadedStrings #-}
module Parsley.Internal.Core.CombinatorAST (module Parsley.Internal.Core.CombinatorAST) where
import Data.Kind (Type)
import Parsley.Internal.Common (IFunctor(..), Fix, Const1(..), cata, intercalateDiff, (:+:))
import Parsley.Internal.Core.Identifiers (MVar, ΣVar)
import Parsley.Internal.Core.Defunc (Defunc)
{-|
The opaque datatype that represents parsers.
@since 0.1.0.0
-}
newtype Parser a = Parser {unParser :: Fix (Combinator :+: ScopeRegister) a}
-- Core datatype
data Combinator (k :: Type -> Type) (a :: Type) where
Pure :: Defunc a -> Combinator k a
Satisfy :: Defunc (Char -> Bool) -> Combinator k Char
(:<*>:) :: k (a -> b) -> k a -> Combinator k b
(:*>:) :: k a -> k b -> Combinator k b
(:<*:) :: k a -> k b -> Combinator k a
(:<|>:) :: k a -> k a -> Combinator k a
Empty :: Combinator k a
Try :: k a -> Combinator k a
LookAhead :: k a -> Combinator k a
Let :: Bool -> MVar a -> k a -> Combinator k a
NotFollowedBy :: k a -> Combinator k ()
Branch :: k (Either a b) -> k (a -> c) -> k (b -> c) -> Combinator k c
Match :: k a -> [Defunc (a -> Bool)] -> [k b] -> k b -> Combinator k b
ChainPre :: k (a -> a) -> k a -> Combinator k a
ChainPost :: k a -> k (a -> a) -> Combinator k a
MakeRegister :: ΣVar a -> k a -> k b -> Combinator k b
GetRegister :: ΣVar a -> Combinator k a
PutRegister :: ΣVar a -> k a -> Combinator k ()
Debug :: String -> k a -> Combinator k a
MetaCombinator :: MetaCombinator -> k a -> Combinator k a
data ScopeRegister (k :: Type -> Type) (a :: Type) where
ScopeRegister :: k a -> (forall r. Reg r a -> k b) -> ScopeRegister k b
{-|
This is an opaque representation of a parsing register. It cannot be manipulated as a user, and the
type parameter @r@ is used to ensure that it cannot leak out of the scope it has been created in.
It is the abstracted representation of a runtime storage location.
@since 0.1.0.0
-}
newtype Reg (r :: Type) a = Reg (ΣVar a)
data MetaCombinator where
Cut :: MetaCombinator
RequiresCut :: MetaCombinator
-- Instances
instance IFunctor Combinator where
imap _ (Pure x) = Pure x
imap _ (Satisfy p) = Satisfy p
imap f (p :<*>: q) = f p :<*>: f q
imap f (p :*>: q) = f p :*>: f q
imap f (p :<*: q) = f p :<*: f q
imap f (p :<|>: q) = f p :<|>: f q
imap _ Empty = Empty
imap f (Try p) = Try (f p)
imap f (LookAhead p) = LookAhead (f p)
imap f (Let r v p) = Let r v (f p)
imap f (NotFollowedBy p) = NotFollowedBy (f p)
imap f (Branch b p q) = Branch (f b) (f p) (f q)
imap f (Match p fs qs d) = Match (f p) fs (map f qs) (f d)
imap f (ChainPre op p) = ChainPre (f op) (f p)
imap f (ChainPost p op) = ChainPost (f p) (f op)
imap f (MakeRegister σ p q) = MakeRegister σ (f p) (f q)
imap _ (GetRegister σ) = GetRegister σ
imap f (PutRegister σ p) = PutRegister σ (f p)
imap f (Debug name p) = Debug name (f p)
imap f (MetaCombinator m p) = MetaCombinator m (f p)
instance Show (Fix Combinator a) where
show = ($ "") . getConst1 . cata (Const1 . alg)
where
alg (Pure x) = "(pure " . shows x . ")"
alg (Satisfy f) = "(satisfy " . shows f . ")"
alg (Const1 pf :<*>: Const1 px) = "(" . pf . " <*> " . px . ")"
alg (Const1 p :*>: Const1 q) = "(" . p . " *> " . q . ")"
alg (Const1 p :<*: Const1 q) = "(" . p . " <* " . q . ")"
alg (Const1 p :<|>: Const1 q) = "(" . p . " <|> " . q . ")"
alg Empty = "empty"
alg (Try (Const1 p)) = "(try " . p . ")"
alg (LookAhead (Const1 p)) = "(lookAhead " . p . ")"
alg (Let False v _) = "(let-bound " . shows v . ")"
alg (Let True v _) = "(rec " . shows v . ")"
alg (NotFollowedBy (Const1 p)) = "(notFollowedBy " . p . ")"
alg (Branch (Const1 b) (Const1 p) (Const1 q)) = "(branch " . b . " " . p . " " . q . ")"
alg (Match (Const1 p) fs qs (Const1 def)) = "(match " . p . " " . shows fs . " [" . intercalateDiff ", " (map getConst1 qs) . "] " . def . ")"
alg (ChainPre (Const1 op) (Const1 p)) = "(chainPre " . op . " " . p . ")"
alg (ChainPost (Const1 p) (Const1 op)) = "(chainPost " . p . " " . op . ")"
alg (MakeRegister σ (Const1 p) (Const1 q)) = "(make " . shows σ . " " . p . " " . q . ")"
alg (GetRegister σ) = "(get " . shows σ . ")"
alg (PutRegister σ (Const1 p)) = "(put " . shows σ . " " . p . ")"
alg (Debug _ (Const1 p)) = p
alg (MetaCombinator m (Const1 p)) = p . " [" . shows m . "]"
instance IFunctor ScopeRegister where
imap f (ScopeRegister p g) = ScopeRegister (f p) (f . g)
instance Show MetaCombinator where
show Cut = "coins after"
show RequiresCut = "requires cut"
{-# INLINE traverseCombinator #-}
traverseCombinator :: Applicative m => (forall a. f a -> m (k a)) -> Combinator f a -> m (Combinator k a)
traverseCombinator expose (pf :<*>: px) = do pf' <- expose pf; px' <- expose px; pure (pf' :<*>: px')
traverseCombinator expose (p :*>: q) = do p' <- expose p; q' <- expose q; pure (p' :*>: q')
traverseCombinator expose (p :<*: q) = do p' <- expose p; q' <- expose q; pure (p' :<*: q')
traverseCombinator expose (p :<|>: q) = do p' <- expose p; q' <- expose q; pure (p' :<|>: q')
traverseCombinator _ Empty = do pure Empty
traverseCombinator expose (Try p) = do p' <- expose p; pure (Try p')
traverseCombinator expose (LookAhead p) = do p' <- expose p; pure (LookAhead p')
traverseCombinator expose (NotFollowedBy p) = do p' <- expose p; pure (NotFollowedBy p')
traverseCombinator expose (Branch b p q) = do b' <- expose b; p' <- expose p; q' <- expose q; pure (Branch b' p' q')
traverseCombinator expose (Match p fs qs d) = do p' <- expose p; qs' <- traverse expose qs; d' <- expose d; pure (Match p' fs qs' d')
traverseCombinator expose (ChainPre op p) = do op' <- expose op; p' <- expose p; pure (ChainPre op' p')
traverseCombinator expose (ChainPost p op) = do p' <- expose p; op' <- expose op; pure (ChainPost p' op')
traverseCombinator expose (MakeRegister σ p q) = do p' <- expose p; q' <- expose q; pure (MakeRegister σ p' q')
traverseCombinator _ (GetRegister σ) = do pure (GetRegister σ)
traverseCombinator expose (PutRegister σ p) = do p' <- expose p; pure (PutRegister σ p')
traverseCombinator expose (Debug name p) = do p' <- expose p; pure (Debug name p')
traverseCombinator _ (Pure x) = do pure (Pure x)
traverseCombinator _ (Satisfy f) = do pure (Satisfy f)
traverseCombinator expose (Let r v p) = do p' <- expose p; pure (Let r v p')
traverseCombinator expose (MetaCombinator m p) = do p' <- expose p; pure (MetaCombinator m p')