{-|
This modules provides 'RegexMaker' and 'RegexLike' instances for using
@ByteString@ with the DFA backend ("Text.Regex.Lib.WrapDFAEngine" and
"Text.Regex.Lazy.DFAEngineFPS").  This module is usually used via
import "Text.Regex.TDFA".

This exports instances of the high level API and the medium level
API of 'compile','execute', and 'regexec'.
-}
module Text.Regex.TDFA.Sequence(
  Regex
 ,CompOption
 ,ExecOption
 ,compile
 ,execute
 ,regexec
 ) where

import Data.Sequence(Seq)
import Data.Foldable as F(toList)

import Text.Regex.Base(MatchArray,RegexContext(..),RegexMaker(..),RegexLike(..),Extract(..))
import Text.Regex.Base.Impl(polymatch,polymatchM)
import Text.Regex.TDFA.Common(Regex(..),CompOption,ExecOption(captureGroups))
import Text.Regex.TDFA.String() -- piggyback on RegexMaker for String
import Text.Regex.TDFA.TDFA(patternToRegex)
import Text.Regex.TDFA.ReadRegex(parseRegex)

import Data.Array.IArray((!),elems)
import Data.Maybe(listToMaybe)
import Text.Regex.TDFA.NewDFA.Engine(execMatch)
import Text.Regex.TDFA.NewDFA.Tester as Tester(matchTest)

{- By Chris Kuklewicz, 2007. BSD License, see the LICENSE file. -}

instance RegexContext Regex (Seq Char) (Seq Char) where
  match :: Regex -> Seq Char -> Seq Char
match = Regex -> Seq Char -> Seq Char
forall a b. RegexLike a b => a -> b -> b
polymatch
  matchM :: Regex -> Seq Char -> m (Seq Char)
matchM = Regex -> Seq Char -> m (Seq Char)
forall a b (m :: * -> *).
(RegexLike a b, MonadFail m) =>
a -> b -> m b
polymatchM

instance RegexMaker Regex CompOption ExecOption (Seq Char) where
  makeRegexOptsM :: CompOption -> ExecOption -> Seq Char -> m Regex
makeRegexOptsM CompOption
c ExecOption
e Seq Char
source =
    case String -> Either ParseError (Pattern, (GroupIndex, DoPa))
parseRegex (Seq Char -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList Seq Char
source) of
      Left ParseError
err -> String -> m Regex
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m Regex) -> String -> m Regex
forall a b. (a -> b) -> a -> b
$ String
"parseRegex for Text.Regex.TDFA.Sequence failed:"String -> String -> String
forall a. [a] -> [a] -> [a]
++ParseError -> String
forall a. Show a => a -> String
show ParseError
err
      Right (Pattern, (GroupIndex, DoPa))
pattern -> Regex -> m Regex
forall (m :: * -> *) a. Monad m => a -> m a
return (Regex -> m Regex) -> Regex -> m Regex
forall a b. (a -> b) -> a -> b
$ (Pattern, (GroupIndex, DoPa)) -> CompOption -> ExecOption -> Regex
patternToRegex (Pattern, (GroupIndex, DoPa))
pattern CompOption
c ExecOption
e

instance RegexLike Regex (Seq Char) where
  matchOnce :: Regex -> Seq Char -> Maybe MatchArray
matchOnce Regex
r Seq Char
s = [MatchArray] -> Maybe MatchArray
forall a. [a] -> Maybe a
listToMaybe (Regex -> Seq Char -> [MatchArray]
forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r Seq Char
s)
  matchAll :: Regex -> Seq Char -> [MatchArray]
matchAll Regex
r Seq Char
s = Regex -> GroupIndex -> Char -> Seq Char -> [MatchArray]
forall text.
Uncons text =>
Regex -> GroupIndex -> Char -> text -> [MatchArray]
execMatch Regex
r GroupIndex
0 Char
'\n' Seq Char
s
  matchCount :: Regex -> Seq Char -> GroupIndex
