1{-|
2This modules provides 'RegexMaker' and 'RegexLike' instances for using
3@ByteString@ with the DFA backend ("Text.Regex.Lib.WrapDFAEngine" and
4"Text.Regex.Lazy.DFAEngineFPS").  This module is usually used via
5import "Text.Regex.TDFA".
6
7This exports instances of the high level API and the medium level
8API of 'compile','execute', and 'regexec'.
9-}
10module Text.Regex.TDFA.ByteString.Lazy(
11  Regex
12 ,CompOption
13 ,ExecOption
14 ,compile
15 ,execute
16 ,regexec
17 ) where
18
19import Data.Array.IArray((!),elems,amap)
20import qualified Data.ByteString.Lazy.Char8 as L(ByteString,take,drop,unpack)
21
22import Text.Regex.Base(MatchArray,RegexContext(..),RegexMaker(..),RegexLike(..))
23import Text.Regex.Base.Impl(polymatch,polymatchM)
24import Text.Regex.TDFA.ReadRegex(parseRegex)
25import Text.Regex.TDFA.String() -- piggyback on RegexMaker for String
26import Text.Regex.TDFA.TDFA(patternToRegex)
27import Text.Regex.TDFA.Common(Regex(..),CompOption,ExecOption(captureGroups))
28
29import Data.Maybe(listToMaybe)
30import Text.Regex.TDFA.NewDFA.Engine(execMatch)
31import Text.Regex.TDFA.NewDFA.Tester as Tester(matchTest)
32
33{- By Chris Kuklewicz, 2007. BSD License, see the LICENSE file. -}
34
35instance RegexContext Regex L.ByteString L.ByteString where
36  match = polymatch
37  matchM = polymatchM
38
39instance RegexMaker Regex CompOption ExecOption L.ByteString where
40  makeRegexOptsM c e source = makeRegexOptsM c e (L.unpack source)
41
42instance RegexLike Regex L.ByteString where
43  matchOnce r s = listToMaybe (matchAll r s)
44  matchAll r s = execMatch r 0 '\n' s
45  matchCount r s = length (matchAll r' s)
46    where r' = r { regex_execOptions = (regex_execOptions r) {captureGroups = False} }
47  matchTest = Tester.matchTest
48  matchOnceText regex source =
49    fmap (\ma ->
50            let (o32,l32) = ma!0
51                o = fi o32
52                l = fi l32
53            in (L.take o source
54               ,fmap (\ol@(off32,len32) ->
55                        let off = fi off32
56                            len = fi len32
57                        in (L.take len (L.drop off source),ol)) ma
58               ,L.drop (o+l) source))
59         (matchOnce regex source)
60  matchAllText regex source =
61    let go i _ _ | i `seq` False = undefined
62        go _i _t [] = []
63        go i t (x:xs) =
64          let (off0,len0) = x!0
65              trans pair@(off32,len32) = (L.take (fi len32) (L.drop (fi (off32-i)) t),pair)
66              t' = L.drop (fi (off0+len0-i)) t
67          in amap trans x : seq t' (go (off0+len0) t' xs)
68    in go 0 source (matchAll regex source)
69
70fi :: (Integral a, Num b) => a -> b
71fi = fromIntegral
72
73compile :: CompOption -- ^ Flags (summed together)
74        -> ExecOption -- ^ Flags (summed together)
75        -> L.ByteString -- ^ The regular expression to compile
76        -> Either String Regex -- ^ Returns: the compiled regular expression
77compile compOpt execOpt bs =
78  case parseRegex (L.unpack bs) of
79    Left err -> Left ("parseRegex for Text.Regex.TDFA.ByteString failed:"++show err)
80    Right pattern -> Right (patternToRegex pattern compOpt execOpt)
81
82execute :: Regex      -- ^ Compiled regular expression
83        -> L.ByteString -- ^ ByteString to match against
84        -> Either String (Maybe MatchArray)
85execute r bs = Right (matchOnce r bs)
86
87regexec :: Regex      -- ^ Compiled regular expression
88        -> L.ByteString -- ^ ByteString to match against
89        -> Either String (Maybe (L.ByteString, L.ByteString, L.ByteString, [L.ByteString]))
90regexec r bs =
91  case matchOnceText r bs of
92    Nothing -> Right (Nothing)
93    Just (pre,mt,post) ->
94      let main = fst (mt!0)
95          rest = map fst (tail (elems mt)) -- will be []
96      in Right (Just (pre,main,post,rest))
97