{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-unused-binds #-}
{-# LANGUAGE NoImplicitPrelude, UndecidableInstances, FlexibleInstances, FlexibleContexts, BangPatterns #-}
{-# LANGUAGE TemplateHaskell, QuasiQuotes, UnicodeSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface, CPP #-}
#if __GLASGOW_HASKELL__ < 710
{-# LANGUAGE OverlappingInstances #-}
#endif
module Text.Regex.PCRE.Heavy (
(=~)
, (≈)
, scan
, scanO
, scanRanges
, scanRangesO
, RegexReplacement
, sub
, subO
, gsub
, gsubO
, split
, splitO
, re
, mkRegexQQ
, escape
, Regex
, PCREOption
, PCRE.compileM
, rawMatch
, rawSub
) where
import Prelude.Compat
import Language.Haskell.TH hiding (match)
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax
import qualified Text.Regex.PCRE.Light as PCRE
import Text.Regex.PCRE.Light.Base
import Data.Maybe (isJust, fromMaybe)
import Data.List (unfoldr, mapAccumL)
import qualified Data.List.NonEmpty as NE
import Data.String.Conversions
import Data.String.Conversions.Monomorphic
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Internal as BS
import System.IO.Unsafe (unsafePerformIO)
import Foreign (withForeignPtr, allocaBytes, nullPtr, plusPtr, peekElemOff)
substr ∷ SBS → (Int, Int) → SBS
substr :: SBS -> (Int, Int) -> SBS
substr SBS
s (Int
f, Int
t) = Int -> SBS -> SBS
BS.take (Int
t forall a. Num a => a -> a -> a
- Int
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SBS -> SBS
BS.drop Int
f forall a b. (a -> b) -> a -> b
$ SBS
s
behead ∷ NE.NonEmpty a → (a, [a])
behead :: forall a. NonEmpty a -> (a, [a])
behead NonEmpty a
l = (forall a. NonEmpty a -> a
NE.head NonEmpty a
l, forall a. NonEmpty a -> [a]
NE.tail NonEmpty a
l)
reMatch ∷ ConvertibleStrings a SBS ⇒ Regex → a → Bool
reMatch :: forall a. ConvertibleStrings a SBS => Regex -> a -> Bool
reMatch Regex
r a
s = forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ Regex -> SBS -> [PCREExecOption] -> Maybe [SBS]
PCRE.match Regex
r (forall a b. ConvertibleStrings a b => a -> b
cs a
s) []
(=~), (≈) ∷ ConvertibleStrings a SBS ⇒ a → Regex → Bool
=~ :: forall a. ConvertibleStrings a SBS => a -> Regex -> Bool
(=~) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. ConvertibleStrings a SBS => Regex -> a -> Bool
reMatch
≈ :: forall a. ConvertibleStrings a SBS => a -> Regex -> Bool
(≈) = forall a. ConvertibleStrings a SBS => a -> Regex -> Bool
(=~)
rawMatch ∷ Regex → SBS → Int → [PCREExecOption] → Maybe [(Int, Int)]
rawMatch :: Regex -> SBS -> Int -> [PCREExecOption] -> Maybe [(Int, Int)]
rawMatch r :: Regex
r@(Regex ForeignPtr PCRE
pcreFp SBS
_) SBS
s Int
offset [PCREExecOption]
opts = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr PCRE
pcreFp forall a b. (a -> b) -> a -> b
$ \Ptr PCRE
pcrePtr → do
let nCapt :: Int
nCapt = Regex -> Int
PCRE.captureCount Regex
r
ovecSize :: Int
ovecSize = (Int
nCapt forall a. Num a => a -> a -> a
+ Int
1) forall a. Num a => a -> a -> a
* Int
3
ovecBytes :: Int
ovecBytes = Int
ovecSize forall a. Num a => a -> a -> a
* Int
size_of_cint
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
ovecBytes forall a b. (a -> b) -> a -> b
$ \Ptr CInt
ovec → do
let (ForeignPtr Word8
strFp, Int
off, Int
len) = SBS -> (ForeignPtr Word8, Int, Int)
BS.toForeignPtr SBS
s
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
strFp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
strPtr → do
CInt
results ← Ptr PCRE
-> Ptr PCRE
-> Ptr Word8
-> CInt
-> CInt
-> PCREExecOption
-> Ptr CInt
-> CInt
-> IO CInt
c_pcre_exec Ptr PCRE
pcrePtr forall a. Ptr a
nullPtr (Ptr Word8
strPtr forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
offset)
([PCREExecOption] -> PCREExecOption
combineExecOptions [PCREExecOption]
opts) Ptr CInt
ovec (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ovecSize)
if CInt
results forall a. Ord a => a -> a -> Bool
< CInt
0 then forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
else
let loop :: CInt -> Int -> [(a, b)] -> IO (Maybe [(a, b)])
loop CInt
n Int
o [(a, b)]
acc =
if CInt
n forall a. Eq a => a -> a -> Bool
== CInt
results then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [(a, b)]
acc
else do
CInt
i ← forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr CInt
ovec forall a b. (a -> b) -> a -> b
$! Int
o
CInt
j ← forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr CInt
ovec (Int
o forall a. Num a => a -> a -> a
+ Int
1)
CInt -> Int -> [(a, b)] -> IO (Maybe [(a, b)])
loop (CInt
n forall a. Num a => a -> a -> a
+ CInt
1) (Int
o forall a. Num a => a -> a -> a
+ Int
2) ((forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
i, forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
j) forall a. a -> [a] -> [a]
: [(a, b)]
acc)
in forall {a} {b}.
(Num a, Num b) =>
CInt -> Int -> [(a, b)] -> IO (Maybe [(a, b)])
loop CInt
0 Int
0 []
nextMatch ∷ Regex → [PCREExecOption] → SBS → Int → Maybe (NE.NonEmpty (Int, Int), Int)
nextMatch :: Regex
-> [PCREExecOption]
-> SBS
-> Int
-> Maybe (NonEmpty (Int, Int), Int)
nextMatch Regex
r [PCREExecOption]
opts SBS
str Int
offset =
Regex -> SBS -> Int -> [PCREExecOption] -> Maybe [(Int, Int)]
rawMatch Regex
r SBS
str Int
offset [PCREExecOption]
opts forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \NonEmpty (Int, Int)
ms → forall (m :: * -> *) a. Monad m => a -> m a
return (NonEmpty (Int, Int)
ms, forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd NonEmpty (Int, Int)
ms)
scan ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → [(a, [a])]
scan :: forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> a -> [(a, [a])]
scan Regex
r a
s = forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> [PCREExecOption] -> a -> [(a, [a])]
scanO Regex
r [] a
s
scanO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → [PCREExecOption] → a → [(a, [a])]
scanO :: forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> [PCREExecOption] -> a -> [(a, [a])]
scanO Regex
r [PCREExecOption]
opts a
s = forall a b. (a -> b) -> [a] -> [b]
map forall a. NonEmpty a -> (a, [a])
behead forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. ConvertibleStrings a b => a -> b
cs forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBS -> (Int, Int) -> SBS
substr SBS
str) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (Regex
-> [PCREExecOption]
-> SBS
-> Int
-> Maybe (NonEmpty (Int, Int), Int)
nextMatch Regex
r [PCREExecOption]
opts SBS
str) Int
0
where str :: SBS
str = forall a. ConvertibleStrings a SBS => a -> SBS
toSBS a
s
scanRanges ∷ ConvertibleStrings a SBS ⇒ Regex → a → [((Int, Int), [(Int, Int)])]
scanRanges :: forall a.
ConvertibleStrings a SBS =>
Regex -> a -> [((Int, Int), [(Int, Int)])]
scanRanges Regex
r a
s = forall a.
ConvertibleStrings a SBS =>
Regex -> [PCREExecOption] -> a -> [((Int, Int), [(Int, Int)])]
scanRangesO Regex
r [] a
s
scanRangesO ∷ ConvertibleStrings a SBS ⇒ Regex → [PCREExecOption] → a → [((Int, Int), [(Int, Int)])]
scanRangesO :: forall a.
ConvertibleStrings a SBS =>
Regex -> [PCREExecOption] -> a -> [((Int, Int), [(Int, Int)])]
scanRangesO Regex
r [PCREExecOption]
opts a
s = forall a b. (a -> b) -> [a] -> [b]
map forall a. NonEmpty a -> (a, [a])
behead forall a b. (a -> b) -> a -> b
$ forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (Regex
-> [PCREExecOption]
-> SBS
-> Int
-> Maybe (NonEmpty (Int, Int), Int)
nextMatch Regex
r [PCREExecOption]
opts SBS
str) Int
0
where str :: SBS
str = forall a. ConvertibleStrings a SBS => a -> SBS
toSBS a
s
class RegexReplacement a where
performReplacement ∷ SBS → [SBS] → a → SBS
instance {-# OVERLAPPABLE #-} ConvertibleStrings a SBS ⇒ RegexReplacement a where
performReplacement :: SBS -> [SBS] -> a -> SBS
performReplacement SBS
_ [SBS]
_ a
to = forall a b. ConvertibleStrings a b => a -> b
cs a
to
instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement (a → [a] → a) where
performReplacement :: SBS -> [SBS] -> (a -> [a] -> a) -> SBS
performReplacement SBS
from [SBS]
groups a -> [a] -> a
replacer = forall a b. ConvertibleStrings a b => a -> b
cs forall a b. (a -> b) -> a -> b
$ a -> [a] -> a
replacer (forall a b. ConvertibleStrings a b => a -> b
cs SBS
from) (forall a b. (a -> b) -> [a] -> [b]
map forall a b. ConvertibleStrings a b => a -> b
cs [SBS]
groups)
instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement (a → a) where
performReplacement :: SBS -> [SBS] -> (a -> a) -> SBS
performReplacement SBS
from [SBS]
_ a -> a
replacer = forall a b. ConvertibleStrings a b => a -> b
cs forall a b. (a -> b) -> a -> b
$ a -> a
replacer (forall a b. ConvertibleStrings a b => a -> b
cs SBS
from)
instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement ([a] → a) where
performReplacement :: SBS -> [SBS] -> ([a] -> a) -> SBS
performReplacement SBS
_ [SBS]
groups [a] -> a
replacer = forall a b. ConvertibleStrings a b => a -> b
cs forall a b. (a -> b) -> a -> b
$ [a] -> a
replacer (forall a b. (a -> b) -> [a] -> [b]
map forall a b. ConvertibleStrings a b => a -> b
cs [SBS]
groups)
rawSub ∷ RegexReplacement r ⇒ Regex → r → SBS → Int → [PCREExecOption] → Maybe (SBS, Int)
rawSub :: forall r.
RegexReplacement r =>
Regex -> r -> SBS -> Int -> [PCREExecOption] -> Maybe (SBS, Int)
rawSub Regex
r r
t SBS
s Int
offset [PCREExecOption]
opts =
case Regex -> SBS -> Int -> [PCREExecOption] -> Maybe [(Int, Int)]
rawMatch Regex
r SBS
s Int
offset [PCREExecOption]
opts of
Just ((Int
begin, Int
end):[(Int, Int)]
groups) →
let replacement :: SBS
replacement = forall a. RegexReplacement a => SBS -> [SBS] -> a -> SBS
performReplacement (SBS -> (Int, Int) -> SBS
substr SBS
s (Int
begin, Int
end)) (forall a b. (a -> b) -> [a] -> [b]
map (SBS -> (Int, Int) -> SBS
substr SBS
s) [(Int, Int)]
groups) r
t in
forall a. a -> Maybe a
Just ([SBS] -> SBS
BS.concat [ SBS -> (Int, Int) -> SBS
substr SBS
s (Int
0, Int
begin)
, SBS
replacement
, SBS -> (Int, Int) -> SBS
substr SBS
s (Int
end, SBS -> Int
BS.length SBS
s)], Int
begin forall a. Num a => a -> a -> a
+ SBS -> Int
BS.length SBS
replacement)
Maybe [(Int, Int)]
_ → forall a. Maybe a
Nothing
sub ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → r → a → a
sub :: forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> r -> a -> a
sub Regex
r r
t a
s = forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> [PCREExecOption] -> r -> a -> a
subO Regex
r [] r
t a
s
subO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
subO :: forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> [PCREExecOption] -> r -> a -> a
subO Regex
r [PCREExecOption]
opts r
t a
s = forall a. a -> Maybe a -> a
fromMaybe a
s forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall r.
RegexReplacement r =>
Regex -> r -> SBS -> Int -> [PCREExecOption] -> Maybe (SBS, Int)
rawSub Regex
r r
t (forall a b. ConvertibleStrings a b => a -> b
cs a
s) Int
0 [PCREExecOption]
opts
gsub ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → r → a → a
gsub :: forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> r -> a -> a
gsub Regex
r r
t a
s = forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> [PCREExecOption] -> r -> a -> a
gsubO Regex
r [] r
t a
s
gsubO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
gsubO :: forall a r.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS,
RegexReplacement r) =>
Regex -> [PCREExecOption] -> r -> a -> a
gsubO Regex
r [PCREExecOption]
opts r
t a
s = forall a b. ConvertibleStrings a b => a -> b
cs forall a b. (a -> b) -> a -> b
$ Int -> SBS -> SBS
loop Int
0 SBS
str
where str :: SBS
str = forall a. ConvertibleStrings a SBS => a -> SBS
toSBS a
s
loop :: Int -> SBS -> SBS
loop Int
offset SBS
acc
| Int
offset forall a. Ord a => a -> a -> Bool
>= Int
l = SBS
acc
| Bool
otherwise = case forall r.
RegexReplacement r =>
Regex -> r -> SBS -> Int -> [PCREExecOption] -> Maybe (SBS, Int)
rawSub Regex
r r
t SBS
acc Int
offset [PCREExecOption]
opts of
Just (SBS
result, Int
newOffset) →
if Int
newOffset forall a. Eq a => a -> a -> Bool
== Int
offset Bool -> Bool -> Bool
&& Int
l forall a. Eq a => a -> a -> Bool
== SBS -> Int
BS.length SBS
result
then SBS
acc
else Int -> SBS -> SBS
loop Int
newOffset SBS
result
Maybe (SBS, Int)
_ → SBS
acc
where l :: Int
l = SBS -> Int
BS.length SBS
acc
split ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → [a]
split :: forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> a -> [a]
split Regex
r a
s = forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> [PCREExecOption] -> a -> [a]
splitO Regex
r [] a
s
splitO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → [PCREExecOption] → a → [a]
splitO :: forall a.
(ConvertibleStrings SBS a, ConvertibleStrings a SBS) =>
Regex -> [PCREExecOption] -> a -> [a]
splitO Regex
r [PCREExecOption]
opts a
s = forall a b. (a -> b) -> [a] -> [b]
map forall a b. ConvertibleStrings a b => a -> b
cs forall a b. (a -> b) -> a -> b
$ forall {t :: * -> *} {b}.
Foldable t =>
((Int, Int) -> b) -> t (Int, Int) -> [b]
map' (SBS -> (Int, Int) -> SBS
substr SBS
str) [(Int, Int)]
partRanges
where map' :: ((Int, Int) -> b) -> t (Int, Int) -> [b]
map' (Int, Int) -> b
f = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((:) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> b
f) [(Int, Int) -> b
f (Int
lastL, SBS -> Int
BS.length SBS
str)]
(Int
lastL, [(Int, Int)]
partRanges) = forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL forall {a} {b} {a}. a -> (b, a) -> (a, (a, b))
invRange Int
0 [(Int, Int)]
ranges
invRange :: a -> (b, a) -> (a, (a, b))
invRange a
acc (b
xl, a
xr) = (a
xr, (a
acc, b
xl))
ranges :: [(Int, Int)]
ranges = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a.
ConvertibleStrings a SBS =>
Regex -> [PCREExecOption] -> a -> [((Int, Int), [(Int, Int)])]
scanRangesO Regex
r [PCREExecOption]
opts SBS
str
str :: SBS
str = forall a. ConvertibleStrings a SBS => a -> SBS
toSBS a
s
instance Lift PCREOption where
liftTyped :: forall (m :: * -> *). Quote m => PCREOption -> Code m PCREOption
liftTyped PCREOption
o = let o' :: String
o' = forall a. Show a => a -> String
show PCREOption
o in [|| read o' ∷ PCREOption ||]
quoteExpRegex ∷ [PCREOption] → String → ExpQ
quoteExpRegex :: [PCREOption] -> String -> ExpQ
quoteExpRegex [PCREOption]
opts String
txt = [| PCRE.compile (cs (txt ∷ String)) opts |]
where !Regex
_ = SBS -> [PCREOption] -> Regex
PCRE.compile (forall a b. ConvertibleStrings a b => a -> b
cs String
txt) [PCREOption]
opts
mkRegexQQ ∷ [PCREOption] → QuasiQuoter
mkRegexQQ :: [PCREOption] -> QuasiQuoter
mkRegexQQ [PCREOption]
opts = QuasiQuoter
{ quoteExp :: String -> ExpQ
quoteExp = [PCREOption] -> String -> ExpQ
quoteExpRegex [PCREOption]
opts
, quotePat :: String -> Q Pat
quotePat = forall a. HasCallStack => a
undefined
, quoteType :: String -> Q Type
quoteType = forall a. HasCallStack => a
undefined
, quoteDec :: String -> Q [Dec]
quoteDec = forall a. HasCallStack => a
undefined }
re ∷ QuasiQuoter
re :: QuasiQuoter
re = [PCREOption] -> QuasiQuoter
mkRegexQQ [PCREOption
utf8]
pcreMetachars ∷ SBS
pcreMetachars :: SBS
pcreMetachars = SBS
"\\^$.[|()?*+{"
startQuoteMarker, endQuoteMarker ∷ SBS
startQuoteMarker :: SBS
startQuoteMarker = SBS
"\\Q"
endQuoteMarker :: SBS
endQuoteMarker = SBS
"\\E"
escape ∷ (ConvertibleStrings a SBS, ConvertibleStrings SBS a) ⇒ a → a
escape :: forall a.
(ConvertibleStrings a SBS, ConvertibleStrings SBS a) =>
a -> a
escape = forall a b. ConvertibleStrings a b => a -> b
convertString forall b c a. (b -> c) -> (a -> b) -> a -> c
. SBS -> SBS
escapeSBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ConvertibleStrings a b => a -> b
convertString
where escapeSBS :: SBS -> SBS
escapeSBS SBS
s
| SBS
endQuoteMarker SBS -> SBS -> Bool
`BS.isInfixOf` SBS
s = (Char -> SBS) -> SBS -> SBS
BS.concatMap Char -> SBS
step SBS
s
| Bool
otherwise = [SBS] -> SBS
BS.concat [SBS
startQuoteMarker, SBS
s, SBS
endQuoteMarker]
step :: Char -> SBS
step Char
c
| Char
c Char -> SBS -> Bool
`BS.elem` SBS
pcreMetachars = String -> SBS
BS.pack [Char
'\\', Char
c]
| Bool
otherwise = Char -> SBS
BS.singleton Char
c