matchCount Regex
r Seq Char
s = [MatchArray] -> GroupIndex
forall (t :: * -> *) a. Foldable t => t a -> GroupIndex
length (Regex -> Seq Char -> [MatchArray]
forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r' Seq Char
s)
    where r' :: Regex
r' = Regex
r { regex_execOptions :: ExecOption
regex_execOptions = (Regex -> ExecOption
regex_execOptions Regex
r) {captureGroups :: Bool
captureGroups = Bool
False} }
  matchTest :: Regex -> Seq Char -> Bool
matchTest = Regex -> Seq Char -> Bool
forall text. Uncons text => Regex -> text -> Bool
Tester.matchTest
  matchOnceText :: Regex
-> Seq Char -> Maybe (Seq Char, MatchText (Seq Char), Seq Char)
matchOnceText Regex
regex Seq Char
source =
    (MatchArray -> (Seq Char, MatchText (Seq Char), Seq Char))
-> Maybe MatchArray
-> Maybe (Seq Char, MatchText (Seq Char), Seq Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\MatchArray
ma -> let (GroupIndex
o,GroupIndex
l) = MatchArray
maMatchArray -> GroupIndex -> (GroupIndex, GroupIndex)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
!GroupIndex
0
                 in (GroupIndex -> Seq Char -> Seq Char
forall source. Extract source => GroupIndex -> source -> source
before GroupIndex
o Seq Char
source
                    ,((GroupIndex, GroupIndex) -> (Seq Char, (GroupIndex, GroupIndex)))
-> MatchArray -> MatchText (Seq Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(GroupIndex, GroupIndex)
ol -> ((GroupIndex, GroupIndex) -> Seq Char -> Seq Char
forall source.
Extract source =>
(GroupIndex, GroupIndex) -> source -> source
extract (GroupIndex, GroupIndex)
ol Seq Char
source,(GroupIndex, GroupIndex)
ol)) MatchArray
ma
                    ,GroupIndex -> Seq Char -> Seq Char
forall source. Extract source => GroupIndex -> source -> source
after (GroupIndex
oGroupIndex -> GroupIndex -> GroupIndex
forall a. Num a => a -> a -> a
+GroupIndex
l) Seq Char
source))
         (Regex -> Seq Char -> Maybe MatchArray
forall regex source.
RegexLike regex source =>
regex -> source -> Maybe MatchArray
matchOnce Regex
regex Seq Char
source)
  matchAllText :: Regex -> Seq Char -> [MatchText (Seq Char)]
matchAllText Regex
regex Seq Char
source =
    (MatchArray -> MatchText (Seq Char))
-> [MatchArray] -> [MatchText (Seq Char)]
forall a b. (a -> b) -> [a] -> [b]
map (((GroupIndex, GroupIndex) -> (Seq Char, (GroupIndex, GroupIndex)))
-> MatchArray -> MatchText (Seq Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(GroupIndex, GroupIndex)
ol -> ((GroupIndex, GroupIndex) -> Seq Char -> Seq Char
forall source.
Extract source =>
(GroupIndex, GroupIndex) -> source -> source
extract (GroupIndex, GroupIndex)
ol Seq Char
source,(GroupIndex, GroupIndex)
ol)))
        (Regex -> Seq Char -> [MatchArray]
forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
regex Seq Char
source)

compile :: CompOption -- ^ Flags (summed together)
        -> ExecOption -- ^ Flags (summed together)
        -> (Seq Char) -- ^ The regular expression to compile
        -> Either String Regex -- ^ Returns: the compiled regular expression
compile :: CompOption -> ExecOption -> Seq Char -> Either String Regex
compile CompOption
compOpt ExecOption
execOpt Seq Char
bs =
  case String -> Either ParseError (Pattern, (GroupIndex, DoPa))
parseRegex (Seq Char -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList Seq Char
bs) of
    Left ParseError
