    \begin{code}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE MultiParamTypeClasses      #-}
    {-# LANGUAGE FunctionalDependencies     #-}
    {-# LANGUAGE CPP                        #-}
    #if __GLASGOW_HASKELL__ >= 800
    {-# LANGUAGE TemplateHaskellQuotes      #-}
    {-# LANGUAGE DeriveLift                 #-}
    {-# LANGUAGE StandaloneDeriving         #-}
    #else
    {-# LANGUAGE QuasiQuotes                #-}
    {-# LANGUAGE TemplateHaskell            #-}
    #endif

    module Text.RE.REOptions
      (
      -- * The Options Tutorial
      -- $tutorial

      -- * 'SimpleREOptions'
        SimpleREOptions(..)
      -- * 'REOptions_'
      , REOptions_(..)
      -- * The Macro Tables
      , Macros
      , MacroID(..)
      , emptyMacros
      ) where

    import qualified Data.HashMap.Strict        as HM
    import           Data.Hashable
    import           Data.String
    import           Language.Haskell.TH.Syntax
    \end{code}

    The RE Options
    --------------

    \begin{code}
    -- | the default API uses these simple, universal RE options,
    -- which get auto-converted into the appropriate back-end 'REOptions_'
    data SimpleREOptions
      = MultilineSensitive        -- ^ case-sensitive with ^ and $ matching the start and end of a line
      | MultilineInsensitive      -- ^ case-insensitive with ^ and $ matsh the start and end of a line
      | BlockSensitive            -- ^ case-sensitive with ^ and $ matching the start and end of the input text
      | BlockInsensitive          -- ^ case-insensitive with ^ and $ matching the start and end of the input text
      deriving (SimpleREOptions
    SimpleREOptions -> SimpleREOptions -> Bounded SimpleREOptions
    forall a. a -> a -> Bounded a
    $cminBound :: SimpleREOptions
    minBound :: SimpleREOptions
    $cmaxBound :: SimpleREOptions
    maxBound :: SimpleREOptions
    Bounded,Int -> SimpleREOptions
    SimpleREOptions -> Int
    SimpleREOptions -> [SimpleREOptions]
    SimpleREOptions -> SimpleREOptions
    SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    SimpleREOptions
    -> SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    (SimpleREOptions -> SimpleREOptions)
    -> (SimpleREOptions -> SimpleREOptions)
    -> (Int -> SimpleREOptions)
    -> (SimpleREOptions -> Int)
    -> (SimpleREOptions -> [SimpleREOptions])
    -> (SimpleREOptions -> SimpleREOptions -> [SimpleREOptions])
    -> (SimpleREOptions -> SimpleREOptions -> [SimpleREOptions])
    -> (SimpleREOptions
        -> SimpleREOptions -> SimpleREOptions -> [SimpleREOptions])
    -> Enum SimpleREOptions
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    $csucc :: SimpleREOptions -> SimpleREOptions
    succ :: SimpleREOptions -> SimpleREOptions
    $cpred :: SimpleREOptions -> SimpleREOptions
    pred :: SimpleREOptions -> SimpleREOptions
    $ctoEnum :: Int -> SimpleREOptions
    toEnum :: Int -> SimpleREOptions
    $cfromEnum :: SimpleREOptions -> Int
    fromEnum :: SimpleREOptions -> Int
    $cenumFrom :: SimpleREOptions -> [SimpleREOptions]
    enumFrom :: SimpleREOptions -> [SimpleREOptions]
    $cenumFromThen :: SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    enumFromThen :: SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    $cenumFromTo :: SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    enumFromTo :: SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    $cenumFromThenTo :: SimpleREOptions
    -> SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    enumFromThenTo :: SimpleREOptions
    -> SimpleREOptions -> SimpleREOptions -> [SimpleREOptions]
    Enum,SimpleREOptions -> SimpleREOptions -> Bool
    (SimpleREOptions -> SimpleREOptions -> Bool)
    -> (SimpleREOptions -> SimpleREOptions -> Bool)
    -> Eq SimpleREOptions
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SimpleREOptions -> SimpleREOptions -> Bool
    == :: SimpleREOptions -> SimpleREOptions -> Bool
    $c/= :: SimpleREOptions -> SimpleREOptions -> Bool
    /= :: SimpleREOptions -> SimpleREOptions -> Bool
    Eq,Eq SimpleREOptions
    Eq SimpleREOptions =>
    (SimpleREOptions -> SimpleREOptions -> Ordering)
    -> (SimpleREOptions -> SimpleREOptions -> Bool)
    -> (SimpleREOptions -> SimpleREOptions -> Bool)
    -> (SimpleREOptions -> SimpleREOptions -> Bool)
    -> (SimpleREOptions -> SimpleREOptions -> Bool)
    -> (SimpleREOptions -> SimpleREOptions -> SimpleREOptions)
    -> (SimpleREOptions -> SimpleREOptions -> SimpleREOptions)
    -> Ord SimpleREOptions
    SimpleREOptions -> SimpleREOptions -> Bool
    SimpleREOptions -> SimpleREOptions -> Ordering
    SimpleREOptions -> SimpleREOptions -> SimpleREOptions
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: SimpleREOptions -> SimpleREOptions -> Ordering
    compare :: SimpleREOptions -> SimpleREOptions -> Ordering
    $c< :: SimpleREOptions -> SimpleREOptions -> Bool
    < :: SimpleREOptions -> SimpleREOptions -> Bool
    $c<= :: SimpleREOptions -> SimpleREOptions -> Bool
    <= :: SimpleREOptions -> SimpleREOptions -> Bool
    $c> :: SimpleREOptions -> SimpleREOptions -> Bool
    > :: SimpleREOptions -> SimpleREOptions -> Bool
    $c>= :: SimpleREOptions -> SimpleREOptions -> Bool
    >= :: SimpleREOptions -> SimpleREOptions -> Bool
    $cmax :: SimpleREOptions -> SimpleREOptions -> SimpleREOptions
    max :: SimpleREOptions -> SimpleREOptions -> SimpleREOptions
    $cmin :: SimpleREOptions -> SimpleREOptions -> SimpleREOptions
    min :: SimpleREOptions -> SimpleREOptions -> SimpleREOptions
    Ord,Int -> SimpleREOptions -> ShowS
    [SimpleREOptions] -> ShowS
    SimpleREOptions -> String
    (Int -> SimpleREOptions -> ShowS)
    -> (SimpleREOptions -> String)
    -> ([SimpleREOptions] -> ShowS)
    -> Show SimpleREOptions
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> SimpleREOptions -> ShowS
    showsPrec :: Int -> SimpleREOptions -> ShowS
    $cshow :: SimpleREOptions -> String
    show :: SimpleREOptions -> String
    $cshowList :: [SimpleREOptions] -> ShowS
    showList :: [SimpleREOptions] -> ShowS
    Show)
    \end{code}

    \begin{code}
    -- | we need to use this in the quasi quoters to specify @SimpleREOptions@
    -- selected by the quasi quoter
    deriving instance Lift SimpleREOptions
    \end{code}

    \begin{code}
    -- | the general options for an RE are dependent on which back end is
    -- being used and are parameterised over the @RE@ type for the back end,
    -- and its @CompOption@ and @ExecOption@ types (the compile-time and
    -- execution time options, respectively); each back end will define an
    -- @REOptions@ type that fills out these three type parameters with the
    -- appropriate types (see, for example, "Text.RE.TDFA")
    data REOptions_ r c e =
      REOptions
        { forall r c e. REOptions_ r c e -> Macros r
    optionsMacs :: !(Macros r)    -- ^ the available TestBench RE macros
        , forall r c e. REOptions_ r c e -> c
    optionsComp :: !c             -- ^ the back end compile-time options
        , forall r c e. REOptions_ r c e -> e
    optionsExec :: !e             -- ^ the back end execution-time options
        }
      deriving (Int -> REOptions_ r c e -> ShowS
    [REOptions_ r c e] -> ShowS
    REOptions_ r c e -> String
    (Int -> REOptions_ r c e -> ShowS)
    -> (REOptions_ r c e -> String)
    -> ([REOptions_ r c e] -> ShowS)
    -> Show (REOptions_ r c e)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall r c e.
    (Show r, Show c, Show e) =>
    Int -> REOptions_ r c e -> ShowS
    forall r c e.
    (Show r, Show c, Show e) =>
    [REOptions_ r c e] -> ShowS
    forall r c e.
    (Show r, Show c, Show e) =>
    REOptions_ r c e -> String
    $cshowsPrec :: forall r c e.
    (Show r, Show c, Show e) =>
    Int -> REOptions_ r c e -> ShowS
    showsPrec :: Int -> REOptions_ r c e -> ShowS
    $cshow :: forall r c e.
    (Show r, Show c, Show e) =>
    REOptions_ r c e -> String
    show :: REOptions_ r c e -> String
    $cshowList :: forall r c e.
    (Show r, Show c, Show e) =>
    [REOptions_ r c e] -> ShowS
    showList :: [REOptions_ r c e] -> ShowS
    Show)
    \end{code}

    The Macro Tables
    ----------------

    \begin{code}
    -- | our macro tables are parameterised over the back end @RE@ type and
    -- and just associate each @MacroID@ with an @RE@ (which may in turn
    -- contain macros to be expanded)
    type Macros r = HM.HashMap MacroID r
    \end{code}

    \begin{code}
    -- | @MacroID@ is just a wrapped @String@ type with an @IsString@
    -- instance
    newtype MacroID =
        MacroID { MacroID -> String
    getMacroID :: String }
      deriving (String -> MacroID
    (String -> MacroID) -> IsString MacroID
    forall a. (String -> a) -> IsString a
    $cfromString :: String -> MacroID
    fromString :: String -> MacroID
    IsString,Eq MacroID
    Eq MacroID =>
    (MacroID -> MacroID -> Ordering)
    -> (MacroID -> MacroID -> Bool)
    -> (MacroID -> MacroID -> Bool)
    -> (MacroID -> MacroID -> Bool)
    -> (MacroID -> MacroID -> Bool)
    -> (MacroID -> MacroID -> MacroID)
    -> (MacroID -> MacroID -> MacroID)
    -> Ord MacroID
    MacroID -> MacroID -> Bool
    MacroID -> MacroID -> Ordering
    MacroID -> MacroID -> MacroID
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: MacroID -> MacroID -> Ordering
    compare :: MacroID -> MacroID -> Ordering
    $c< :: MacroID -> MacroID -> Bool
    < :: MacroID -> MacroID -> Bool
    $c<= :: MacroID -> MacroID -> Bool
    <= :: MacroID -> MacroID -> Bool
    $c> :: MacroID -> MacroID -> Bool
    > :: MacroID -> MacroID -> Bool
    $c>= :: MacroID -> MacroID -> Bool
    >= :: MacroID -> MacroID -> Bool
    $cmax :: MacroID -> MacroID -> MacroID
    max :: MacroID -> MacroID -> MacroID
    $cmin :: MacroID -> MacroID -> MacroID
    min :: MacroID -> MacroID -> MacroID
    Ord,MacroID -> MacroID -> Bool
    (MacroID -> MacroID -> Bool)
    -> (MacroID -> MacroID -> Bool) -> Eq MacroID
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: MacroID -> MacroID -> Bool
    == :: MacroID -> MacroID -> Bool
    $c/= :: MacroID -> MacroID -> Bool
    /= :: MacroID -> MacroID -> Bool
    Eq,Int -> MacroID -> ShowS
    [MacroID] -> ShowS
    MacroID -> String
    (Int -> MacroID -> ShowS)
    -> (MacroID -> String) -> ([MacroID] -> ShowS) -> Show MacroID
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> MacroID -> ShowS
    showsPrec :: Int -> MacroID -> ShowS
    $cshow :: MacroID -> String
    show :: MacroID -> String
    $cshowList :: [MacroID] -> ShowS
    showList :: [MacroID] -> ShowS
    Show)
    \end{code}

    \begin{code}
    -- | @MacroID@ is used with @HM.HashMap@ to build macro lookup tables
    instance Hashable MacroID where
      hashWithSalt :: Int -> MacroID -> Int
    hashWithSalt Int
    i = Int -> String -> Int
    forall a. Hashable a => Int -> a -> Int
    hashWithSalt Int
    i (String -> Int) -> (MacroID -> String) -> MacroID -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MacroID -> String
    getMacroID
    \end{code}

    \begin{code}
    -- | a macro table containing no entries
    emptyMacros :: Macros r
    emptyMacros :: forall r. Macros r
    emptyMacros = HashMap MacroID r
    forall k v. HashMap k v
    HM.empty
    \end{code}

    \begin{code}
    -- $tutorial
    -- This API module provides the generic types used to specify the options
    -- when compiling REs for each of the backl ends.
    --
    -- See the tutorials at http://re-tutorial-options.regex.uk
    \end{code}