packages feed

regex-base 0.83 → 0.90

raw patch · 4 files changed

+253/−80 lines, 4 files

Files

Text/Regex/Base.hs view
@@ -53,6 +53,6 @@  getVersion_Text_Regex_Base :: Version getVersion_Text_Regex_Base =-  Version { versionBranch = [0,83]+  Version { versionBranch = [0,90]           , versionTags = ["unstable"]           }
Text/Regex/Base/Context.hs view
@@ -9,88 +9,190 @@ Stability   :  experimental Portability :  non-portable (MPTC+FD) -This is a module of instances of 'RegexContext'.  Nothing else is-exported.   These work for all the front ends and backends-interchangably.  These instances are important because they provide-the different results that can be gotten from a match or matchM-operation (often via the @=~@ and @=~~@ operators).  The name is Context-because they are context dependent: use them in a context that expects-an Int and you get a count of matches, use them in a Bool context and-get True if there is a match, etc.+This is a module of instances of 'RegexContext' (defined in+Text.Regex.Base.RegexLike).  Nothing else is exported.  This is+usually imported via the Text.Regex.Base convenience package which+itself is re-exported from newer Text.Regex.XXX modules provided by+the different regex-xxx backends. +These instances work for all the supported types and backends+interchangably.  These instances provide the different results that+can be gotten from a match or matchM operation (often via the @=~@ and+@=~~@ operators with combine @makeRegex@ with @match@ and @matchM@+respectively).  This module name is Context because they operators are+context dependent: use them in a context that expects an Int and you+get a count of matches, use them in a Bool context and get True if+there is a match, etc.++@RegexContext a b c@ takes a regular expression suppied in a type 'a'+generated by 'RegexMaker' and a target text supplied in type 'b' to a+result type 'c' using the 'match' class function.  The 'matchM' class+function works like 'match' unless there is no match found, in which+case it calls 'fail' in the (arbitrary) monad context.++There are a few type synonyms from RegexLike that are used here:+ @ +-- | 0 based index from start of source, or (-1) for unused+type MatchOffset = Int+-- | non-negative length of a match+type MatchLength = Int type MatchArray = Array Int (MatchOffset, MatchLength) type MatchText source = Array Int (source, (MatchOffset, MatchLength)) @ -These are for the first match:+There are also a few newtypes that used to prevent any possible+overlap of types, which were not needed for GHC's late overlap+detection but are needed for use in Hugs. -(@ RegexLike a b => RegexContext a b Bool @) :-  Whether there is any match or not+@+newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}+newtype AllTextSubmatches f b = AllTextSubmatches (f b)+newtype AllMatches f b = AllMatches (f b)+newtype AllTextMatches f b = AllTextMatches (f b)+@ -(@ RegexLike a b => RegexContext a b () @) :-  Useful using @=~~@ in a monad, since failure to match is via 'fail'+The newtypes' @f@ parameters are the containers, usually @[]@ or+@Array Int@, (where the arrays all have lower bound 0). -(@ RegexLike a b => RegexContext a b (MatchOffset,MatchLength) @) :-  This returns the initial index and length of the whole match.-  Starting at (-1) indicates failure to match.+The two *Submatches newtypes return only information on the first+match.  The other two newtypes return information on all the+non-overlapping matches.  The two *Text* newtypes are used to mark+result types that contain the same type as the target text. -(@ RegexLike a b => RegexContext a b b @) :+Where provided, noncaptured submatches will have a @MatchOffset@ of+(-1) and non-negative otherwise.  The semantics of submatches depend+on the backend and its compile and execution options.  Where provided,+@MatchLength@ will always be non-negative.  Arrays with no elements+are returned with bounds of (1,0).  Arrays with elements will have a+lower bound of 0.++XXX THIS HADDOCK DOCUMENTATION IS OUT OF DATE XXX++These are for finding the first match in the target text:+++@ RegexContext a b Bool @ :+  Whether there is any match or not.+++@ RegexContext a b () @ :+  Useful as a guard with @matchM@ or @=~~@ in a monad, since failure to match calls 'fail'.+++@ RegexContext a b b @ :   This returns the text of the whole match.-  It will return 'empty' from 'Extract' if there is no match.-  These are defined in other modules, but documented here for convenience.+  It will return 'empty' from the 'Extract' type class if there is no match.+  These are defined in each backend module, but documented here for convenience. -(@ RegexLike a b => RegexContext a b MatchArray @) :-  Where each sub-part the match starts and its length.-  Starting at (-1) indicates unused. -(@ RegexLike a b => RegexContext a b (Array Int b) @) :-  The text of each sub-part of the match.-  Unused matches are 'empty' (defined via 'Extract')+@ RegexContext a b (MatchOffset,MatchLength) @ :+  This returns the initial index and length of the whole match.+  MatchLength will always be non-negative, and 0 for a failed match. -(@ RegexLike a b => RegexContext a b (b, MatchText b, b) @) :-  The text before the match, the details of the match, and the text after the match -(@ RegexLike a b => RegexContext a b (b, b, b) @) :+@ RegexContext a b (MatchResult b) @ : The+  'MatchResult' structure with details for the match.  This is the+  structure copied from the old @JRegex@ pacakge.+++@ RegexContext a b (b, b, b) @ :   The text before the match, the text of the match, the text after the match -(@ RegexLike a b => RegexContext a b (b, b, b, [b]) @) :-  The text before the match, the text of the match, the text after the match, and the text of the 1st and higher sub-parts of the match.  This is the same return value as used in Text.Regex. -(@ RegexLike a b => RegexContext a b (MatchResult b) @) :-  The 'MatchResult' structure for the match.+@ RegexContext a b (b, MatchText b, b) @ :+  The text before the match, the details of the match, and the text after the match -These instances are for all the matches (non-overlapping).  Note that backends are supposed to supply RegexLike instances for which matchAll and matchAllText stop searching after returning any successful but empty match. -(@ RegexLike a b => RegexContext a b Int @) :-  The number of matches+@ RegexContext a b (b, b, b, [b]) @ : +  The text before the match, the text of the match, the text after the+  match, and a list of the text of the 1st and higher sub-parts of the+  match.  This is the same return value as used in the old+  @Text.Regex@ API. -These instances similar to the single match ones above, but in a List:+Two containers of the submatch offset information: -(@ RegexLike a b => RegexContext a b [(MatchOffset, MatchLength)] @) : -(@ RegexLike a b => RegexContext a b [b] @) :-  As a policy, I chose [b] to be the list of whole text of each match.+@ RegexContext a b MatchArray @ :+  Array of @(MatchOffset,MatchLength)@ for all the sub matches.+  The whole match is at the intial 0th index.+  Noncaptured submatches will have a @MatchOffset@ of (-1)+  The array will have no elements and bounds (1,0) if there is no match. -(@ RegexLike a b => RegexContext a b [MatchArray] @) : -(@ RegexLike a b => RegexContext a b [Array Int b] @) :+@ RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength) @ :+  List of @(MatchOffset,MatchLength)@+  The whole match is the first element, the rest are the submatches (if any) in order.+  The list is empty if there is no match. -(@ RegexLike a b => RegexContext a b [MatchText b] @) :+Two containers of the submatch text and offset information: -(@ RegexLike a b => RegexContext a b [[b]] @) :-  This is the list of the list of the text of the sub-part of each match.-  Unused matches are 'empty' (defined via 'Extract')+@ RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) @ +@ RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength)))  @++Two containers of the submatch text information:++@ RegexContext a b (AllTextSubmatches [] b) @++@ RegexContext a b (AllTextSubmatches (Array Int) b) @++These instances are for all the matches (non-overlapping).  Note that+backends are supposed to supply 'RegexLike' instances for which the+default 'matchAll' and 'matchAllText' stop searching after returning+any successful but empty match.+++@ RegexContext a b Int @ :+  The number of matches, non-negative.++Two containers for locations of all matches:++@ RegexContext a b (AllMatches [] (MatchOffset, MatchLength)) @++@ RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) @++Two containers for the locations of all matches and their submatches:++@ RegexContext a b [MatchArray] @ :++@ RegexContext a b (AllMatches (Array Int) MatchArray) @++Two containers for the text and locations of all matches and their submatches:++@ RegexContext a b [MatchText b] @++@ RegexContext a b (AllTextMatches (Array Int) (MatchText b)) @++Two containers for text of all matches:+@ RegexContext a b (AllTextMatches [] b) @++@ RegexContext a b (AllTextMatches (Array Int) b) @++Four containers for text of all matches and their submatches:++@ RegexContext a b [[b]] @++@ RegexContext a b (AllTextMatches (Array Int) [b]) @++@ RegexContext a b (AllTextMatches [] (Array Int b)) @++@ RegexContext a b (AllTextMatches (Array Int) (Array Int b)) @++Unused matches are 'empty' (defined via 'Extract')+ -}  module Text.Regex.Base.Context() where +import Control.Monad(liftM) import Data.Array(Array,(!),elems,listArray) import Data.Maybe(maybe) import Text.Regex.Base.RegexLike(RegexLike(..),RegexContext(..)+  ,AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)   ,MatchResult(..),Extract(empty),MatchOffset,MatchLength,MatchArray,MatchText) + {- -- Get the ByteString type for mood/doom import Data.ByteString(ByteString)@@ -141,12 +243,24 @@ {-# INLINE nullArray #-} nullArray = listArray (1,0) [] -nullFail :: (RegexContext regex source [target],Monad m) => regex -> source -> m [target]+nullFail :: (RegexContext regex source (AllMatches [] target),Monad m) => regex -> source -> m (AllMatches [] target) {-# INLINE nullFail #-} nullFail r s = case match r s of-                 [] -> regexFailed+                 (AllMatches []) -> regexFailed                  xs -> return xs +nullFailText :: (RegexContext regex source (AllTextMatches [] target),Monad m) => regex -> source -> m (AllTextMatches [] target)+{-# INLINE nullFailText #-}+nullFailText r s = case match r s of+                     (AllTextMatches []) -> regexFailed+                     xs -> return xs++nullFail' :: (RegexContext regex source ([] target),Monad m) => regex -> source -> m ([] target)+{-# INLINE nullFail' #-}+nullFail' r s = case match r s of+                 ([]) -> regexFailed+                 xs -> return xs+ regexFailed :: (Monad m) => m b {-# INLINE regexFailed #-} regexFailed =  fail $ "regex failed to match"@@ -185,18 +299,21 @@   match r s = maybe (-1,0) (!0) (matchOnce r s)   matchM r s = maybe regexFailed (return.(!0)) (matchOnce r s) -instance (RegexLike a b) => RegexContext a b MatchArray where -  match r s = maybe nullArray id (matchOnce r s)-  matchM r s = maybe regexFailed return (matchOnce r s)+instance (RegexLike a b) => RegexContext a b (MatchResult b) where +  match r s = maybe (MR {mrBefore = s,mrMatch = empty,mrAfter = empty+                        ,mrSubs = nullArray,mrSubList = []}) id (matchM r s)+  matchM = actOn (\(pre,ma,post) -> +     let ((whole,_):subs) = elems ma+     in MR { mrBefore = pre+           , mrMatch = whole+           , mrAfter = post+           , mrSubs = fmap fst ma+           , mrSubList = map fst subs })  instance (RegexLike a b) => RegexContext a b (b,MatchText b,b) where    match r s = maybe (s,nullArray,empty) id (matchOnceText r s)   matchM r s = maybe regexFailed return (matchOnceText r s) -instance (RegexLike a b) => RegexContext a b (Array Int b) where -  match r s = maybe nullArray id (matchM r s)-  matchM = actOn (\(_,ma,_) -> fmap fst ma)- instance (RegexLike a b) => RegexContext a b (b,b,b) where    match r s = maybe (s,empty,empty) id (matchM r s)   matchM = actOn (\(pre,ma,post) -> let ((whole,_):_) = elems ma@@ -207,39 +324,85 @@   matchM = actOn (\(pre,ma,post) -> let ((whole,_):subs) = elems ma                                     in (pre,whole,post,map fst subs)) -instance (RegexLike a b) => RegexContext a b (MatchResult b) where -  match r s = maybe (MR {mrBefore = s,mrMatch = empty,mrAfter = empty-                        ,mrSubs = nullArray,mrSubList = []}) id (matchM r s)-  matchM = actOn (\(pre,ma,post) -> -     let ((whole,_):subs) = elems ma-     in MR { mrBefore = pre-           , mrMatch = whole-           , mrAfter = post-           , mrSubs = fmap fst ma-           , mrSubList = map fst subs })+-- now AllSubmatches wrapper+instance (RegexLike a b) => RegexContext a b MatchArray where +  match r s = maybe nullArray id (matchOnce r s)+  matchM r s = maybe regexFailed return (matchOnce r s)+instance (RegexLike a b) => RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength)) where +  match r s = maybe (AllSubmatches []) id (matchM r s)+  matchM r s = case matchOnce r s of+                 Nothing -> regexFailed+                 Just ma -> return (AllSubmatches (elems ma)) +-- essentially AllSubmatches applied to (MatchText b)+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) where +  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)+  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches ma) r s+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength))) where +  match r s = maybe (AllTextSubmatches []) id (matchM r s)+  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches (elems ma)) r s++instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] b) where +  match r s = maybe (AllTextSubmatches []) id (matchM r s)+  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> map fst . elems $ ma) r s+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) b) where +  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)+  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> fmap fst ma) r s+ -- ** Instances based on matchAll,matchAllText +instance (RegexLike a b) => RegexContext a b (AllMatches [] (MatchOffset,MatchLength)) where+  match r s = AllMatches [ ma!0 | ma <- matchAll r s ]+  matchM r s = nullFail r s+instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) where+  match r s = maybe (AllMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 (AllMatches []) -> regexFailed+                 (AllMatches pairs) -> return . AllMatches . listArray (0,pred $ length pairs) $ pairs++-- No AllMatches wrapper instance (RegexLike a b) => RegexContext a b [MatchArray] where   match = matchAll-  matchM = nullFail+  matchM = nullFail'+instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) MatchArray) where+  match r s = maybe (AllMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 [] -> regexFailed+                 mas -> return . AllMatches . listArray (0,pred $ length mas) $ mas +-- No AllTextMatches wrapper instance (RegexLike a b) => RegexContext a b [MatchText b] where   match = matchAllText-  matchM = nullFail-           -instance (RegexLike a b) => RegexContext a b [(MatchOffset,MatchLength)] where-  match r s = [ ma!0 | ma <- matchAll r s ]-  matchM = nullFail--instance (RegexLike a b) => RegexContext a b [b] where-  match r s = [ fst (ma!0) | ma <- matchAllText r s ]-  matchM = nullFail+  matchM = nullFail'+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (MatchText b)) where+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 ([]) -> regexFailed+                 (mts) -> return . AllTextMatches . listArray (0,pred $ length mts) $ mts -instance (RegexLike a b) => RegexContext a b [Array Int b] where-  match r s = [ fmap fst ma | ma <- matchAllText r s ]-  matchM = nullFail+instance (RegexLike a b) => RegexContext a b (AllTextMatches [] b) where+  match r s = AllTextMatches [ fst (ma!0) | ma <- matchAllText r s ]+  matchM r s = nullFailText r s+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) b) where+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 (AllTextMatches []) -> regexFailed+                 (AllTextMatches bs) -> return . AllTextMatches . listArray (0,pred $ length bs) $ bs +-- No AllTextMatches wrapper instance (RegexLike a b) => RegexContext a b [[b]] where   match r s = [ map fst (elems ma) | ma <- matchAllText r s ]-  matchM = nullFail+  matchM r s = nullFail' r s+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) [b]) where+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 ([]) -> regexFailed+                 (ls) -> return . AllTextMatches . listArray (0,pred $ length ls) $ ls+instance (RegexLike a b) => RegexContext a b (AllTextMatches [] (Array Int b)) where+  match r s = AllTextMatches [ fmap fst ma | ma <- matchAllText r s ]+  matchM r s = nullFailText r s+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (Array Int b)) where+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)+  matchM r s = case match r s of+                 (AllTextMatches []) -> regexFailed+                 (AllTextMatches as) -> return . AllTextMatches . listArray (0,pred $ length as) $ as
Text/Regex/Base/RegexLike.hs view
@@ -36,6 +36,7 @@   RegexLike(..),   RegexContext(..),   Extract(..),+  AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)   ) where  import Control.Monad.Error()@@ -217,3 +218,12 @@  instance Extract (S.Seq a) where   before = S.take; after = S.drop; empty = S.empty++-- | Used in results of RegexContext instances+newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}+-- | Used in results of RegexContext instances+newtype AllTextSubmatches f b = AllTextSubmatches {getAllTextSubmatches :: (f b)}+-- | Used in results of RegexContext instances+newtype AllMatches f b = AllMatches {getAllMatches :: (f b)}+-- | Used in results of RegexContext instances+newtype AllTextMatches f b = AllTextMatches {getAllTextMatches :: (f b) }
regex-base.cabal view
@@ -1,5 +1,5 @@ Name:                   regex-base-Version:                0.83+Version:                0.90 -- Cabal-Version:       >=1.1.4 License:                BSD3 License-File:           LICENSE