regex-parsec-0.90: Text/Regex/Parsec/Sequence.hs
{-# OPTIONS_GHC -fglasgow-exts -fno-warn-orphans #-}
{-|
This offers type class instances for 'RegexMaker' and
'RegexLike'. This is usually used via import "Text.Regex.Full".
It is worth noting that 'RegexMaker' and 'RegexLike' methods for
'ByteString' are built on those for 'String' except the default
'matchOnceText' and 'matchAllText' are used since they are already
efficient for use on 'ByteString' (and they use 'matchOnce' and
'matchAll').
This exports instances of the high level API and the medium level
API of 'compile','execute', and 'regexec'.
-}
module Text.Regex.Parsec.Sequence(
-- ** Types
Regex
,MatchOffset
,MatchLength
,CompOption(..)
,ExecOption(..)
-- ** Medium level API functions
,compile
,execute
,regexec
) where
import Data.Array(Array,elems,accumArray)
import qualified Data.IntMap as I (toList,(!))
import Text.Regex.Parsec.Common(MatchedStrings)
import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchText,MatchArray,MatchOffset,MatchLength)
import Text.Regex.Parsec.Wrap(Regex(..),CompOption(..),ExecOption(..),wrapCompile,wrapMatch)
import Text.Regex.Parsec.String() -- build on these instances for RegexMaker and RegexLike
import Data.Sequence(Seq)
import Data.Sequence(ViewL(..))
import qualified Data.Sequence as S
import Text.Regex.Base.Impl(polymatch,polymatchM)
instance RegexContext Regex (Seq Char) (Seq Char) where
match = polymatch
matchM = polymatchM
instance RegexMaker Regex CompOption ExecOption (Seq Char) where
makeRegexOpts opts e source = makeRegexOpts opts e (unpack source)
makeRegexOptsM opts e source = makeRegexOptsM opts e (unpack source)
instance RegexLike Regex (Seq Char) where
matchOnce r bs = matchOnce r (unpack bs)
matchAll r bs = matchAll r (unpack bs)
matchTest r bs = matchTest r (unpack bs)
matchCount r bs = matchCount r (unpack bs)
-- Use default matchOnceText and matchAllText
{-# INLINE unpack #-}
unpack :: (Seq Char) -> String
unpack s = case S.viewl s of
EmptyL -> []
(h :< t) -> h : unpack t
compile :: CompOption -- ^ Flags (summed together)
-> ExecOption -- ^ Flags (summed together)
-> (Seq Char) -- ^ The regular expression to compile
-> Either String Regex -- ^ Returns: the compiled regular expression
compile c e bs = wrapCompile c e (unpack bs)
execute :: Regex -- ^ Compiled regular expression
-> (Seq Char) -- ^ (Seq Char) to match against
-> Either String (Maybe (Array Int (MatchOffset,MatchLength)))
execute r@(Regex {groups=g}) bs = either Left (Right . (fmap (toArr g))) (wrapMatch 0 r (unpack bs))
regexec :: Regex -- ^ Compiled regular expression
-> (Seq Char) -- ^ (Seq Char) to match against
-> Either String (Maybe ((Seq Char), (Seq Char), (Seq Char), [(Seq Char)]))
regexec r@(Regex {groups=g}) bs =
case wrapMatch 0 r (unpack bs) of
Left err -> Left err
Right Nothing -> Right Nothing
Right (Just ms) -> Right . Just $
let (_,(o,l)) = ms I.! 0
in (S.take o bs
,S.take l (S.drop o bs)
,S.drop (o+l) bs
,map (\(_,(o',l')) -> if (-1)==o'
then S.empty
else S.take l' (S.drop o' bs))
(tail (elems (toMT g ms))))
toMT :: Int -> MatchedStrings -> MatchText String
toMT maxSubs ms = accumArray (\_ new->new) ("",(-1,0)) (0,maxSubs) (I.toList ms)
toArr :: Int -> MatchedStrings -> MatchArray
toArr maxSubs ms = accumArray (\_ (_,ol)->ol) (-1,0) (0,maxSubs) (I.toList ms)