{-| Module : Parsley.ParserOps Description : Combinators that interact with user-defined functions. License : BSD-3-Clause Maintainer : Jamie Willis Stability : stable This module contains the definition of `ParserOps`, which is used to generalise the representation of user-defined functions to either `Defunc` or `WQ`. @since 2.0.0.0 -} module Parsley.ParserOps (module Parsley.ParserOps) where import Prelude hiding (pure) import Control.Arrow (first) import Parsley.Internal (Parser, WQ, Defunc(BLACK)) import qualified Parsley.Internal as Internal (pure, satisfy, conditional) {-| This typeclass is used to allow abstraction of the representation of user-level functions. See the instances for information on what these representations are. This may be required as a constraint on custom built combinators that make use of one of the minimal required methods of this class. @since 0.1.0.0 -} class ParserOps rep where {-| Lift a value into the parser world without consuming input or having any other effect. @since 0.1.0.0 -} pure :: rep a -> Parser a {-| Attempts to read a single character matching the provided predicate. If it succeeds, the character will be returned and consumed, otherwise the parser will fail having consumed no input. @since 0.1.0.0 -} satisfy :: rep (Char -> Bool) -- ^ The predicate that a character must satisfy to be parsed -> Parser Char -- ^ A parser that matches a single character matching the predicate {-| @conditional fqs p def@ first parses @p@, then it will try each of the predicates in @fqs@ in turn until one of them returns @True@. The corresponding parser for the first predicate that succeeded is then executes, or if none of the predicates succeeded then the @def@ parser is executed. @since 0.1.0.0 -} conditional :: [(rep (a -> Bool), Parser b)] -- ^ A list of predicates and their outcomes -> Parser a -- ^ A parser whose result is used to choose an outcome -> Parser b -- ^ A parser who will be executed if no predicates succeed -> Parser b {-| This is the default representation used for user-level functions and values: plain old code. @since 0.1.0.0 -} instance {-# INCOHERENT #-} x ~ WQ => ParserOps x where pure :: forall a. x a -> Parser a pure = forall (rep :: Type -> Type) a. ParserOps rep => rep a -> Parser a pure forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. WQ a -> Defunc a BLACK satisfy :: x (Char -> Bool) -> Parser Char satisfy = forall (rep :: Type -> Type). ParserOps rep => rep (Char -> Bool) -> Parser Char satisfy forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. WQ a -> Defunc a BLACK conditional :: forall a b. [(x (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b conditional = forall (rep :: Type -> Type) a b. ParserOps rep => [(rep (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b conditional forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a -> b) -> [a] -> [b] map (forall (a :: Type -> Type -> Type) b c d. Arrow a => a b c -> a (b, d) (c, d) first forall a. WQ a -> Defunc a BLACK) {-| This is used to allow defunctionalised versions of many standard Haskell functions to be used directly as an argument to relevant combinators. @since 0.1.0.0 -} instance ParserOps Defunc where pure :: forall a. Defunc a -> Parser a pure = forall a. Defunc a -> Parser a Internal.pure satisfy :: Defunc (Char -> Bool) -> Parser Char satisfy = Defunc (Char -> Bool) -> Parser Char Internal.satisfy conditional :: forall a b. [(Defunc (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b conditional = forall a b. [(Defunc (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b Internal.conditional