{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
module Text.Regex (
Regex,
mkRegex,
mkRegexWithOpts,
matchRegex,
matchRegexAll,
subRegex,
splitRegex
) where
import Data.Array((!))
import Data.Bits((.|.))
import Text.Regex.Base(RegexMaker(makeRegexOpts),defaultExecOpt,RegexLike(matchAll,matchAllText),RegexContext(matchM),MatchText)
import Text.Regex.Posix(Regex,compNewline,compIgnoreCase,compExtended)
mkRegex :: String -> Regex
mkRegex s = makeRegexOpts opt defaultExecOpt s
where opt = compExtended .|. compNewline
mkRegexWithOpts
:: String
-> Bool
-> Bool
-> Regex
mkRegexWithOpts s single_line case_sensitive
= let opt = (if single_line then (compNewline .|.) else id) .
(if case_sensitive then id else (compIgnoreCase .|.)) $
compExtended
in makeRegexOpts opt defaultExecOpt s
matchRegex
:: Regex
-> String
-> Maybe [String]
matchRegex p str = fmap (\(_,_,_,str) -> str) (matchRegexAll p str)
matchRegexAll
:: Regex
-> String
-> Maybe ( String, String, String, [String] )
matchRegexAll p str = matchM p str
subRegex :: Regex
-> String
-> String
-> String
subRegex _ "" _ = ""
subRegex regexp inp repl =
let compile _i str [] = \ _m -> (str++)
compile i str (("\\",(off,len)):rest) =
let i' = off+len
pre = take (off-i) str
str' = drop (i'-i) str
in if null str' then \ _m -> (pre ++) . ('\\':)
else \ m -> (pre ++) . ('\\' :) . compile i' str' rest m
compile i str ((xstr,(off,len)):rest) =
let i' = off+len
pre = take (off-i) str
str' = drop (i'-i) str
x = read xstr
in if null str' then \ m -> (pre++) . ((fst (m!x))++)
else \ m -> (pre++) . ((fst (m!x))++) . compile i' str' rest m
compiled :: MatchText String -> String -> String
compiled = compile 0 repl findrefs where
bre = mkRegex "\\\\(\\\\|[0-9]+)"
findrefs = map (\m -> (fst (m!1),snd (m!0))) (matchAllText bre repl)
go _i str [] = str
go i str (m:ms) =
let (_,(off,len)) = m!0
i' = off+len
pre = take (off-i) str
str' = drop (i'-i) str
in if null str' then pre ++ (compiled m "")
else pre ++ (compiled m (go i' str' ms))
in go 0 inp (matchAllText regexp inp)
splitRegex :: Regex -> String -> [String]
splitRegex _ [] = []
splitRegex delim strIn =
let matches = map (!0) (matchAll delim strIn)
go _i str [] = str : []
go i str ((off,len):rest) =
let i' = off+len
firstline = take (off-i) str
remainder = drop (i'-i) str
in seq i' $
if null remainder then [firstline,""]
else firstline : go i' remainder rest
in go 0 strIn matches