err -> String -> Either String Regex
forall a b. a -> Either a b
Left (String
"parseRegex for Text.Regex.TDFA.Sequence failed:"String -> String -> String
forall a. [a] -> [a] -> [a]
++ParseError -> String
forall a. Show a => a -> String
show ParseError
err)
    Right (Pattern, (GroupIndex, DoPa))
pattern -> Regex -> Either String Regex
forall a b. b -> Either a b
Right ((Pattern, (GroupIndex, DoPa)) -> CompOption -> ExecOption -> Regex
patternToRegex (Pattern, (GroupIndex, DoPa))
pattern CompOption
compOpt ExecOption
execOpt)

execute :: Regex      -- ^ Compiled regular expression
        -> (Seq Char) -- ^ ByteString to match against
        -> Either String (Maybe MatchArray)
execute :: Regex -> Seq Char -> Either String (Maybe MatchArray)
execute Regex
r Seq Char
bs = Maybe MatchArray -> Either String (Maybe MatchArray)
forall a b. b -> Either a b
Right (Regex -> Seq Char -> Maybe MatchArray
forall regex source.
RegexLike regex source =>
regex -> source -> Maybe MatchArray
matchOnce Regex
r Seq Char
bs)

regexec :: Regex      -- ^ Compiled regular expression
        -> (Seq Char) -- ^ ByteString to match against
        -> Either String (Maybe ((Seq Char), (Seq Char), (Seq Char), [(Seq Char)]))
regexec :: Regex
-> Seq Char
-> Either String (Maybe (Seq Char, Seq Char, Seq Char, [Seq Char]))
regexec Regex
r Seq Char
bs =
  case Regex
-> Seq Char -> Maybe (Seq Char, MatchText (Seq Char), Seq Char)
forall regex source.
RegexLike regex source =>
regex -> source -> Maybe (source, MatchText source, source)
matchOnceText Regex
r Seq Char
bs of
    Maybe (Seq Char, MatchText (Seq Char), Seq Char)
Nothing -> Maybe (Seq Char, Seq Char, Seq Char, [Seq Char])
-> Either String (Maybe (Seq Char, Seq Char, Seq Char, [Seq Char]))
forall a b. b -> Either a b
Right (Maybe (Seq Char, Seq Char, Seq Char, [Seq Char])
forall a. Maybe a
Nothing)
    Just (Seq Char
pre,MatchText (Seq Char)
mt,Seq Char
post) ->
      let main :: Seq Char
main = (Seq Char, (GroupIndex, GroupIndex)) -> Seq Char
forall a b. (a, b) -> a
fst (MatchText (Seq Char)
mtMatchText (Seq Char)
-> GroupIndex -> (Seq Char, (GroupIndex, GroupIndex))
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
!GroupIndex
0)
          rest :: [Seq Char]
rest = ((Seq Char, (GroupIndex, GroupIndex)) -> Seq Char)
-> [(Seq Char, (GroupIndex, GroupIndex))] -> [Seq Char]
forall a b. (a -> b) -> [a] -> [b]
map (Seq Char, (GroupIndex, GroupIndex)) -> Seq Char
forall a b. (a, b) -> a
fst ([(Seq Char, (GroupIndex, GroupIndex))]
-> [(Seq Char, (GroupIndex, GroupIndex))]
forall a. [a] -> [a]
tail (MatchText (Seq Char) -> [(Seq Char, (GroupIndex, GroupIndex))]
forall (a :: * -> * -> *) e i. (IArray a e, Ix i) => a i e -> [e]
elems MatchText (Seq Char)
mt)) -- will be []
      in Maybe (Seq Char, Seq Char, Seq Char, [Seq Char])
-> Either String (Maybe (Seq Char, Seq Char, Seq Char, [Seq Char]))
forall a b. b -> Either a b
Right ((Seq Char, Seq Char, Seq Char, [Seq Char])
-> Maybe (Seq Char, Seq Char, Seq Char, [Seq Char])
forall a. a -> Maybe a
Just (Seq Char
pre,Seq Char
main,Seq Char
post,[Seq Char]
rest))