    {- |
    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 = String -> String -> a
    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 -> String -> v
    forall a. String -> a
    err (String
    "Text.Regex.TDFA.String died: "String -> String -> String
    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 -> String -> Either String Regex
    forall a b. a -> Either a b
    Left (String
    "parseRegex for Text.Regex.TDFA.String failed:"String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ParseError -> String
    forall a. Show a => a -> String
    show ParseError
    msg)
        Right (Pattern, (MatchOffset, DoPa))
    pattern -> Regex -> Either String Regex
    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 = Either String Regex -> Regex
    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 = (String -> m Regex)
    -> (Regex -> m Regex) -> Either String Regex -> m Regex
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either String -> m Regex
    forall a. String -> m a
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail Regex -> m Regex
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either String Regex -> m Regex) -> Either String Regex -> m Regex
    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 = Maybe MatchArray -> Either String (Maybe MatchArray)
    forall a b. b -> Either a b
    Right (Regex -> String -> Maybe MatchArray
    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 = Maybe (String, String, String, [String])
    -> Either String (Maybe (String, String, String, [String]))
    forall a b. b -> Either a b
    Right (Maybe (String, String, String, [String])
     -> Either String (Maybe (String, String, String, [String])))
    -> Maybe (String, String, String, [String])
    -> Either String (Maybe (String, String, String, [String]))
    forall a b. (a -> b) -> a -> b
    $
      case Regex -> String -> Maybe (String, MatchText String, String)
    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 <- ((String, (MatchOffset, MatchOffset)) -> String)
    -> [(String, (MatchOffset, MatchOffset))] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (String, (MatchOffset, MatchOffset)) -> String
    forall a b. (a, b) -> a
    fst (MatchText String -> [(String, (MatchOffset, MatchOffset))]
    forall (a :: * -> * -> *) e i. (IArray a e, Ix i) => a i e -> [e]
    elems MatchText String
    mt)
          -> (String, String, String, [String])
    -> Maybe (String, String, String, [String])
    forall a. a -> Maybe a
    Just (String
    pre, String
    main, String
    post, [String]
    rest)
        Maybe (String, MatchText String, String)
    _ -> Maybe (String, String, 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 = [MatchArray] -> Maybe MatchArray
    forall a. [a] -> Maybe a
    listToMaybe (Regex -> String -> [MatchArray]
    forall regex source.
    RegexLike regex source =>
    regex -> source -> [MatchArray]
    matchAll Regex
    r String
    s)
      matchAll :: Regex -> String -> [MatchArray]
    matchAll Regex
    r String
    s = Regex -> MatchOffset -> Char -> String -> [MatchArray]
    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 = [MatchArray] -> MatchOffset
    forall a. [a] -> MatchOffset
    forall (t :: * -> *) a. Foldable t => t a -> MatchOffset
    length (Regex -> String -> [MatchArray]
    forall regex source.
    RegexLike regex source =>
    regex -> source -> [MatchArray]
    matchAll Regex
    r' String
    s)
        where r' :: Regex
    r' = Regex
    r { regex_execOptions = (regex_execOptions r) {captureGroups = False} }
      matchTest :: Regex -> String -> Bool
    matchTest = Regex -> String -> Bool
    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 MatchOffset -> Bool -> Bool
    forall a b. a -> b -> b
    `seq` Bool
    False = [a i ([a], (MatchOffset, MatchOffset))]
    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)
    xa i (MatchOffset, MatchOffset) -> i -> (MatchOffset, MatchOffset)
    forall (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) = (MatchOffset -> [a] -> [a]
    forall a. MatchOffset -> [a] -> [a]
    take MatchOffset
    len (MatchOffset -> [a] -> [a]
    forall a. MatchOffset -> [a] -> [a]
    drop (MatchOffset
    offMatchOffset -> MatchOffset -> MatchOffset
    forall a. Num a => a -> a -> a
    -MatchOffset
    i) [a]
    t),(MatchOffset, MatchOffset)
    pair)
                                t' :: [a]
    t' = MatchOffset -> [a] -> [a]
    forall a. MatchOffset -> [a] -> [a]
    drop (MatchOffset
    off0MatchOffset -> MatchOffset -> MatchOffset
    forall a. Num a => a -> a -> a
    +MatchOffset
    len0MatchOffset -> MatchOffset -> MatchOffset
    forall a. Num a => a -> a -> a
    -MatchOffset
    i) [a]
    t
                            in ((MatchOffset, MatchOffset) -> ([a], (MatchOffset, MatchOffset)))
    -> a i (MatchOffset, MatchOffset)
    -> a i ([a], (MatchOffset, MatchOffset))
    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 a i ([a], (MatchOffset, MatchOffset))
    -> [a i ([a], (MatchOffset, MatchOffset))]
    -> [a i ([a], (MatchOffset, MatchOffset))]
    forall a. a -> [a] -> [a]
    : [a]
    -> [a i ([a], (MatchOffset, MatchOffset))]
    -> [a i ([a], (MatchOffset, MatchOffset))]
    forall a b. a -> b -> b
    seq [a]
    t' (MatchOffset
    -> [a]
    -> [a i (MatchOffset, MatchOffset)]
    -> [a i ([a], (MatchOffset, MatchOffset))]
    go (MatchOffset
    off0MatchOffset -> MatchOffset -> MatchOffset
    forall a. Num a => a -> a -> a
    +MatchOffset
    len0) [a]
    t' [a i (MatchOffset, MatchOffset)]
    xs)
        in MatchOffset -> String -> [MatchArray] -> [MatchText String]
    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 (Regex -> String -> [MatchArray]
    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 = Regex -> String -> String
    forall a b. RegexLike a b => a -> b -> b
    polymatch
      matchM :: forall (m :: * -> *). MonadFail m => Regex -> String -> m String
    matchM = Regex -> String -> m String
    forall a b (m :: * -> *).
    (RegexLike a b, MonadFail m) =>
    a -> b -> m b
    polymatchM