module Re ( matchOnce, matchAll, matchCount, matchTest, replace, replaceMap ) where import qualified Text.Regex.Base as B ( RegexMaker(..) , RegexLike(..) , RegexContext(..) , defaultExecOpt , MatchText , MatchArray ) import Text.Regex.Posix as P ( Regex , compNewline , compIgnoreCase , compExtended ) import Data.Array ((!), indices, bounds, elems) makeRegex :: String -> Regex makeRegex = B.makeRegex matchOnce :: String -> String -> Maybe (String, B.MatchText String, String) matchOnce r s = B.matchOnceText (makeRegex r) s matchAll :: String -> String -> [((String, Int), [String])] matchAll r s = do let matches = B.matchAllText (makeRegex r) s map (\m -> ((substr m, count m), values m)) matches where values m = map (\n -> fst (m!n)) (drop 1 $ indices m) count m = snd $ bounds m substr m = fst (m!0) matchCount :: String -> String -> Int matchCount r s = B.matchCount (makeRegex r) s matchTest :: String -> String -> Bool matchTest r s = B.matchTest (makeRegex r) s replace :: String -> String -> String -> String replace r s m = replaceMap r s (func m) where func tmpl ps = compile "\\\\([0-9])" tmpl ps compile :: String -> String -> [String] -> String compile r s m = replaceMap r s (func m) where func ms ps = ms !! (read $ (ps!!1) :: Int) replaceMap :: String -> String -> ([String] -> String) -> String replaceMap r s f = do let matches = B.matchAllText (makeRegex r) s let splited = _split 0 s (map (\m -> m!0) matches) concat $ _replacer splited matches f where _replacer [] _ _ = [] _replacer s [] _ = s _replacer ss ms f = do let ps = map (\m -> fst m) $ elems (head ms) [head ss] ++ [f ps] ++ (_replacer (tail ss) (tail ms) f) _split _ s [] = [s] _split i s m = do let (offset, len) = snd (head m) let pre = take (offset - i) s let left = drop (offset + len - i) s pre : ( _split (offset + len) left (tail m) )