{-# 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
showList :: [CaptureID] -> ShowS
$cshowList :: [CaptureID] -> ShowS
show :: CaptureID -> String
$cshow :: CaptureID -> String
showsPrec :: Int -> CaptureID -> ShowS
$cshowsPrec :: Int -> 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
min :: CaptureID -> CaptureID -> CaptureID
$cmin :: CaptureID -> CaptureID -> CaptureID
max :: CaptureID -> CaptureID -> CaptureID
$cmax :: CaptureID -> CaptureID -> CaptureID
>= :: CaptureID -> CaptureID -> Bool
$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
compare :: CaptureID -> CaptureID -> Ordering
$ccompare :: CaptureID -> CaptureID -> Ordering
$cp1Ord :: Eq CaptureID
Ord,CaptureID -> CaptureID -> Bool
(CaptureID -> CaptureID -> Bool)
-> (CaptureID -> CaptureID -> Bool) -> Eq CaptureID
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CaptureID -> CaptureID -> Bool
$c/= :: CaptureID -> CaptureID -> Bool
== :: CaptureID -> CaptureID -> Bool
$c== :: 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
showList :: [CaptureName] -> ShowS
$cshowList :: [CaptureName] -> ShowS
show :: CaptureName -> String
$cshow :: CaptureName -> String
showsPrec :: Int -> CaptureName -> ShowS
$cshowsPrec :: Int -> 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
min :: CaptureName -> CaptureName -> CaptureName
$cmin :: CaptureName -> CaptureName -> CaptureName
max :: CaptureName -> CaptureName -> CaptureName
$cmax :: CaptureName -> CaptureName -> CaptureName
>= :: CaptureName -> CaptureName -> Bool
$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
compare :: CaptureName -> CaptureName -> Ordering
$ccompare :: CaptureName -> CaptureName -> Ordering
$cp1Ord :: Eq CaptureName
Ord,CaptureName -> CaptureName -> Bool
(CaptureName -> CaptureName -> Bool)
-> (CaptureName -> CaptureName -> Bool) -> Eq CaptureName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CaptureName -> CaptureName -> Bool
$c/= :: CaptureName -> CaptureName -> Bool
== :: CaptureName -> CaptureName -> Bool
$c== :: 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
showList :: [CaptureOrdinal] -> ShowS
$cshowList :: [CaptureOrdinal] -> ShowS
show :: CaptureOrdinal -> String
$cshow :: CaptureOrdinal -> String
showsPrec :: Int -> CaptureOrdinal -> ShowS
$cshowsPrec :: Int -> 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
min :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
$cmin :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
max :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
$cmax :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
>= :: CaptureOrdinal -> CaptureOrdinal -> Bool
$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
compare :: CaptureOrdinal -> CaptureOrdinal -> Ordering
$ccompare :: CaptureOrdinal -> CaptureOrdinal -> Ordering
$cp1Ord :: Eq CaptureOrdinal
Ord,CaptureOrdinal -> CaptureOrdinal -> Bool
(CaptureOrdinal -> CaptureOrdinal -> Bool)
-> (CaptureOrdinal -> CaptureOrdinal -> Bool) -> Eq CaptureOrdinal
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CaptureOrdinal -> CaptureOrdinal -> Bool
$c/= :: CaptureOrdinal -> CaptureOrdinal -> Bool
== :: CaptureOrdinal -> CaptureOrdinal -> Bool
$c== :: 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
enumFromThenTo :: CaptureOrdinal
-> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
$cenumFromThenTo :: CaptureOrdinal
-> CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
enumFromTo :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
$cenumFromTo :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
enumFromThen :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
$cenumFromThen :: CaptureOrdinal -> CaptureOrdinal -> [CaptureOrdinal]
enumFrom :: CaptureOrdinal -> [CaptureOrdinal]
$cenumFrom :: CaptureOrdinal -> [CaptureOrdinal]
fromEnum :: CaptureOrdinal -> Int
$cfromEnum :: CaptureOrdinal -> Int
toEnum :: Int -> CaptureOrdinal
$ctoEnum :: Int -> CaptureOrdinal
pred :: CaptureOrdinal -> CaptureOrdinal
$cpred :: CaptureOrdinal -> CaptureOrdinal
succ :: CaptureOrdinal -> CaptureOrdinal
$csucc :: 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
unsafeRangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
$cunsafeRangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
rangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
$crangeSize :: (CaptureOrdinal, CaptureOrdinal) -> Int
inRange :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool
$cinRange :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Bool
unsafeIndex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
$cunsafeIndex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
index :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
$cindex :: (CaptureOrdinal, CaptureOrdinal) -> CaptureOrdinal -> Int
range :: (CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal]
$crange :: (CaptureOrdinal, CaptureOrdinal) -> [CaptureOrdinal]
$cp1Ix :: Ord CaptureOrdinal
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
fromInteger :: Integer -> CaptureOrdinal
$cfromInteger :: Integer -> CaptureOrdinal
signum :: CaptureOrdinal -> CaptureOrdinal
$csignum :: CaptureOrdinal -> CaptureOrdinal
abs :: CaptureOrdinal -> CaptureOrdinal
$cabs :: CaptureOrdinal -> CaptureOrdinal
negate :: CaptureOrdinal -> CaptureOrdinal
$cnegate :: CaptureOrdinal -> CaptureOrdinal
* :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
$c* :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
- :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
$c- :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
+ :: CaptureOrdinal -> CaptureOrdinal -> CaptureOrdinal
$c+ :: CaptureOrdinal -> CaptureOrdinal -> 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