{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 800
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
#else
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
#endif
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module Text.RE.ZeInternals.SearchReplace
( unsafeCompileSearchReplace_
, compileSearchReplace_
, compileSearchAndReplace_
) where
import Control.Monad.Fail
import qualified Data.HashMap.Strict as HMS
import Prelude.Compat hiding (fail)
import Text.RE.ZeInternals.NamedCaptures
import Text.RE.ZeInternals.Replace
import Text.RE.ZeInternals.Types.Capture
import Text.RE.ZeInternals.Types.CaptureID
import Text.RE.ZeInternals.Types.Matches
import Text.RE.ZeInternals.Types.Poss
import Text.RE.ZeInternals.Types.SearchReplace
import qualified Text.Regex.TDFA as TDFA
unsafeCompileSearchReplace_ :: (String->s)
-> (String->Either String re)
-> String
-> SearchReplace re s
unsafeCompileSearchReplace_ pk cf = poss err id . compileSearchReplace_ pk cf
where
err msg = error $ "unsafeCompileSearchReplace_: " ++ msg
compileSearchReplace_ :: (Monad m,MonadFail m,Functor m)
=> (String->s)
-> (String->Either String re)
-> String
-> m (SearchReplace re s)
compileSearchReplace_ pack compile_re sr_tpl = poss fail return $ do
case mainCaptures $ sr_tpl $=~ "///" of
[cap] ->
compileSearchAndReplace_ pack compile_re
(capturePrefix cap) (captureSuffix cap)
_ -> Eek $ "bad search-replace template syntax: " ++ sr_tpl
compileSearchAndReplace_ :: (Monad m,MonadFail m,Functor m)
=> (String->s)
-> (String->Either String re)
-> String
-> String
-> m (SearchReplace re s)
compileSearchAndReplace_ pack compile_re re_s tpl = either fail return $ do
re <- compile_re re_s
((n,cnms),_) <- extractNamedCaptures re_s
mapM_ (check n cnms) $ templateCaptures id tpl
return $ SearchReplace re $ pack tpl
where
check :: Int -> CaptureNames -> CaptureID -> Either String ()
check n cnms cid = case cid of
IsCaptureOrdinal co -> check_co n co
IsCaptureName cn -> check_cn cnms cn
check_co n (CaptureOrdinal i) = case i <= n of
True -> return ()
False -> Left $ "capture ordinal out of range: " ++
show i ++ " >= " ++ show n
check_cn cnms cnm = case cnm `HMS.member` cnms of
True -> return ()
False -> Left $ "capture name not defined: " ++
show (getCaptureName cnm)
($=~) :: String -> String -> Matches String
($=~) = (TDFA.=~)