    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    module Text.RE.ZeInternals.Types.CaptureID where

    import qualified Data.HashMap.Strict            as HMS
    import           Data.Hashable
    import           Data.Ix
    import qualified Data.Text                      as T

    -- | CaptureID identifies captures, either by number
    -- (e.g., [cp|1|]) or name (e.g., [cp|foo|]).
    data CaptureID
      = IsCaptureOrdinal CaptureOrdinal   -- [cp|3|]
      | IsCaptureName    CaptureName      -- [cp|y|]
      deriving (Int -> CaptureID -> ShowS
    [CaptureID] -> ShowS
    CaptureID -> String
    (Int -> CaptureID -> ShowS)
    -> (CaptureID -> String)
    -> ([CaptureID] -> ShowS)
    -> Show CaptureID
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CaptureID -> ShowS
    showsPrec :: Int -> CaptureID -> ShowS
    $cshow :: CaptureID -> String
    show :: CaptureID -> String
    $cshowList :: [CaptureID] -> ShowS
    showList :: [CaptureID] -> ShowS
    Show,Eq CaptureID
    Eq CaptureID =>
    (CaptureID -> CaptureID -> Ordering)
    -> (CaptureID -> CaptureID -> Bool)
    -> (CaptureID -> CaptureID -> Bool)
    -> (CaptureID -> CaptureID -> Bool)
    -> (CaptureID -> CaptureID -> Bool)
    -> (CaptureID -> CaptureID -> CaptureID)
    -> (CaptureID -> CaptureID -> CaptureID)
    -> Ord CaptureID
    CaptureID -> CaptureID -> Bool
    CaptureID -> CaptureID -> Ordering
    CaptureID -> CaptureID -> CaptureID
    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 :: CaptureID -> CaptureID -> Ordering
    compare :: CaptureID -> CaptureID -> Ordering
    $c< :: CaptureID -> CaptureID -> Bool
    < :: CaptureID -> CaptureID -> Bool
    $c<= :: CaptureID -> CaptureID -> Bool
    <= :: CaptureID -> CaptureID -> Bool
    $c> :: CaptureID -> CaptureID -> Bool
    > :: CaptureID -> CaptureID -> Bool
    $c>= :: CaptureID -> CaptureID -> Bool
    >= :: CaptureID -> CaptureID -> Bool
    $cmax :: CaptureID -> CaptureID -> CaptureID
    max :: CaptureID -> CaptureID -> CaptureID
    $cmin :: CaptureID -> CaptureID -> CaptureID
    min :: CaptureID -> CaptureID -> CaptureID
    Ord,CaptureID -> CaptureID -> Bool
    (CaptureID -> CaptureID -> Bool)
    -> (CaptureID -> CaptureID -> Bool) -> Eq CaptureID
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CaptureID -> CaptureID -> Bool
    == :: CaptureID -> CaptureID -> Bool
    $c/= :: CaptureID -> CaptureID -> Bool
    /= :: CaptureID -> CaptureID -> Bool
    Eq)

    -- | the dictionary for named captures stored in compiled regular
    -- expressions associates
    type CaptureNames = HMS.HashMap CaptureName CaptureOrdinal

    -- | an empty 'CaptureNames' dictionary
    noCaptureNames :: CaptureNames
    noCaptureNames :: CaptureNames
    noCaptureNames = CaptureNames
    forall k v. HashMap k v
    HMS.empty

    -- | a 'CaptureName' is just the text of the name
    newtype CaptureName = CaptureName { CaptureName -> Text
    getCaptureName :: T.Text }
      deriving (Int -> CaptureName -> ShowS
    [CaptureName] -> ShowS
    CaptureName -> String
    (Int -> CaptureName -> ShowS)
    -> (CaptureName -> String)
    -> ([CaptureName] -> ShowS)
    -> Show CaptureName
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CaptureName -> ShowS
    showsPrec :: Int -> CaptureName -> ShowS
    $cshow :: CaptureName -> String
    show :: CaptureName -> String
    $cshowList :: [CaptureName] -> ShowS
    showList :: [CaptureName] -> ShowS
    Show,Eq CaptureName
    Eq CaptureName =>
    (CaptureName -> CaptureName -> Ordering)
    -> (CaptureName -> CaptureName -> Bool)
    -> (CaptureName -> CaptureName -> Bool)
    -> (CaptureName -> CaptureName -> Bool)
    -> (CaptureName -> CaptureName -> Bool)
    -> (CaptureName -> CaptureName -> CaptureName)
    -> (CaptureName -> CaptureName -> CaptureName)
    -> Ord CaptureName
    CaptureName -> CaptureName -> Bool
    CaptureName -> CaptureName -> Ordering
    CaptureName -> CaptureName -> CaptureName
    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 :: CaptureName -> CaptureName -> Ordering
    compare :: CaptureName -> CaptureName -> Ordering
    $c< :: CaptureName -> CaptureName -> Bool
    < :: CaptureName -> CaptureName -> Bool
    $c<= :: CaptureName -> CaptureName -> Bool
    <= :: CaptureName -> CaptureName -> Bool
    $c> :: CaptureName -> CaptureName -> Bool
    > :: CaptureName -> CaptureName -> Bool
    $c>= :: CaptureName -> CaptureName -> Bool
    >= :: CaptureName -> CaptureName -> Bool
    $cmax :: CaptureName -> CaptureName -> CaptureName
    max :: CaptureName -> CaptureName -> CaptureName
    $cmin :: CaptureName -> CaptureName -> CaptureName
    min :: CaptureName -> CaptureName -> CaptureName
    Ord,CaptureName -> CaptureName -> Bool
    (CaptureName -> CaptureName -> Bool)
    -> (CaptureName -> CaptureName -> Bool) -> Eq CaptureName
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CaptureName -> CaptureName -> Bool
    == :: CaptureName -> CaptureName -> Bool
    $c/= :: CaptureName -> CaptureName -> Bool
    /= :: CaptureName -> CaptureName -> Bool
    Eq)

    instance Hashable CaptureName where
      hashWithSalt :: Int -> CaptureName -> Int
    hashWithSalt Int
    i = Int -> Text -> Int
    forall a. Hashable a => Int -> a -> Int
    hashWithSalt Int
    i (Text -> Int) -> (CaptureName -> Text) -> CaptureName -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CaptureName -> Text
    getCaptureName

    -- | a 'CaptureOrdinal' is just the number of the capture, starting
    -- with 0 for the whole of the text matched, then in leftmost,
    -- outermost
    newtype CaptureOrdinal = CaptureOrdinal { CaptureOrdinal -> Int
    getCaptureOrdinal :: Int }
      deriving (Int -> CaptureOrdinal -> ShowS
    [CaptureOrdinal] -> ShowS
    CaptureOrdinal -> String
    (Int -> CaptureOrdinal -> ShowS)
    -> (CaptureOrdinal -> String)
    -> ([CaptureOrdinal] -> ShowS)
    -> Show CaptureOrdinal
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CaptureOrdinal -> ShowS
    showsPrec :: Int -> CaptureOrdinal -> ShowS
    $cshow :: CaptureOrdinal -> String
    show :: CaptureOrdinal -> String
    $cshowList :: [CaptureOrdinal] -> ShowS
    showList :: [CaptureOrdinal] -> ShowS
    Show,Eq CaptureOrdinal
    Eq CaptureOrdinal =>
    (CaptureOrdinal -> CaptureOrdinal -> Ordering)
    -> (CaptureOrdinal -> CaptureOrdinal -> Bool)
    -> (CaptureOrdinal -> CaptureOrdinal -> Bool)
    -> (CaptureOrdinal -> CaptureOrdinal -> Bool)
    -> (CaptureOrdinal -> CaptureOrdinal -> Bool)
    -> (CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal)
    -> Ord CaptureOrdinal
    CaptureOrdinal -> CaptureOrdinal -> Bool
    CaptureOrdinal -> CaptureOrdinal -> Ordering
    CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    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 :: CaptureOrdinal -> CaptureOrdinal -> Ordering
    compare :: CaptureOrdinal -> CaptureOrdinal -> Ordering
    $c< :: CaptureOrdinal -> CaptureOrdinal -> Bool
    < :: CaptureOrdinal -> CaptureOrdinal -> Bool
    $c<= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    <= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    $c> :: CaptureOrdinal -> CaptureOrdinal -> Bool
    > :: CaptureOrdinal -> CaptureOrdinal -> Bool
    $c>= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    >= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    $cmax :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    max :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    $cmin :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    min :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    Ord,CaptureOrdinal -> CaptureOrdinal -> Bool
    (CaptureOrdinal -> CaptureOrdinal -> Bool)
    -> (CaptureOrdinal -> CaptureOrdinal -> Bool) -> Eq CaptureOrdinal
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CaptureOrdinal -> CaptureOrdinal -> Bool
    == :: CaptureOrdinal -> CaptureOrdinal -> Bool
    $c/= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    /= :: CaptureOrdinal -> CaptureOrdinal -> Bool
    Eq,Int -> CaptureOrdinal
    CaptureOrdinal -> Int
    CaptureOrdinal -> [CaptureOrdinal]
    CaptureOrdinal -> CaptureOrdinal
    CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    CaptureOrdinal
    -> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    (CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal)
    -> (Int -> CaptureOrdinal)
    -> (CaptureOrdinal -> Int)
    -> (CaptureOrdinal -> [CaptureOrdinal])
    -> (CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal])
    -> (CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal])
    -> (CaptureOrdinal
        -> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal])
    -> Enum CaptureOrdinal
    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 :: CaptureOrdinal -> CaptureOrdinal
    succ :: CaptureOrdinal -> CaptureOrdinal
    $cpred :: CaptureOrdinal -> CaptureOrdinal
    pred :: CaptureOrdinal -> CaptureOrdinal
    $ctoEnum :: Int -> CaptureOrdinal
    toEnum :: Int -> CaptureOrdinal
    $cfromEnum :: CaptureOrdinal -> Int
    fromEnum :: CaptureOrdinal -> Int
    $cenumFrom :: CaptureOrdinal -> [CaptureOrdinal]
    enumFrom :: CaptureOrdinal -> [CaptureOrdinal]
    $cenumFromThen :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    enumFromThen :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    $cenumFromTo :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    enumFromTo :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    $cenumFromThenTo :: CaptureOrdinal
    -> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    enumFromThenTo :: CaptureOrdinal
    -> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
    Enum,Ord CaptureOrdinal
    Ord CaptureOrdinal =>
    ((CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal])
    -> ((CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int)
    -> ((CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int)
    -> ((CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool)
    -> ((CaptureOrdinal, CaptureOrdinal) -> Int)
    -> ((CaptureOrdinal, CaptureOrdinal) -> Int)
    -> Ix CaptureOrdinal
    (CaptureOrdinal, CaptureOrdinal) -> Int
    (CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal]
    (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool
    (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
    forall a.
    Ord a =>
    ((a, a) -> [a])
    -> ((a, a) -> a -> Int)
    -> ((a, a) -> a -> Int)
    -> ((a, a) -> a -> Bool)
    -> ((a, a) -> Int)
    -> ((a, a) -> Int)
    -> Ix a
    $crange :: (CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal]
    range :: (CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal]
    $cindex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
    index :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
    $cunsafeIndex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
    unsafeIndex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
    $cinRange :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool
    inRange :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool
    $crangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
    rangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
    $cunsafeRangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
    unsafeRangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
    Ix,Integer -> CaptureOrdinal
    CaptureOrdinal -> CaptureOrdinal
    CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    (CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal)
    -> (CaptureOrdinal -> CaptureOrdinal)
    -> (Integer -> CaptureOrdinal)
    -> Num CaptureOrdinal
    forall a.
    (a -> a -> a)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> (a -> a)
    -> (a -> a)
    -> (a -> a)
    -> (Integer -> a)
    -> Num a
    $c+ :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    + :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    $c- :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    - :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    $c* :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    * :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
    $cnegate :: CaptureOrdinal -> CaptureOrdinal
    negate :: CaptureOrdinal -> CaptureOrdinal
    $cabs :: CaptureOrdinal -> CaptureOrdinal
    abs :: CaptureOrdinal -> CaptureOrdinal
    $csignum :: CaptureOrdinal -> CaptureOrdinal
    signum :: CaptureOrdinal -> CaptureOrdinal
    $cfromInteger :: Integer -> CaptureOrdinal
    fromInteger :: Integer -> CaptureOrdinal
    Num)

    -- | look up a 'CaptureID' in the 'CaptureNames' dictionary
    findCaptureID :: CaptureID -> CaptureNames -> Either String CaptureOrdinal
    findCaptureID :: CaptureID -> CaptureNames -> Either String CaptureOrdinal
    findCaptureID (IsCaptureOrdinal CaptureOrdinal
    o) CaptureNames
    _   = CaptureOrdinal -> Either String CaptureOrdinal
    forall a b. b -> Either a b
    Right CaptureOrdinal
    o
    findCaptureID (IsCaptureName    CaptureName
    n) CaptureNames
    hms =
        Either String CaptureOrdinal
    -> (CaptureOrdinal -> Either String CaptureOrdinal)
    -> Maybe CaptureOrdinal
    -> Either String CaptureOrdinal
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Either String CaptureOrdinal
    forall {b}. Either String b
    oops CaptureOrdinal -> Either String CaptureOrdinal
    forall a b. b -> Either a b
    Right (Maybe CaptureOrdinal -> Either String CaptureOrdinal)
    -> Maybe CaptureOrdinal -> Either String CaptureOrdinal
    forall a b. (a -> b) -> a -> b
    $ CaptureName -> CaptureNames -> Maybe CaptureOrdinal
    forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
    HMS.lookup CaptureName
    n CaptureNames
    hms
      where
        oops :: Either String b
    oops = String -> Either String b
    forall a b. a -> Either a b
    Left (String -> Either String b) -> String -> Either String b
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    unlines ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $
          (String
    "lookupCaptureID: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Text -> String
    T.unpack Text
    t String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " not found in:") String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    :
            [ String
    "  "String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++Text -> String
    T.unpack (CaptureName -> Text
    getCaptureName CaptureName
    nm) | CaptureName
    nm <- CaptureNames -> [CaptureName]
    forall k v. HashMap k v -> [k]
    HMS.keys CaptureNames
    hms ]
        t :: Text
    t = CaptureName -> Text
    getCaptureName CaptureName
    n