parsley-core-2.1.0.0: src/ghc/Parsley/Internal/Core/CombinatorAST.hs
{-# LANGUAGE 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.CharPred (CharPred)
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 :: CharPred -> 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 -> 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
Loop :: k () -> k 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 ()
Position :: PosSelector -> Combinator k Int
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
data PosSelector where
Line :: PosSelector
Col :: PosSelector
{-|
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
-- | After this combinator exits, a cut has happened
Cut :: MetaCombinator
-- | This combinator requires a cut from below to respect parsec semantics
RequiresCut :: MetaCombinator
-- | This combinator denotes that within its scope, cut semantics are not enforced
--
-- @since 1.6.0.0
CutImmune :: 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 _ (Let r v) = Let r v
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 (Loop body exit) = Loop (f body) (f exit)
imap f (MakeRegister σ p q) = MakeRegister σ (f p) (f q)
imap _ (GetRegister σ) = GetRegister σ
imap f (PutRegister σ p) = PutRegister σ (f p)
imap _ (Position sel) = Position sel
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 (Loop (Const1 body) (Const1 exit)) = "loop (" . body . ") (" . exit . ")"
alg (MakeRegister σ (Const1 p) (Const1 q)) = "make " . shows σ . " (" . p . ") (" . q . ")"
alg (GetRegister σ) = "get " . shows σ
alg (PutRegister σ (Const1 p)) = "put " . shows σ . " (" . p . ")"
alg (Position Line) = "line"
alg (Position Col) = "col"
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"
show CutImmune = "immune to cuts"
{-# INLINE traverseCombinator #-}
traverseCombinator :: Applicative m => (forall a. f a -> m (k a)) -> Combinator f a -> m (Combinator k a)
traverseCombinator expose (pf :<*>: px) = (:<*>:) <$> expose pf <*> expose px
traverseCombinator expose (p :*>: q) = (:*>:) <$> expose p <*> expose q
traverseCombinator expose (p :<*: q) = (:<*:) <$> expose p <*> expose q
traverseCombinator expose (p :<|>: q) = (:<|>:) <$> expose p <*> expose q
traverseCombinator _ Empty = pure Empty
traverseCombinator expose (Try p) = Try <$> expose p
traverseCombinator expose (LookAhead p) = LookAhead <$> expose p
traverseCombinator expose (NotFollowedBy p) = NotFollowedBy <$> expose p
traverseCombinator expose (Branch b p q) = Branch <$> expose b <*> expose p <*> expose q
traverseCombinator expose (Match p fs qs d) = Match <$> expose p <*> pure fs <*> traverse expose qs <*> expose d
traverseCombinator expose (Loop body exit) = Loop <$> expose body <*> expose exit
traverseCombinator expose (MakeRegister σ p q) = MakeRegister σ <$> expose p <*> expose q
traverseCombinator _ (GetRegister σ) = pure (GetRegister σ)
traverseCombinator expose (PutRegister σ p) = PutRegister σ <$> expose p
traverseCombinator _ (Position sel) = pure (Position sel)
traverseCombinator expose (Debug name p) = Debug name <$> expose p
traverseCombinator _ (Pure x) = pure (Pure x)
traverseCombinator _ (Satisfy f) = pure (Satisfy f)
traverseCombinator _ (Let r v) = pure (Let r v)
traverseCombinator expose (MetaCombinator m p) = MetaCombinator m <$> expose p