\begin{code}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE UndecidableInstances       #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE MonoLocalBinds             #-}
\end{code}

\begin{code}
module Text.RE.ZeInternals.Types.Matches
  ( Matches(..)
  , anyMatches
  , countMatches
  , matches
  , mainCaptures
  ) where
\end{code}

\begin{code}
import           Data.Typeable
import           Text.RE.ZeInternals.Types.Capture
import           Text.RE.ZeInternals.Types.CaptureID
import           Text.RE.ZeInternals.Types.Match
import           Text.Regex.Base
\end{code}


\begin{code}
-- | the result of matching a RE against a text (with @*=~@), retaining
-- the text that was matched against
data Matches a =
  Matches
    { Matches a -> a
matchesSource :: !a          -- ^ the source text being matched
    , Matches a -> [Match a]
allMatches    :: ![Match a]  -- ^ all 'Match' instances found, left to right
    }
  deriving (Int -> Matches a -> ShowS
[Matches a] -> ShowS
Matches a -> String
(Int -> Matches a -> ShowS)
-> (Matches a -> String)
-> ([Matches a] -> ShowS)
-> Show (Matches a)
forall a. Show a => Int -> Matches a -> ShowS
forall a. Show a => [Matches a] -> ShowS
forall a. Show a => Matches a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Matches a] -> ShowS
$cshowList :: forall a. Show a => [Matches a] -> ShowS
show :: Matches a -> String
$cshow :: forall a. Show a => Matches a -> String
showsPrec :: Int -> Matches a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Matches a -> ShowS
Show,Matches a -> Matches a -> Bool
(Matches a -> Matches a -> Bool)
-> (Matches a -> Matches a -> Bool) -> Eq (Matches a)
forall a. Eq a => Matches a -> Matches a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Matches a -> Matches a -> Bool
$c/= :: forall a. Eq a => Matches a -> Matches a -> Bool
== :: Matches a -> Matches a -> Bool
$c== :: forall a. Eq a => Matches a -> Matches a -> Bool
Eq,Typeable)
\end{code}

\begin{code}
instance Functor Matches where
  fmap :: (a -> b) -> Matches a -> Matches b
fmap a -> b
f Matches{a
[Match a]
allMatches :: [Match a]
matchesSource :: a
allMatches :: forall a. Matches a -> [Match a]
matchesSource :: forall a. Matches a -> a
..} =
    Matches :: forall a. a -> [Match a] -> Matches a
Matches
      { matchesSource :: b
matchesSource = a -> b
f a
matchesSource
      , allMatches :: [Match b]
allMatches    = (Match a -> Match b) -> [Match a] -> [Match b]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> Match a -> Match b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) [Match a]
allMatches
      }
\end{code}

\begin{code}
-- | tests whether the RE matched the source text at all
anyMatches :: Matches a -> Bool
anyMatches :: Matches a -> Bool
anyMatches = Bool -> Bool
not (Bool -> Bool) -> (Matches a -> Bool) -> Matches a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Match a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([Match a] -> Bool)
-> (Matches a -> [Match a]) -> Matches a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matches a -> [Match a]
forall a. Matches a -> [Match a]
allMatches

-- | count the matches
countMatches :: Matches a -> Int
countMatches :: Matches a -> Int
countMatches = [Match a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Match a] -> Int) -> (Matches a -> [Match a]) -> Matches a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matches a -> [Match a]
forall a. Matches a -> [Match a]
allMatches

-- | list the texts that Matched
matches :: Matches a -> [a]
matches :: Matches a -> [a]
matches = (Capture a -> a) -> [Capture a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Capture a -> a
forall a. Capture a -> a
capturedText ([Capture a] -> [a])
-> (Matches a -> [Capture a]) -> Matches a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matches a -> [Capture a]
forall a. Matches a -> [Capture a]
mainCaptures

-- | extract the main capture from each match
mainCaptures :: Matches a -> [Capture a]
mainCaptures :: Matches a -> [Capture a]
mainCaptures Matches a
ac = [ CaptureID -> Match a -> Capture a
forall a. CaptureID -> Match a -> Capture a
capture CaptureID
c0 Match a
cs | Match a
cs<-Matches a -> [Match a]
forall a. Matches a -> [Match a]
allMatches Matches a
ac ]
  where
    c0 :: CaptureID
c0 = CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal Int
0
\end{code}

\begin{code}
-- | this instance hooks 'Matches' into regex-base: regex consumers need
-- not worry about any of this
instance
    ( RegexContext regex source [MatchText source]
    , RegexLike    regex source
    , RegexFix     regex source
    ) =>
  RegexContext regex source (Matches source) where
    match :: regex -> source -> Matches source
match  regex
r source
s = source -> [Match source] -> Matches source
forall a. a -> [Match a] -> Matches a
Matches source
s ([Match source] -> Matches source)
-> [Match source] -> Matches source
forall a b. (a -> b) -> a -> b
$ (MatchText source -> Match source)
-> [MatchText source] -> [Match source]
forall a b. (a -> b) -> [a] -> [b]
map (regex -> source -> MatchText source -> Match source
forall regex source.
RegexFix regex source =>
regex -> source -> MatchText source -> Match source
convertMatchText regex
r source
s) ([MatchText source] -> [Match source])
-> [MatchText source] -> [Match source]
forall a b. (a -> b) -> a -> b
$ regex -> source -> [MatchText source]
forall regex source target.
RegexContext regex source target =>
regex -> source -> target
match regex
r source
s
    matchM :: regex -> source -> m (Matches source)
matchM regex
r source
s = do
      [MatchText source]
y <- regex -> source -> m [MatchText source]
forall regex source target (m :: * -> *).
(RegexContext regex source target, MonadFail m) =>
regex -> source -> m target
matchM regex
r source
s
      Matches source -> m (Matches source)
forall (m :: * -> *) a. Monad m => a -> m a
return (Matches source -> m (Matches source))
-> Matches source -> m (Matches source)
forall a b. (a -> b) -> a -> b
$ source -> [Match source] -> Matches source
forall a. a -> [Match a] -> Matches a
Matches source
s ([Match source] -> Matches source)
-> [Match source] -> Matches source
forall a b. (a -> b) -> a -> b
$ (MatchText source -> Match source)
-> [MatchText source] -> [Match source]
forall a b. (a -> b) -> [a] -> [b]
map (regex -> source -> MatchText source -> Match source
forall regex source.
RegexFix regex source =>
regex -> source -> MatchText source -> Match source
convertMatchText regex
r source
s) [MatchText source]
y
\end{code}