{- |
This modules provides 'RegexMaker' and 'RegexLike' instances for using
'String' with the TDFA backend.

This exports instances of the high level API and the medium level
API of 'compile','execute', and 'regexec'.
-}
{- By Chris Kuklewicz, 2009. BSD License, see the LICENSE file. -}
module Text.Regex.TDFA.String(
  -- ** Types
  Regex
 ,MatchOffset
 ,MatchLength
 ,CompOption
 ,ExecOption
  -- ** Medium level API functions
 ,compile
 ,execute
 ,regexec
 ) where

import Text.Regex.Base.Impl(polymatch,polymatchM)
import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchOffset,MatchLength,MatchArray)
import Text.Regex.TDFA.Common(common_error,Regex(..),CompOption,ExecOption(captureGroups))
import Text.Regex.TDFA.ReadRegex(parseRegex)
import Text.Regex.TDFA.TDFA(patternToRegex)

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

err :: String -> a
err :: forall a. String -> a
err = forall a. String -> String -> a
common_error String
"Text.Regex.TDFA.String"

unwrap :: Either String v -> v
unwrap :: forall v. Either String v -> v
unwrap Either String v
x = case Either String v
x of Left String
msg -> forall a. String -> a
err (String
"Text.Regex.TDFA.String died: "forall a. [a] -> [a] -> [a]
++String
msg)
                     Right v
v -> v
v

compile  :: CompOption -- ^ Flags (summed together)
         -> ExecOption -- ^ Flags (summed together)
         -> String     -- ^ The regular expression to compile (ASCII only, no null bytes)
         -> Either String Regex -- ^ Returns: the compiled regular expression
compile :: CompOption -> ExecOption -> String -> Either String Regex
compile CompOption
compOpt ExecOption
execOpt String
source =
  case String -> Either ParseError (Pattern, (MatchOffset, DoPa))
parseRegex String
source of
    Left ParseError
msg -> forall a b. a -> Either a b
Left (String
"parseRegex for Text.Regex.TDFA.String failed:"forall a. [a] -> [a] -> [a]
++forall a. Show a => a -> String
show ParseError
msg)
    Right (Pattern, (MatchOffset, DoPa))
pattern -> forall a b. b -> Either a b
Right ((Pattern, (MatchOffset, DoPa)) -> CompOption -> ExecOption -> Regex
patternToRegex (Pattern, (MatchOffset, DoPa))
pattern CompOption
compOpt ExecOption
execOpt)

instance RegexMaker Regex CompOption ExecOption String where
  makeRegexOpts :: CompOption -> ExecOption -> String -> Regex
makeRegexOpts CompOption
c ExecOption
e String
source = forall v. Either String v -> v
unwrap (CompOption -> ExecOption -> String -> Either String Regex
compile CompOption
c ExecOption
e String
source)
  makeRegexOptsM :: forall (m :: * -> *).
MonadFail m =>
CompOption -> ExecOption -> String -> m Regex
makeRegexOptsM CompOption
c ExecOption
e String
source = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ CompOption -> ExecOption -> String -> Either String Regex
compile CompOption
c ExecOption
e String
source

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

regexec :: Regex      -- ^ Compiled regular expression
        -> String     -- ^ String to match against
        -> Either String (Maybe (String, String, String, [String]))
regexec :: Regex
-> String
-> Either String (Maybe (String, String, String, [String]))
regexec Regex
r String
txt = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$
  case forall regex source.
RegexLike regex source =>
regex -> source -> Maybe (source, MatchText source, source)
matchOnceText Regex
r String
txt of
    Just (String
pre, MatchText String
mt, String
post) | String
main:[String]
rest <- forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (forall (a :: * -> * -> *) e i. (IArray a e, Ix i) => a i e -> [e]
elems MatchText String
mt)
      -> forall a. a -> Maybe a
Just (String
pre, String
main, String
post, [String]
rest)
    Maybe (String, MatchText String, String)
_ -> forall a. Maybe a
Nothing

-- Minimal definition for now
instance RegexLike Regex String where
  matchOnce :: Regex -> String -> Maybe MatchArray
matchOnce Regex
r String
s = forall a. [a] -> Maybe a
listToMaybe (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r String
s)
  matchAll :: Regex -> String -> [MatchArray]
matchAll Regex
r String
s = forall text.
Uncons text =>
Regex -> MatchOffset -> Char -> text -> [MatchArray]
execMatch Regex
r MatchOffset
0 Char
'\n' String
s
  matchCount :: Regex -> String -> MatchOffset
matchCount Regex
r String
s = forall (t :: * -> *) a. Foldable t => t a -> MatchOffset
length (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r' String
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 -> String -> Bool
matchTest = forall text. Uncons text => Regex -> text -> Bool
Tester.matchTest
  -- matchOnceText
  matchAllText :: Regex -> String -> [MatchText String]
matchAllText Regex
r String
s =
    let go :: MatchOffset
-> [a]
-> [a i (MatchOffset, MatchOffset)]
-> [a i ([a], (MatchOffset, MatchOffset))]
go MatchOffset
i [a]
_ [a i (MatchOffset, MatchOffset)]
_ | MatchOffset
i seq :: forall a b. a -> b -> b
`seq` Bool
False = forall a. HasCallStack => a
undefined
        go MatchOffset
_i [a]
_t [] = []
        go MatchOffset
i [a]
t (a i (MatchOffset, MatchOffset)
x:[a i (MatchOffset, MatchOffset)]
xs) = let (MatchOffset
off0,MatchOffset
len0) = a i (MatchOffset, MatchOffset)
xforall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
!i
0
                            trans :: (MatchOffset, MatchOffset) -> ([a], (MatchOffset, MatchOffset))
trans pair :: (MatchOffset, MatchOffset)
pair@(MatchOffset
off,MatchOffset
len) = (forall a. MatchOffset -> [a] -> [a]
take MatchOffset
len (forall a. MatchOffset -> [a] -> [a]
drop (MatchOffset
offforall a. Num a => a -> a -> a
-MatchOffset
i) [a]
t),(MatchOffset, MatchOffset)
pair)
                            t' :: [a]
t' = forall a. MatchOffset -> [a] -> [a]
drop (MatchOffset
off0forall a. Num a => a -> a -> a
+MatchOffset
len0forall a. Num a => a -> a -> a
-MatchOffset
i) [a]
t
                        in forall (a :: * -> * -> *) e' e i.
(IArray a e', IArray a e, Ix i) =>
(e' -> e) -> a i e' -> a i e
amap (MatchOffset, MatchOffset) -> ([a], (MatchOffset, MatchOffset))
trans a i (MatchOffset, MatchOffset)
x forall a. a -> [a] -> [a]
: seq :: forall a b. a -> b -> b
seq [a]
t' (MatchOffset
-> [a]
-> [a i (MatchOffset, MatchOffset)]
-> [a i ([a], (MatchOffset, MatchOffset))]
go (MatchOffset
off0forall a. Num a => a -> a -> a
+MatchOffset
len0) [a]
t' [a i (MatchOffset, MatchOffset)]
xs)
    in forall {a :: * -> * -> *} {a} {i}.
(IArray a ([a], (MatchOffset, MatchOffset)),
 IArray a (MatchOffset, MatchOffset), Ix i, Num i) =>
MatchOffset
-> [a]
-> [a i (MatchOffset, MatchOffset)]
-> [a i ([a], (MatchOffset, MatchOffset))]
go MatchOffset
0 String
s (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r String
s)

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