{-# LANGUAGE NoImplicitPrelude          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE TypeSynonymInstances       #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE CPP                        #-}
#if __GLASGOW_HASKELL__ >= 800
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
{-# LANGUAGE TemplateHaskellQuotes      #-}
#else
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE TemplateHaskell            #-}
#endif
{-# OPTIONS_GHC -fno-warn-orphans               #-}
{-# OPTIONS_GHC -fno-warn-unused-imports        #-}

module Text.RE.ZeInternals.TDFA
  ( -- * About
    -- $about

    -- * RE Type
    RE
  , regexType
  , reOptions
  , reSource
  , reCaptureNames
  , reRegex
  -- * IsOptions Class and REOptions Type
  , IsOption(..)
  , REOptions
  , defaultREOptions
  , noPreludeREOptions
  , unpackSimpleREOptions
  -- * Compiling Regular Expressions
  , compileRegex
  , compileRegexWith
  , compileRegexWithOptions
  , compileRegexWithOptionsForQQ
  -- * Compiling Search-Replace Templates
  , compileSearchReplace
  , compileSearchReplaceWith
  , compileSearchReplaceWithOptions
  -- * Escaping String
  , escape
  , escapeWith
  , escapeWithOptions
  , escapeREString
  -- * Macros Standard Environment
  , prelude
  , preludeEnv
  , preludeTestsFailing
  , preludeTable
  , preludeSummary
  , preludeSources
  , preludeSource
  -- * The Quasi Quoters
  , re
  , reMS
  , reMI
  , reBS
  , reBI
  , reMultilineSensitive
  , reMultilineInsensitive
  , reBlockSensitive
  , reBlockInsensitive
  , re_
  , cp
  ) where

import           Control.Monad.Fail
import           Data.Functor.Identity
import           Language.Haskell.TH
import           Language.Haskell.TH.Quote
import           Prelude.Compat                       hiding (fail)
import           Text.RE.REOptions
import           Text.RE.Replace
import           Text.RE.TestBench
import           Text.RE.Tools
import           Text.RE.ZeInternals
import           Text.RE.ZeInternals.Types.Poss
import           Text.Regex.TDFA


-- | the RE type for this back end representing a well-formed, compiled
-- RE
data RE =
  RE
    { RE -> REOptions
_re_options :: !REOptions
    , RE -> String
_re_source  :: !String
    , RE -> CaptureNames
_re_cnames  :: !CaptureNames
    , RE -> Regex
_re_regex   :: !Regex
    }

-- | some functions in the "Text.RE.TestBench" need the back end to
-- be passed dynamically as a 'RegexType' parameters: use 'regexType'
-- for this
regexType :: RegexType
regexType :: RegexType
regexType =
  TestBenchMatcher -> RegexType
mkTDFA (TestBenchMatcher -> RegexType) -> TestBenchMatcher -> RegexType
forall a b. (a -> b) -> a -> b
$ \String
txt MacroEnv
env MacroDescriptor
md -> String
txt String -> String -> Matches String
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
 RegexContext Regex source1 target) =>
source1 -> source -> target
=~ RegexType -> WithCaptures -> MacroEnv -> MacroDescriptor -> String
mdRegexSource RegexType
regexType WithCaptures
ExclCaptures MacroEnv
env MacroDescriptor
md

-- | extract the 'REOptions' from the @RE@
reOptions :: RE -> REOptions
reOptions :: RE -> REOptions
reOptions = RE -> REOptions
_re_options

-- | extract the RE source string from the @RE@
reSource :: RE -> String
reSource :: RE -> String
reSource = RE -> String
_re_source

-- | extract the 'CaptureNames' from the @RE@
reCaptureNames :: RE -> CaptureNames
reCaptureNames :: RE -> CaptureNames
reCaptureNames = RE -> CaptureNames
_re_cnames

-- | extract the back end compiled 'Regex' type from the @RE@
reRegex :: RE -> Regex
reRegex :: RE -> Regex
reRegex = RE -> Regex
_re_regex


------------------------------------------------------------------------
-- IsOption & REOptions
------------------------------------------------------------------------

-- | a number of types can be used to encode 'REOptions_', each of which
-- is made a member of this class
class IsOption o where
  -- | convert the @o@ type into an @REOptions@
  makeREOptions :: o -> REOptions

-- | and the REOptions for this back end (see "Text.RE.REOptions"
-- for details)
type REOptions = REOptions_ RE CompOption ExecOption

instance IsOption SimpleREOptions where
  makeREOptions :: SimpleREOptions -> REOptions
makeREOptions    = SimpleREOptions -> REOptions
unpackSimpleREOptions

instance IsOption (Macros RE) where
  makeREOptions :: Macros RE -> REOptions
makeREOptions Macros RE
ms = Macros RE -> CompOption -> ExecOption -> REOptions
forall r c e. Macros r -> c -> e -> REOptions_ r c e
REOptions Macros RE
ms CompOption
def_comp_option ExecOption
def_exec_option

instance IsOption CompOption where
  makeREOptions :: CompOption -> REOptions
makeREOptions CompOption
co = Macros RE -> CompOption -> ExecOption -> REOptions
forall r c e. Macros r -> c -> e -> REOptions_ r c e
REOptions Macros RE
prelude CompOption
co ExecOption
def_exec_option

instance IsOption ExecOption where
  makeREOptions :: ExecOption -> REOptions
makeREOptions ExecOption
eo = Macros RE -> CompOption -> ExecOption -> REOptions
forall r c e. Macros r -> c -> e -> REOptions_ r c e
REOptions Macros RE
prelude CompOption
def_comp_option ExecOption
eo

instance IsOption REOptions where
  makeREOptions :: REOptions -> REOptions
makeREOptions    = REOptions -> REOptions
forall a. a -> a
id

instance IsOption () where
  makeREOptions :: () -> REOptions
makeREOptions ()
_  = SimpleREOptions -> REOptions
unpackSimpleREOptions SimpleREOptions
forall a. Bounded a => a
minBound

-- | the default 'REOptions'
defaultREOptions :: REOptions
defaultREOptions :: REOptions
defaultREOptions = SimpleREOptions -> REOptions
forall o. IsOption o => o -> REOptions
makeREOptions (SimpleREOptions
forall a. Bounded a => a
minBound::SimpleREOptions)

-- | the default 'REOptions' but with no RE macros defined
noPreludeREOptions :: REOptions
noPreludeREOptions :: REOptions
noPreludeREOptions = REOptions
defaultREOptions { optionsMacs :: Macros RE
optionsMacs = Macros RE
forall r. Macros r
emptyMacros }

-- | convert a universal 'SimpleReOptions' into the 'REOptions' used
-- by this back end
unpackSimpleREOptions :: SimpleREOptions -> REOptions
unpackSimpleREOptions :: SimpleREOptions -> REOptions
unpackSimpleREOptions SimpleREOptions
sro =
  REOptions :: forall r c e. Macros r -> c -> e -> REOptions_ r c e
REOptions
    { optionsMacs :: Macros RE
optionsMacs = Macros RE
prelude
    , optionsComp :: CompOption
optionsComp = CompOption
comp
    , optionsExec :: ExecOption
optionsExec = ExecOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
execOpt
defaultExecOpt
    }
  where
    comp :: CompOption
comp = CompOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
compOpt
defaultCompOpt
      { caseSensitive :: Bool
caseSensitive = Bool
cs
      , multiline :: Bool
multiline     = Bool
ml
      }

    (Bool
ml,Bool
cs) = case SimpleREOptions
sro of
        SimpleREOptions
MultilineSensitive    -> (,) Bool
True  Bool
True
        SimpleREOptions
MultilineInsensitive  -> (,) Bool
True  Bool
False
        SimpleREOptions
BlockSensitive        -> (,) Bool
False Bool
True
        SimpleREOptions
BlockInsensitive      -> (,) Bool
False Bool
False


------------------------------------------------------------------------
-- Compiling Regular Expressions
------------------------------------------------------------------------

-- | compile a 'String' into a 'RE' with the default options,
-- generating an error if the RE is not well formed
compileRegex :: (Functor m,Monad m,MonadFail m) => String -> m RE
compileRegex :: String -> m RE
compileRegex = SimpleREOptions -> String -> m RE
forall (m :: * -> *).
(Functor m, Monad m, MonadFail m) =>
SimpleREOptions -> String -> m RE
compileRegexWith SimpleREOptions
forall a. Bounded a => a
minBound

-- | compile a 'String' into a 'RE' using the given @SimpleREOptions@,
-- generating an error if the RE is not well formed
compileRegexWith :: (Functor m,Monad m,MonadFail m) => SimpleREOptions -> String -> m RE
compileRegexWith :: SimpleREOptions -> String -> m RE
compileRegexWith = SimpleREOptions -> String -> m RE
forall o (m :: * -> *).
(IsOption o, Functor m, Monad m, MonadFail m) =>
o -> String -> m RE
compileRegexWithOptions

-- | compile a 'String' into a 'RE' using the given @SimpleREOptions@,
-- generating an error if the RE is not well formed
compileRegexWithOptions :: (IsOption o, Functor m, Monad   m, MonadFail m)
                        => o
                        -> String
                        -> m RE
compileRegexWithOptions :: o -> String -> m RE
compileRegexWithOptions = RegexParseMode -> REOptions -> String -> m RE
forall (m :: * -> *).
(Functor m, MonadFail m, Monad m) =>
RegexParseMode -> REOptions -> String -> m RE
compileRegex_ RegexParseMode
RPM_raw (REOptions -> String -> m RE)
-> (o -> REOptions) -> o -> String -> m RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. o -> REOptions
forall o. IsOption o => o -> REOptions
makeREOptions

-- | compile a 'String' into a 'RE' for q quasi quoter, using the given
-- @SimpleREOptions@, generating an error if the RE is not well formed
compileRegexWithOptionsForQQ :: (IsOption o, Functor m, Monad   m,MonadFail m)
                             => o
                             -> String
                             -> m RE
compileRegexWithOptionsForQQ :: o -> String -> m RE
compileRegexWithOptionsForQQ = RegexParseMode -> REOptions -> String -> m RE
forall (m :: * -> *).
(Functor m, MonadFail m, Monad m) =>
RegexParseMode -> REOptions -> String -> m RE
compileRegex_ RegexParseMode
RPM_qq (REOptions -> String -> m RE)
-> (o -> REOptions) -> o -> String -> m RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. o -> REOptions
forall o. IsOption o => o -> REOptions
makeREOptions


------------------------------------------------------------------------
-- Compiling Search Replace Templates
------------------------------------------------------------------------

-- | compile a SearchReplace template generating errors if the RE or
-- the template are not well formed, all capture references being checked
compileSearchReplace :: (Monad m,MonadFail m,Functor m,IsRegex RE s)
                     => String
                     -> String
                     -> m (SearchReplace RE s)
compileSearchReplace :: String -> String -> m (SearchReplace RE s)
compileSearchReplace = SimpleREOptions -> String -> String -> m (SearchReplace RE s)
forall (m :: * -> *) s.
(Monad m, MonadFail m, Functor m, IsRegex RE s) =>
SimpleREOptions -> String -> String -> m (SearchReplace RE s)
compileSearchReplaceWith SimpleREOptions
forall a. Bounded a => a
minBound

-- | compile a SearchReplace template, with simple options, generating
-- errors if the RE or the template are not well formed, all capture
-- references being checked
compileSearchReplaceWith :: (Monad m,MonadFail m,Functor m,IsRegex RE s)
                         => SimpleREOptions
                         -> String
                         -> String
                         -> m (SearchReplace RE s)
compileSearchReplaceWith :: SimpleREOptions -> String -> String -> m (SearchReplace RE s)
compileSearchReplaceWith SimpleREOptions
sro = (String -> s)
-> (String -> Either String RE)
-> String
-> String
-> m (SearchReplace RE s)
forall (m :: * -> *) s re.
(Monad m, MonadFail m, Functor m) =>
(String -> s)
-> (String -> Either String re)
-> String
-> String
-> m (SearchReplace re s)
compileSearchAndReplace_ String -> s
forall a. Replace a => String -> a
packR ((String -> Either String RE)
 -> String -> String -> m (SearchReplace RE s))
-> (String -> Either String RE)
-> String
-> String
-> m (SearchReplace RE s)
forall a b. (a -> b) -> a -> b
$ Poss RE -> Either String RE
forall a. Poss a -> Either String a
poss2either (Poss RE -> Either String RE)
-> (String -> Poss RE) -> String -> Either String RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimpleREOptions -> String -> Poss RE
forall (m :: * -> *).
(Functor m, Monad m, MonadFail m) =>
SimpleREOptions -> String -> m RE
compileRegexWith SimpleREOptions
sro

-- | compile a SearchReplace template, with general options, generating
-- errors if the RE or the template are not well formed, all capture
-- references being checked
compileSearchReplaceWithOptions :: (Monad m,MonadFail m,Functor m,IsRegex RE s)
                                => REOptions
                                -> String
                                -> String
                                -> m (SearchReplace RE s)
compileSearchReplaceWithOptions :: REOptions -> String -> String -> m (SearchReplace RE s)
compileSearchReplaceWithOptions REOptions
os = (String -> s)
-> (String -> Either String RE)
-> String
-> String
-> m (SearchReplace RE s)
forall (m :: * -> *) s re.
(Monad m, MonadFail m, Functor m) =>
(String -> s)
-> (String -> Either String re)
-> String
-> String
-> m (SearchReplace re s)
compileSearchAndReplace_ String -> s
forall a. Replace a => String -> a
packR ((String -> Either String RE)
 -> String -> String -> m (SearchReplace RE s))
-> (String -> Either String RE)
-> String
-> String
-> m (SearchReplace RE s)
forall a b. (a -> b) -> a -> b
$ Poss RE -> Either String RE
forall a. Poss a -> Either String a
poss2either (Poss RE -> Either String RE)
-> (String -> Poss RE) -> String -> Either String RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. REOptions -> String -> Poss RE
forall o (m :: * -> *).
(IsOption o, Functor m, Monad m, MonadFail m) =>
o -> String -> m RE
compileRegexWithOptions REOptions
os


------------------------------------------------------------------------
-- Escaping Strings
------------------------------------------------------------------------

-- | convert a string into a RE that matches that string, and apply it
-- to an argument continuation function to make up the RE string to be
-- compiled; e.g., to compile a RE that will only match the string:
--
--  @maybe undefined id . escape ((\"^\"++) . (++\"$\"))@
--
escape :: (Functor m,Monad m,MonadFail m)
       => (String->String)
       -> String
       -> m RE
escape :: (String -> String) -> String -> m RE
escape = SimpleREOptions -> (String -> String) -> String -> m RE
forall (m :: * -> *).
(Functor m, Monad m, MonadFail m) =>
SimpleREOptions -> (String -> String) -> String -> m RE
escapeWith SimpleREOptions
forall a. Bounded a => a
minBound

-- | a variant of 'escape' where the 'SimpleREOptions' are specified
escapeWith :: (Functor m,Monad m,MonadFail m)
           => SimpleREOptions
           -> (String->String)
           -> String
           -> m RE
escapeWith :: SimpleREOptions -> (String -> String) -> String -> m RE
escapeWith = SimpleREOptions -> (String -> String) -> String -> m RE
forall o (m :: * -> *).
(IsOption o, Functor m, Monad m, MonadFail m) =>
o -> (String -> String) -> String -> m RE
escapeWithOptions

-- | a variant of 'escapeWith' that allows an 'IsOption' RE option
-- to be specified
escapeWithOptions :: ( IsOption o, Functor m, Monad m,MonadFail m)
                  => o
                  -> (String->String)
                  -> String
                  -> m RE
escapeWithOptions :: o -> (String -> String) -> String -> m RE
escapeWithOptions o
o String -> String
f = o -> String -> m RE
forall o (m :: * -> *).
(IsOption o, Functor m, Monad m, MonadFail m) =>
o -> String -> m RE
compileRegexWithOptions o
o (String -> m RE) -> (String -> String) -> String -> m RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
f (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
escapeREString


------------------------------------------------------------------------
-- Macro Standard Environment
------------------------------------------------------------------------

-- | the standard table of 'Macros' used to compile REs (which can be
-- extended or replace: see "Text.RE.TestBench")
prelude :: Macros RE
prelude :: Macros RE
prelude = Identity (Macros RE) -> Macros RE
forall a. Identity a -> a
runIdentity (Identity (Macros RE) -> Macros RE)
-> Identity (Macros RE) -> Macros RE
forall a b. (a -> b) -> a -> b
$ (String -> Identity RE)
-> RegexType -> WithCaptures -> Identity (Macros RE)
forall (m :: * -> *) r.
(Monad m, Functor m) =>
(String -> m r) -> RegexType -> WithCaptures -> m (Macros r)
preludeMacros String -> Identity RE
mk RegexType
regexType WithCaptures
ExclCaptures
  where
    mk :: String -> Identity RE
mk = RE -> Identity RE
forall a. a -> Identity a
Identity (RE -> Identity RE) -> (String -> RE) -> String -> Identity RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RegexParseMode -> REOptions -> String -> RE
unsafeCompileRegex_ RegexParseMode
RPM_raw REOptions
noPreludeREOptions

-- | the standard 'MacroEnv' for this back end (see "Text.RE.TestBench")
preludeEnv :: MacroEnv
preludeEnv :: MacroEnv
preludeEnv = RegexType -> MacroEnv
preludeMacroEnv RegexType
regexType

-- | the macros in the standard environment that are failing their tests
-- (checked by the test suite to be empty)
preludeTestsFailing :: [MacroID]
preludeTestsFailing :: [MacroID]
preludeTestsFailing = MacroEnv -> [MacroID]
badMacros (MacroEnv -> [MacroID]) -> MacroEnv -> [MacroID]
forall a b. (a -> b) -> a -> b
$ RegexType -> MacroEnv
preludeMacroEnv RegexType
regexType

-- | a table the standard macros in markdown format
preludeTable :: String
preludeTable :: String
preludeTable = RegexType -> String
preludeMacroTable RegexType
regexType

-- | a summary of the macros in the standard environment for this back
-- end in plain text
preludeSummary :: PreludeMacro -> String
preludeSummary :: PreludeMacro -> String
preludeSummary = RegexType -> PreludeMacro -> String
preludeMacroSummary RegexType
regexType

-- | a listing of the RE text for each macro in the standard environment
-- with all macros expanded to normal form
preludeSources :: String
preludeSources :: String
preludeSources = RegexType -> String
preludeMacroSources RegexType
regexType

-- | the prolude source of a given macro in the standard environment
preludeSource :: PreludeMacro -> String
preludeSource :: PreludeMacro -> String
preludeSource = RegexType -> PreludeMacro -> String
preludeMacroSource RegexType
regexType


------------------------------------------------------------------------
-- Quasi Quoters
------------------------------------------------------------------------

-- | @[re| ... |]@, is equivalent to @[reMultilineSensitive| ... |]@,
-- compiling a case-sensitive, multi-line RE
re                      :: QuasiQuoter
re :: QuasiQuoter
re                       = Maybe SimpleREOptions -> QuasiQuoter
re' (Maybe SimpleREOptions -> QuasiQuoter)
-> Maybe SimpleREOptions -> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ SimpleREOptions -> Maybe SimpleREOptions
forall a. a -> Maybe a
Just SimpleREOptions
forall a. Bounded a => a
minBound

-- | @[reMultilineSensitive| ... |]@, compiles a case-sensitive, multi-line RE
reMultilineSensitive    :: QuasiQuoter
reMultilineSensitive :: QuasiQuoter
reMultilineSensitive     = Maybe SimpleREOptions -> QuasiQuoter
re' (Maybe SimpleREOptions -> QuasiQuoter)
-> Maybe SimpleREOptions -> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ SimpleREOptions -> Maybe SimpleREOptions
forall a. a -> Maybe a
Just  SimpleREOptions
MultilineSensitive

-- | @[reMultilineInsensitive| ... |]@, compiles a case-insensitive, multi-line RE
reMultilineInsensitive  :: QuasiQuoter
reMultilineInsensitive :: QuasiQuoter
reMultilineInsensitive   = Maybe SimpleREOptions -> QuasiQuoter
re' (Maybe SimpleREOptions -> QuasiQuoter)
-> Maybe SimpleREOptions -> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ SimpleREOptions -> Maybe SimpleREOptions
forall a. a -> Maybe a
Just  SimpleREOptions
MultilineInsensitive

-- | @[reMultilineInsensitive| ... |]@, compiles a case-sensitive, non-multi-line RE
reBlockSensitive        :: QuasiQuoter
reBlockSensitive :: QuasiQuoter
reBlockSensitive         = Maybe SimpleREOptions -> QuasiQuoter
re' (Maybe SimpleREOptions -> QuasiQuoter)
-> Maybe SimpleREOptions -> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ SimpleREOptions -> Maybe SimpleREOptions
forall a. a -> Maybe a
Just  SimpleREOptions
BlockSensitive

-- | @[reMultilineInsensitive| ... |]@, compiles a case-insensitive, non-multi-line RE
reBlockInsensitive      :: QuasiQuoter
reBlockInsensitive :: QuasiQuoter
reBlockInsensitive       = Maybe SimpleREOptions -> QuasiQuoter
re' (Maybe SimpleREOptions -> QuasiQuoter)
-> Maybe SimpleREOptions -> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ SimpleREOptions -> Maybe SimpleREOptions
forall a. a -> Maybe a
Just  SimpleREOptions
BlockInsensitive

-- | @[reMS| ... |]@ is a shorthand for @[reMultilineSensitive| ... |]@
reMS                     :: QuasiQuoter
reMS :: QuasiQuoter
reMS                     = QuasiQuoter
reMultilineSensitive

-- | @[reMI| ... |]@ is a shorthand for @[reMultilineInsensitive| ... |]@
reMI                    :: QuasiQuoter
reMI :: QuasiQuoter
reMI                     = QuasiQuoter
reMultilineInsensitive

-- | @[reBS| ... |]@ is a shorthand for @[reBlockSensitive| ... |]@
reBS                    :: QuasiQuoter
reBS :: QuasiQuoter
reBS                     = QuasiQuoter
reBlockSensitive

-- | @[reBI| ... |]@ is a shorthand for @[reBlockInsensitive| ... |]@
reBI                    :: QuasiQuoter
reBI :: QuasiQuoter
reBI                     = QuasiQuoter
reBlockInsensitive

-- | @[re_| ... |]@ compiles a RE to produce a function that takes
-- the RE options (e.g., a 'SimpleREOptions' value) and yields the
-- RE compiled with those options. For example,
--
--   @countMatches $ s *=~ [re_|[0-9a-f]+|] MultilineInsensitive@
--
-- counts the number of hexadecimal digit strings in 's', allowing
-- for upper- or lower-case hex didgits (which is entirely equivalent
-- in this example to just using @[reMultilineInsensitive|[0-9a-f]+|]@).
re_                     :: QuasiQuoter
re_ :: QuasiQuoter
re_                      = Maybe SimpleREOptions -> QuasiQuoter
re'   Maybe SimpleREOptions
forall a. Maybe a
Nothing


------------------------------------------------------------------------
-- re Helpers
------------------------------------------------------------------------

re' :: Maybe SimpleREOptions -> QuasiQuoter
re' :: Maybe SimpleREOptions -> QuasiQuoter
re' Maybe SimpleREOptions
mb = case Maybe SimpleREOptions
mb of
  Maybe SimpleREOptions
Nothing  ->
    (String -> QuasiQuoter
qq0 String
"re'")
      { quoteExp :: String -> Q Exp
quoteExp = SimpleREOptions -> (String -> Q Exp) -> String -> Q Exp
parse SimpleREOptions
forall a. Bounded a => a
minBound (\String
rs->[|flip unsafeCompileRegex rs|])
      }
  Just SimpleREOptions
sro ->
    (String -> QuasiQuoter
qq0 String
"re'")
      { quoteExp :: String -> Q Exp
quoteExp = SimpleREOptions -> (String -> Q Exp) -> String -> Q Exp
parse SimpleREOptions
sro (\String
rs->[|unsafeCompileRegexSimple sro rs|])
      }
  where
    parse :: SimpleREOptions -> (String->Q Exp) -> String -> Q Exp
    parse :: SimpleREOptions -> (String -> Q Exp) -> String -> Q Exp
parse SimpleREOptions
sro String -> Q Exp
mk String
rs = (String -> Q Exp) -> (RE -> Q Exp) -> Poss RE -> Q Exp
forall b a. (String -> b) -> (a -> b) -> Poss a -> b
poss String -> Q Exp
forall a. HasCallStack => String -> a
error (\RE
_->String -> Q Exp
mk String
rs) (Poss RE -> Q Exp) -> Poss RE -> Q Exp
forall a b. (a -> b) -> a -> b
$ RegexParseMode -> REOptions -> String -> Poss RE
forall (m :: * -> *).
(Functor m, MonadFail m, Monad m) =>
RegexParseMode -> REOptions -> String -> m RE
compileRegex_ RegexParseMode
RPM_qq REOptions
os String
rs
      where
        os :: REOptions
os = SimpleREOptions -> REOptions
unpackSimpleREOptions SimpleREOptions
sro

data RegexParseMode
  = RPM_qq
  | RPM_raw
  deriving (RegexParseMode -> RegexParseMode -> Bool
(RegexParseMode -> RegexParseMode -> Bool)
-> (RegexParseMode -> RegexParseMode -> Bool) -> Eq RegexParseMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RegexParseMode -> RegexParseMode -> Bool
$c/= :: RegexParseMode -> RegexParseMode -> Bool
== :: RegexParseMode -> RegexParseMode -> Bool
$c== :: RegexParseMode -> RegexParseMode -> Bool
Eq,Int -> RegexParseMode -> String -> String
[RegexParseMode] -> String -> String
RegexParseMode -> String
(Int -> RegexParseMode -> String -> String)
-> (RegexParseMode -> String)
-> ([RegexParseMode] -> String -> String)
-> Show RegexParseMode
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [RegexParseMode] -> String -> String
$cshowList :: [RegexParseMode] -> String -> String
show :: RegexParseMode -> String
$cshow :: RegexParseMode -> String
showsPrec :: Int -> RegexParseMode -> String -> String
$cshowsPrec :: Int -> RegexParseMode -> String -> String
Show)

unsafeCompileRegexSimple :: SimpleREOptions -> String -> RE
unsafeCompileRegexSimple :: SimpleREOptions -> String -> RE
unsafeCompileRegexSimple SimpleREOptions
sro String
re_s = RegexParseMode -> REOptions -> String -> RE
unsafeCompileRegex_ RegexParseMode
RPM_qq REOptions
os String
re_s
  where
    os :: REOptions
os = SimpleREOptions -> REOptions
unpackSimpleREOptions SimpleREOptions
sro

unsafeCompileRegex :: IsOption o
                   => o
                   -> String
                   -> RE
unsafeCompileRegex :: o -> String -> RE
unsafeCompileRegex = RegexParseMode -> REOptions -> String -> RE
unsafeCompileRegex_ RegexParseMode
RPM_qq (REOptions -> String -> RE)
-> (o -> REOptions) -> o -> String -> RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. o -> REOptions
forall o. IsOption o => o -> REOptions
makeREOptions

unsafeCompileRegex_ :: RegexParseMode -> REOptions -> String -> RE
unsafeCompileRegex_ :: RegexParseMode -> REOptions -> String -> RE
unsafeCompileRegex_ RegexParseMode
rpm REOptions
os = (String -> RE) -> (RE -> RE) -> Poss RE -> RE
forall b a. (String -> b) -> (a -> b) -> Poss a -> b
poss String -> RE
forall c. String -> c
oops RE -> RE
forall a. a -> a
id (Poss RE -> RE) -> (String -> Poss RE) -> String -> RE
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RegexParseMode -> REOptions -> String -> Poss RE
forall (m :: * -> *).
(Functor m, MonadFail m, Monad m) =>
RegexParseMode -> REOptions -> String -> m RE
compileRegex_ RegexParseMode
rpm REOptions
os
  where
    oops :: String -> c
oops = String -> c
forall a. HasCallStack => String -> a
error (String -> c) -> (String -> String) -> String -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"unsafeCompileRegex: " String -> String -> String
forall a. [a] -> [a] -> [a]
++)

compileRegex_ :: (Functor m,MonadFail m,Monad m)
              => RegexParseMode
              -> REOptions
              -> String
              -> m RE
compileRegex_ :: RegexParseMode -> REOptions -> String -> m RE
compileRegex_ RegexParseMode
rpm REOptions
os String
re_s = (CaptureNames -> Regex -> RE) -> (CaptureNames, Regex) -> RE
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry CaptureNames -> Regex -> RE
mk ((CaptureNames, Regex) -> RE) -> m (CaptureNames, Regex) -> m RE
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RegexParseMode -> REOptions -> String -> m (CaptureNames, Regex)
forall (m :: * -> *).
(Functor m, MonadFail m, Monad m) =>
RegexParseMode -> REOptions -> String -> m (CaptureNames, Regex)
compileRegex' RegexParseMode
rpm REOptions
os String
re_s
  where
    mk :: CaptureNames -> Regex -> RE
mk CaptureNames
cnms Regex
rx =
      RE :: REOptions -> String -> CaptureNames -> Regex -> RE
RE
        { _re_options :: REOptions
_re_options = REOptions
os
        , _re_source :: String
_re_source  = String
re_s
        , _re_cnames :: CaptureNames
_re_cnames  = CaptureNames
cnms
        , _re_regex :: Regex
_re_regex   = Regex
rx
        }

compileRegex' :: (Functor m,MonadFail m,Monad m)
              => RegexParseMode
              -> REOptions
              -> String
              -> m (CaptureNames,Regex)
compileRegex' :: RegexParseMode -> REOptions -> String -> m (CaptureNames, Regex)
compileRegex' RegexParseMode
rpm REOptions{CompOption
ExecOption
Macros RE
optionsExec :: ExecOption
optionsComp :: CompOption
optionsMacs :: Macros RE
optionsExec :: forall r c e. REOptions_ r c e -> e
optionsComp :: forall r c e. REOptions_ r c e -> c
optionsMacs :: forall r c e. REOptions_ r c e -> Macros r
..} String
s0 = do
    ((Int
_,CaptureNames
cnms),String
s2) <- (String -> m ((Int, CaptureNames), String))
-> (((Int, CaptureNames), String)
    -> m ((Int, CaptureNames), String))
-> Either String ((Int, CaptureNames), String)
-> m ((Int, CaptureNames), String)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> m ((Int, CaptureNames), String)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail ((Int, CaptureNames), String) -> m ((Int, CaptureNames), String)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ((Int, CaptureNames), String)
 -> m ((Int, CaptureNames), String))
-> Either String ((Int, CaptureNames), String)
-> m ((Int, CaptureNames), String)
forall a b. (a -> b) -> a -> b
$ String -> Either String ((Int, CaptureNames), String)
extractNamedCaptures String
s1
    (,) CaptureNames
cnms (Regex -> (CaptureNames, Regex))
-> m Regex -> m (CaptureNames, Regex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CompOption -> ExecOption -> String -> m Regex
forall regex compOpt execOpt source (m :: * -> *).
(RegexMaker regex compOpt execOpt source, MonadFail m) =>
compOpt -> execOpt -> source -> m regex
makeRegexOptsM CompOption
optionsComp ExecOption
optionsExec String
s2
  where
    s1 :: String
s1 = (RE -> String) -> Macros RE -> String -> String
forall r. (r -> String) -> Macros r -> String -> String
expandMacros RE -> String
reSource Macros RE
optionsMacs (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
pp String
s0

    pp :: String -> String
pp = case RegexParseMode
rpm of
      RegexParseMode
RPM_qq  -> String -> String
qq_prep
      RegexParseMode
RPM_raw -> String -> String
forall a. a -> a
id


------------------------------------------------------------------------
-- Preprocessing Literal REs
------------------------------------------------------------------------

qq_prep :: String -> String
qq_prep :: String -> String
qq_prep String
s0 = case String
s0 of
    String
""  -> String
""
    Char
c:String
s -> case Char
c of
      Char
'\\' -> String -> String
backslash String
s
      Char
_    -> Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
  where
    backslash :: String -> String
backslash String
s1 = case String
s1 of
      String
""  -> String
"\\"
      Char
c:String
s -> case Char
c of
        Char
'a'  -> Char
'\a'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
'b'  -> Char
'\b'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
'f'  -> Char
'\f'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
'n'  -> Char
'\n'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
'r'  -> Char
'\r'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
't'  -> Char
'\t'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
'v'  -> Char
'\v'    Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s
        Char
_    -> Char
'\\'Char -> String -> String
forall a. a -> [a] -> [a]
: Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
qq_prep String
s


------------------------------------------------------------------------
-- Options Helpers
------------------------------------------------------------------------

def_comp_option :: CompOption
def_comp_option :: CompOption
def_comp_option = REOptions -> CompOption
forall r c e. REOptions_ r c e -> c
optionsComp REOptions
defaultREOptions

def_exec_option :: ExecOption
def_exec_option :: ExecOption
def_exec_option = REOptions -> ExecOption
forall r c e. REOptions_ r c e -> e
optionsExec REOptions
defaultREOptions


------------------------------------------------------------------------
-- Haddock Sections
------------------------------------------------------------------------

-- $about
--
-- This module provides the regex PCRE back end. Most of the functions that
-- you will need for day to day use are provided by the primary API modules
-- (e.g., "Text.RE.TDFA.Text").