    {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
    {-# LANGUAGE OverloadedStrings                  #-}
    {-# LANGUAGE CPP                                #-}

    module Text.RE.ZeInternals.TestBench.Parsers
      (
      -- * The Test Bench
        MacroEnv
      , MacroDescriptor(..)
      , RegexSource(..)
      , WithCaptures(..)
      , RegexType
      , isTDFA
      , isPCRE
      , presentRegexType
      -- ** Constructing a MacrosEnv
      , mkMacros
      -- ** Formatting Macros
      , formatMacroTable
      , formatMacroSummary
      , formatMacroSources
      , formatMacroSource
      -- ** Formatting Macros
      , testMacroEnv
      , runTests
      , runTests'
      -- * Parsing
      , parseInteger
      , parseHex
      , parseDouble
      , parseString
      , parseSimpleString
      , parseDate
      , parseSlashesDate
      , parseTimeOfDay
      , parseTimeZone
      , parseDateTime
      , parseDateTime8601
      , parseDateTimeCLF
      , parseShortMonth
      , shortMonthArray
      , IPV4Address
      , parseIPv4Address
      , Severity(..)
      , parseSeverity
      , severityKeywords
      ) where

    import           Data.Array
    import qualified Data.HashMap.Strict        as HM
    import           Data.Maybe
    import qualified Data.Text                  as T
    import           Data.Time
    import qualified Data.Time.Locale.Compat    as LC
    import           Data.Word
    import           Text.Printf
    import           Text.RE.Replace
    import           Text.RE.ZeInternals.TestBench
    import           Text.Read

    parseInteger :: Replace a => a -> Maybe Int
    parseInteger :: forall a. Replace a => a -> Maybe Int
    parseInteger = [Char] -> Maybe Int
    forall a. Read a => [Char] -> Maybe a
    readMaybe ([Char] -> Maybe Int) -> (a -> [Char]) -> a -> Maybe Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR

    parseHex :: Replace a => a -> Maybe Int
    parseHex :: forall a. Replace a => a -> Maybe Int
    parseHex = [Char] -> Maybe Int
    forall a. Read a => [Char] -> Maybe a
    readMaybe ([Char] -> Maybe Int) -> (a -> [Char]) -> a -> Maybe Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char]
    "0x"[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++) ([Char] -> [Char]) -> (a -> [Char]) -> a -> [Char]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR

    parseDouble :: Replace a => a -> Maybe Double
    parseDouble :: forall a. Replace a => a -> Maybe Double
    parseDouble = [Char] -> Maybe Double
    forall a. Read a => [Char] -> Maybe a
    readMaybe ([Char] -> Maybe Double) -> (a -> [Char]) -> a -> Maybe Double
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR

    parseString :: Replace a => a -> Maybe T.Text
    parseString :: forall a. Replace a => a -> Maybe Text
    parseString = [Char] -> Maybe Text
    forall a. Read a => [Char] -> Maybe a
    readMaybe ([Char] -> Maybe Text) -> (a -> [Char]) -> a -> Maybe Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR

    parseSimpleString :: Replace a => a -> Maybe T.Text
    parseSimpleString :: forall a. Replace a => a -> Maybe Text
    parseSimpleString = Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text) -> (a -> Text) -> a -> Maybe Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text -> Text
    T.dropEnd Int
    1 (Text -> Text) -> (a -> Text) -> a -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text -> Text
    T.drop Int
    1 (Text -> Text) -> (a -> Text) -> a -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Text
    forall a. Replace a => a -> Text
    textifyR

    date_templates, time_templates, timezone_templates,
      date_time_8601_templates, date_time_templates :: [String]
    date_templates :: [[Char]]
    date_templates            = [[Char]
    "%F"]
    time_templates :: [[Char]]
    time_templates            = [[Char]
    "%H:%M:%S",[Char]
    "%H:%M:%S%Q",[Char]
    "%H:%M"]
    timezone_templates :: [[Char]]
    timezone_templates        = [[Char]
    "Z",[Char]
    "%z"]
    date_time_8601_templates :: [[Char]]
    date_time_8601_templates  =
        [ [Char] -> [Char] -> [Char] -> [Char] -> [Char]
    forall r. PrintfType r => [Char] -> r
    printf [Char]
    "%sT%s%s" [Char]
    dt [Char]
    tm [Char]
    tz
            | [Char]
    dt <- [[Char]]
    date_templates
            , [Char]
    tm <- [[Char]]
    time_templates
            , [Char]
    tz <- [[Char]]
    timezone_templates
            ]
    date_time_templates :: [[Char]]
    date_time_templates       =
        [ [Char] -> [Char] -> Char -> [Char] -> [Char] -> [Char]
    forall r. PrintfType r => [Char] -> r
    printf [Char]
    "%s%c%s%s" [Char]
    dt Char
    sc [Char]
    tm [Char]
    tz
            | [Char]
    dt <- [[Char]]
    date_templates
            , Char
    sc <- [Char
    'T',Char
    ' ']
            , [Char]
    tm <- [[Char]]
    time_templates
            , [Char]
    tz <- [[Char]]
    timezone_templates [[Char]] -> [[Char]] -> [[Char]]
    forall a. [a] -> [a] -> [a]
    ++ [[Char]
    " UTC",[Char]
    ""]
            ]

    parseDate :: Replace a => a -> Maybe Day
    parseDate :: forall a. Replace a => a -> Maybe Day
    parseDate = [[Char]] -> a -> Maybe Day
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    date_templates

    parseSlashesDate :: Replace a => a -> Maybe Day
    parseSlashesDate :: forall a. Replace a => a -> Maybe Day
    parseSlashesDate = [[Char]] -> a -> Maybe Day
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]
    "%Y/%m/%d"]

    parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay
    parseTimeOfDay :: forall a. Replace a => a -> Maybe TimeOfDay
    parseTimeOfDay = [[Char]] -> a -> Maybe TimeOfDay
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    time_templates

    parseTimeZone :: Replace a => a -> Maybe TimeZone
    parseTimeZone :: forall a. Replace a => a -> Maybe TimeZone
    parseTimeZone = [[Char]] -> a -> Maybe TimeZone
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    timezone_templates

    parseDateTime :: Replace a => a -> Maybe UTCTime
    parseDateTime :: forall a. Replace a => a -> Maybe UTCTime
    parseDateTime = [[Char]] -> a -> Maybe UTCTime
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    date_time_templates

    parseDateTime8601 :: Replace a => a -> Maybe UTCTime
    parseDateTime8601 :: forall a. Replace a => a -> Maybe UTCTime
    parseDateTime8601 = [[Char]] -> a -> Maybe UTCTime
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    date_time_8601_templates

    parseDateTimeCLF :: Replace a => a -> Maybe UTCTime
    parseDateTimeCLF :: forall a. Replace a => a -> Maybe UTCTime
    parseDateTimeCLF = [[Char]] -> a -> Maybe UTCTime
    forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]
    "%d/%b/%Y:%H:%M:%S %z"]

    parseShortMonth :: Replace a => a -> Maybe Int
    parseShortMonth :: forall a. Replace a => a -> Maybe Int
    parseShortMonth = ([Char] -> HashMap [Char] Int -> Maybe Int)
    -> HashMap [Char] Int -> [Char] -> Maybe Int
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [Char] -> HashMap [Char] Int -> Maybe Int
    forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
    HM.lookup HashMap [Char] Int
    short_month_hm ([Char] -> Maybe Int) -> (a -> [Char]) -> a -> Maybe Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR

    parse_time :: (ParseTime t,Replace s) => [String] -> s -> Maybe t
    parse_time :: forall t s. (ParseTime t, Replace s) => [[Char]] -> s -> Maybe t
    parse_time [[Char]]
    tpls = [Char] -> Maybe t
    forall {a}. ParseTime a => [Char] -> Maybe a
    prs ([Char] -> Maybe t) -> (s -> [Char]) -> s -> Maybe t
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . s -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR
      where
        prs :: [Char] -> Maybe a
    prs [Char]
    s = [a] -> Maybe a
    forall a. [a] -> Maybe a
    listToMaybe ([a] -> Maybe a) -> [a] -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ [Maybe a] -> [a]
    forall a. [Maybe a] -> [a]
    catMaybes
          [ Bool -> TimeLocale -> [Char] -> [Char] -> Maybe a
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> [Char] -> [Char] -> m t
    parseTimeM Bool
    True  TimeLocale
    LC.defaultTimeLocale [Char]
    fmt [Char]
    s
              | [Char]
    fmt<-[[Char]]
    tpls
              ]
    #if !MIN_VERSION_time(1,5,0)
        parseTimeM _ = parseTime
    #endif

    short_month_hm :: HM.HashMap String Int
    short_month_hm :: HashMap [Char] Int
    short_month_hm = [([Char], Int)] -> HashMap [Char] Int
    forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
    HM.fromList [ (Text -> [Char]
    T.unpack (Text -> [Char]) -> Text -> [Char]
    forall a b. (a -> b) -> a -> b
    $ Array Int Text
    shortMonthArrayArray Int Text -> Int -> Text
    forall i e. Ix i => Array i e -> i -> e
    !Int
    i,Int
    i) | Int
    i<-[Int
    1..Int
    12] ]

    shortMonthArray :: Array Int T.Text
    shortMonthArray :: Array Int Text
    shortMonthArray = (Int, Int) -> [Text] -> Array Int Text
    forall i e. Ix i => (i, i) -> [e] -> Array i e
    listArray (Int
    1,Int
    12) ([Text] -> Array Int Text) -> [Text] -> Array Int Text
    forall a b. (a -> b) -> a -> b
    $
      Text -> [Text]
    T.words Text
    "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"

    type IPV4Address = (Word8,Word8,Word8,Word8)

    parseIPv4Address :: Replace a => a -> Maybe IPV4Address
    parseIPv4Address :: forall a. Replace a => a -> Maybe IPV4Address
    parseIPv4Address = [[Char]] -> Maybe IPV4Address
    forall {a} {b} {c} {d}.
    (Enum a, Enum b, Enum c, Enum d) =>
    [[Char]] -> Maybe (a, b, c, d)
    prs ([[Char]] -> Maybe IPV4Address)
    -> (a -> [[Char]]) -> a -> Maybe IPV4Address
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> [Char] -> [[Char]]
    words_by (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Char
    '.') ([Char] -> [[Char]]) -> (a -> [Char]) -> a -> [[Char]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> [Char]
    forall a. Replace a => a -> [Char]
    unpackR
      where
        prs :: [[Char]] -> Maybe (a, b, c, d)
    prs [[Char]
    a_s,[Char]
    b_s,[Char]
    c_s,[Char]
    d_s] = do
          a <- [Char] -> Maybe Int
    forall a. Read a => [Char] -> Maybe a
    readMaybe [Char]
    a_s
          b <- readMaybe b_s
          c <- readMaybe c_s
          d <- readMaybe d_s
          case all is_o [a,b,c,d] of
            Bool
    True  -> (a, b, c, d) -> Maybe (a, b, c, d)
    forall a. a -> Maybe a
    Just (Int -> a
    forall a. Enum a => Int -> a
    toEnum Int
    a,Int -> b
    forall a. Enum a => Int -> a
    toEnum Int
    b,Int -> c
    forall a. Enum a => Int -> a
    toEnum Int
    c,Int -> d
    forall a. Enum a => Int -> a
    toEnum Int
    d)
            Bool
    False -> Maybe (a, b, c, d)
    forall a. Maybe a
    Nothing
        prs [[Char]]
    _ = Maybe (a, b, c, d)
    forall a. Maybe a
    Nothing

        is_o :: a -> Bool
    is_o a
    x = a
    0 a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    x Bool -> Bool -> Bool
    && a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    255

    data Severity
      = Emerg
      | Alert
      | Crit
      | Err
      | Warning
      | Notice
      | Info
      | Debug
      deriving (Severity
    Severity -> Severity -> Bounded Severity
    forall a. a -> a -> Bounded a
    $cminBound :: Severity
    minBound :: Severity
    $cmaxBound :: Severity
    maxBound :: Severity
    Bounded,Int -> Severity
    Severity -> Int
    Severity -> [Severity]
    Severity -> Severity
    Severity -> Severity -> [Severity]
    Severity -> Severity -> Severity -> [Severity]
    (Severity -> Severity)
    -> (Severity -> Severity)
    -> (Int -> Severity)
    -> (Severity -> Int)
    -> (Severity -> [Severity])
    -> (Severity -> Severity -> [Severity])
    -> (Severity -> Severity -> [Severity])
    -> (Severity -> Severity -> Severity -> [Severity])
    -> Enum Severity
    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 :: Severity -> Severity
    succ :: Severity -> Severity
    $cpred :: Severity -> Severity
    pred :: Severity -> Severity
    $ctoEnum :: Int -> Severity
    toEnum :: Int -> Severity
    $cfromEnum :: Severity -> Int
    fromEnum :: Severity -> Int
    $cenumFrom :: Severity -> [Severity]
    enumFrom :: Severity -> [Severity]
    $cenumFromThen :: Severity -> Severity -> [Severity]
    enumFromThen :: Severity -> Severity -> [Severity]
    $cenumFromTo :: Severity -> Severity -> [Severity]
    enumFromTo :: Severity -> Severity -> [Severity]
    $cenumFromThenTo :: Severity -> Severity -> Severity -> [Severity]
    enumFromThenTo :: Severity -> Severity -> Severity -> [Severity]
    Enum,Eq Severity
    Eq Severity =>
    (Severity -> Severity -> Ordering)
    -> (Severity -> Severity -> Bool)
    -> (Severity -> Severity -> Bool)
    -> (Severity -> Severity -> Bool)
    -> (Severity -> Severity -> Bool)
    -> (Severity -> Severity -> Severity)
    -> (Severity -> Severity -> Severity)
    -> Ord Severity
    Severity -> Severity -> Bool
    Severity -> Severity -> Ordering
    Severity -> Severity -> Severity
    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 :: Severity -> Severity -> Ordering
    compare :: Severity -> Severity -> Ordering
    $c< :: Severity -> Severity -> Bool
    < :: Severity -> Severity -> Bool
    $c<= :: Severity -> Severity -> Bool
    <= :: Severity -> Severity -> Bool
    $c> :: Severity -> Severity -> Bool
    > :: Severity -> Severity -> Bool
    $c>= :: Severity -> Severity -> Bool
    >= :: Severity -> Severity -> Bool
    $cmax :: Severity -> Severity -> Severity
    max :: Severity -> Severity -> Severity
    $cmin :: Severity -> Severity -> Severity
    min :: Severity -> Severity -> Severity
    Ord,Severity -> Severity -> Bool
    (Severity -> Severity -> Bool)
    -> (Severity -> Severity -> Bool) -> Eq Severity
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Severity -> Severity -> Bool
    == :: Severity -> Severity -> Bool
    $c/= :: Severity -> Severity -> Bool
    /= :: Severity -> Severity -> Bool
    Eq,Int -> Severity -> [Char] -> [Char]
    [Severity] -> [Char] -> [Char]
    Severity -> [Char]
    (Int -> Severity -> [Char] -> [Char])
    -> (Severity -> [Char])
    -> ([Severity] -> [Char] -> [Char])
    -> Show Severity
    forall a.
    (Int -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: Int -> Severity -> [Char] -> [Char]
    showsPrec :: Int -> Severity -> [Char] -> [Char]
    $cshow :: Severity -> [Char]
    show :: Severity -> [Char]
    $cshowList :: [Severity] -> [Char] -> [Char]
    showList :: [Severity] -> [Char] -> [Char]
    Show)

    parseSeverity :: Replace a => a -> Maybe Severity
    parseSeverity :: forall a. Replace a => a -> Maybe Severity
    parseSeverity = (Text -> HashMap Text Severity -> Maybe Severity)
    -> HashMap Text Severity -> Text -> Maybe Severity
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Text -> HashMap Text Severity -> Maybe Severity
    forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
    HM.lookup HashMap Text Severity
    severity_hm (Text -> Maybe Severity) -> (a -> Text) -> a -> Maybe Severity
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Text
    forall a. Replace a => a -> Text
    textifyR

    severity_hm :: HM.HashMap T.Text Severity
    severity_hm :: HashMap Text Severity
    severity_hm = [(Text, Severity)] -> HashMap Text Severity
    forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
    HM.fromList
      [ (Text
    kw,Severity
    pri)
          | Severity
    pri<-[Severity
    forall a. Bounded a => a
    minBound..Severity
    forall a. Bounded a => a
    maxBound]
          , let (Text
    kw0,[Text]
    kws) = Severity -> (Text, [Text])
    severityKeywords Severity
    pri
          , Text
    kw <- Text
    kw0Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    kws
          ]

    severityKeywords :: Severity -> (T.Text,[T.Text])
    severityKeywords :: Severity -> (Text, [Text])
    severityKeywords Severity
    pri = case Severity
    pri of
      Severity
    Emerg     -> (,) Text
    "emerg"    [Text
    "panic"]
      Severity
    Alert     -> (,) Text
    "alert"    []
      Severity
    Crit      -> (,) Text
    "crit"     []
      Severity
    Err       -> (,) Text
    "err"      [Text
    "error"]
      Severity
    Warning   -> (,) Text
    "warning"  [Text
    "warn"]
      Severity
    Notice    -> (,) Text
    "notice"   []
      Severity
    Info      -> (,) Text
    "info"     []
      Severity
    Debug     -> (,) Text
    "debug"    []

    words_by :: (Char->Bool) -> String -> [String]
    words_by :: (Char -> Bool) -> [Char] -> [[Char]]
    words_by Char -> Bool
    f [Char]
    s = case (Char -> Bool) -> [Char] -> [Char]
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile Char -> Bool
    f [Char]
    s of
      [Char]
    "" -> []
      [Char]
    s' -> [Char]
    w [Char] -> [[Char]] -> [[Char]]
    forall a. a -> [a] -> [a]
    : (Char -> Bool) -> [Char] -> [[Char]]
    words_by Char -> Bool
    f [Char]
    s''
            where
              ([Char]
    w, [Char]
    s'') = (Char -> Bool) -> [Char] -> ([Char], [Char])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break Char -> Bool
    f [Char]
    s'