pcre-light 0.4.0.4 → 0.4.1.0
raw patch · 4 files changed
+4602/−21 lines, 4 filesdep +HUnitdep +containersdep +mtldep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: HUnit, containers, mtl, pcre-light
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Text.Regex.PCRE.Light: captureNames :: Regex -> [(ByteString, Int)]
+ Text.Regex.PCRE.Light.Char8: captureCount :: Regex -> Int
+ Text.Regex.PCRE.Light.Char8: captureNames :: Regex -> [(String, Int)]
Files
- Text/Regex/PCRE/Light.hs +64/−11
- Text/Regex/PCRE/Light/Char8.hs +20/−6
- pcre-light.cabal +25/−4
- tests/Unit.hs +4493/−0
Text/Regex/PCRE/Light.hs view
@@ -10,7 +10,7 @@ -- Portability: H98 + CPP -- ----------------------------------------------------------------------- +-- -- A simple, portable binding to perl-compatible regular expressions -- (PCRE) via strict ByteStrings. --@@ -24,6 +24,7 @@ , compile, compileM , match , captureCount+ , captureNames -- * Regex types and constructors externally visible @@ -82,6 +83,8 @@ #endif import System.IO.Unsafe (unsafePerformIO)+import Data.List (sortBy)+import Data.Function (on) -- Foreigns import Foreign (newForeignPtr, withForeignPtr)@@ -105,7 +108,7 @@ -- > let r = compile "^(b+|a){1,2}?bc" [] -- -- If the regular expression is invalid, an exception is thrown.--- If this is unsuitable, 'compileM' is availlable, which returns failure +-- If this is unsuitable, 'compileM' is availlable, which returns failure -- in a monad. -- -- To do case insentive matching,@@ -119,7 +122,7 @@ -- -- The arguments are: ----- * 'pat': A ByteString containing the regular expression to be compiled. +-- * 'pat': A ByteString containing the regular expression to be compiled. -- -- * 'flags', optional bit flags. If 'Nothing' is provided, defaults are used. --@@ -267,7 +270,7 @@ match :: Regex -> S.ByteString -> [PCREExecOption] -> Maybe [S.ByteString] match (Regex pcre_fp _) subject os = unsafePerformIO $ do withForeignPtr pcre_fp $ \pcre_ptr -> do- n_capt <- captureCount' pcre_ptr+ n_capt <- fullInfoInt pcre_ptr info_capturecount -- The smallest size for ovector that will allow for n captured -- substrings, in addition to the offsets of the substring@@ -311,7 +314,7 @@ -- pair is used for the first capturing subpattern, and so on. The -- value returned by pcre_exec() is one more than the highest num- bered -- pair that has been set. For example, if two sub- strings have been- -- captured, the returned value is 3. + -- captured, the returned value is 3. where -- The first element of a pair is set to the offset of the first@@ -325,12 +328,62 @@ end = S.unsafeTake (fromIntegral (b-a)) start +-- Wrapper around c_pcre_fullinfo for integer values+fullInfoInt pcre_ptr what =+ alloca $ \n_ptr -> do+ c_pcre_fullinfo pcre_ptr nullPtr what n_ptr+ return . fromIntegral =<< peek (n_ptr :: Ptr CInt)+++-- | 'captureCount'+--+-- Returns the number of captures in a 'Regex'. Correctly ignores non-capturing groups+-- like @(?:abc)@.+--+-- >>> captureCount (compile "(?<one>abc) (def) (?:non-captured) (?<three>ghi)" [])+-- 3 captureCount :: Regex -> Int-captureCount (Regex pcre_fp _) = unsafePerformIO $ do+captureCount (Regex pcre_fp _) = unsafePerformIO $+ withForeignPtr pcre_fp $ \pcre_ptr ->+ fullInfoInt pcre_ptr info_capturecount+++-- | 'captureNames'+--+-- Returns the names and numbers of all named subpatterns in the regular+-- expression. Groups are zero-indexed. Unnamed groups are counted, but don't appear in the+-- result list.+--+-- >>> captureNames (compile "(?<one>abc) (def) (?<three>ghi)")+-- [("one", 0), ("three", 2)]+captureNames :: Regex -> [(S.ByteString, Int)]+captureNames (Regex pcre_fp _) = unsafePerformIO $ withForeignPtr pcre_fp $ \pcre_ptr -> do- captureCount' pcre_ptr+ count <- fullInfoInt pcre_ptr info_namecount+ entrysize <- fullInfoInt pcre_ptr info_nameentrysize -captureCount' pcre_fp =- alloca $ \n_ptr -> do -- (st :: Ptr CInt)- c_pcre_fullinfo pcre_fp nullPtr info_capturecount n_ptr- return . fromIntegral =<< peek (n_ptr :: Ptr CInt)+ buf <- alloca $ \n_ptr -> do+ c_pcre_fullinfo pcre_ptr nullPtr info_nametable n_ptr+ buf <- peek n_ptr+ S.packCStringLen (buf, count*entrysize)++ let results = split entrysize buf+ zeroIndexed = fmap (subtract 1) <$> results+ sorted = sortBy (compare `on` snd) zeroIndexed+ return sorted++ where+ -- Split the nametable buffer into entries. Each entry has a fixed size in+ -- bytes. The first two bytes in each entry store the pattern number in+ -- big-endian format, the bytes following that contain the nul-terminated+ -- name of the subpattern.+ split :: Int -> S.ByteString -> [(S.ByteString, Int)]+ split entrysize buf+ | S.null buf = []+ | otherwise =+ let+ (entry, tail) = S.splitAt entrysize buf+ idx = fromIntegral . S.index entry+ num = idx 0 * 256 + idx 1+ name = S.takeWhile (/= 0) $ S.drop 2 entry+ in (name, num) : split entrysize tail
Text/Regex/PCRE/Light/Char8.hs view
@@ -9,7 +9,7 @@ -- Portability: H98 + FFI -- ----------------------------------------------------------------------- +-- -- A simple, portable binding to perl-compatible regular expressions -- (PCRE) via 8-bit latin1 Strings. --@@ -22,6 +22,8 @@ -- * String interface , compile, compileM , match+ , S.captureCount+ , captureNames -- * Regex types and constructors externally visible @@ -69,7 +71,7 @@ import qualified Data.ByteString.Char8 as S import qualified Text.Regex.PCRE.Light as S-import Text.Regex.PCRE.Light hiding (match, compile, compileM)+import Text.Regex.PCRE.Light hiding (match, compile, compileM, captureNames) -- | 'compile' --@@ -77,7 +79,7 @@ -- The arguments are: -- -- * 'pat': A ByteString, which may or may not be zero-terminated,--- containing the regular expression to be compiled. +-- containing the regular expression to be compiled. -- -- * 'flags', optional bit flags. If 'Nothing' is provided, defaults are used. --@@ -125,15 +127,15 @@ -- -- * 'no_utf8_check' - Do not check the pattern for UTF-8 validity ----- If compilation of the pattern fails, the 'Left' constructor is +-- If compilation of the pattern fails, the 'Left' constructor is -- returned with the error string. Otherwise an abstract type -- representing the compiled regular expression is returned. -- The regex is allocated via malloc on the C side, and will be -- deallocated by the runtime when the Haskell value representing it -- goes out of scope. ----- As regexes are often defined statically, GHC will compile them --- to null-terminated, strict C strings, enabling compilation of the +-- As regexes are often defined statically, GHC will compile them+-- to null-terminated, strict C strings, enabling compilation of the -- pattern without copying. This may be useful for very large patterns. -- -- See man pcreapi for more details.@@ -203,3 +205,15 @@ Nothing -> Nothing Just x -> Just (map S.unpack x) {-# INLINE match #-}+++-- | 'captureNames'+--+-- Returns the names and numbers of all named subpatterns in the regular+-- expression. Groups are zero-indexed. Unnamed groups are counted, but don't appear in the+-- result list.+--+-- >>> captureNames (compile "(?<one>abc) (def) (?<three>ghi)")+-- [("one", 0), ("three", 2)]+captureNames :: Regex -> [(String, Int)]+captureNames r = map (\(n,i) -> (S.unpack n, i)) $ S.captureNames r
pcre-light.cabal view
@@ -1,5 +1,5 @@ name: pcre-light-version: 0.4.0.4+version: 0.4.1.0 homepage: https://github.com/Daniel-Diaz/pcre-light synopsis: Portable regex library for Perl 5 compatible regular expressions description:@@ -9,7 +9,7 @@ expression pattern matching using the same syntax and semantics as Perl 5. . If installation fails reporting that you are missing the prce C library, try installing- the @libpcre3-dev@ package (linux).+ the @libpcre3-dev@ package (linux) or @brew install pcre@ (MacOS). . category: Text license: BSD3@@ -17,7 +17,7 @@ copyright: (c) 2007-2010. Don Stewart <dons@galois.com> author: Don Stewart maintainer: Daniel Díaz <dhelta.diaz@gmail.com>-cabal-version: >= 1.2.0+cabal-version: >= 1.8.0 build-type: Simple tested-with: GHC == 7.8.3 extra-source-files: README.md@@ -26,6 +26,10 @@ description: Build with an old version of base (< 3) default: False +flag use-pkg-config+ default: False+ manual: True+ library exposed-modules: Text.Regex.PCRE.Light Text.Regex.PCRE.Light.Char8@@ -38,5 +42,22 @@ else build-depends: base >= 3 && <= 5, bytestring >= 0.9 - pkgconfig-depends: libpcre+ if flag(use-pkg-config)+ pkgconfig-depends: libpcre+ else+ extra-Libraries: pcre +test-suite unit+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: Unit.hs+ if flag(old_base)+ build-depends: base < 3+ else+ build-depends: + base >= 3 && <= 5+ , bytestring >= 0.9+ , containers >= 0.5.5.1+ , HUnit >= 1.2.5.2+ , mtl >= 2.1.3.2+ , pcre-light
+ tests/Unit.hs view
@@ -0,0 +1,4493 @@+{-# LANGUAGE OverloadedStrings #-}++import Text.Regex.PCRE.Light (compile,compileM,match,captureNames,captureCount)+import qualified Text.Regex.PCRE.Light.Char8 as String (compile,compileM,match)+import Text.Regex.PCRE.Light.Base++import qualified Data.ByteString.Char8 as S+import System.IO++import Test.HUnit+import System.Exit (exitFailure)+import Control.Monad (when)+import System.IO+import Data.Either+import qualified Data.Map as M++import System.IO.Unsafe+import Control.Exception+import Control.Monad.Except++assertBool' :: S.ByteString -> Bool -> Assertion+assertBool' s = assertBool (S.unpack s)++assertEqual' :: (Eq a, Show a) => S.ByteString -> a -> a -> Assertion+assertEqual' s = assertEqual (S.unpack s)++testLabel :: S.ByteString -> Test -> Test+testLabel s = TestLabel (S.unpack s)++testRegex :: S.ByteString+ -> [PCREOption]+ -> [S.ByteString]+ -> [Maybe [S.ByteString]]+ -> Test++testRegex regex options inputs outputs = testLabel regex $+ TestCase $ do+ assertEqual' "Input/Output Length Check" (length inputs) (length outputs)++ assertBool' "ByteString regex compile" =<<+ case compile regex options of+ r -> return $+ and [ match r i [] == o+ | (i,o) <- zip inputs outputs ]++ assertBool' "ByteString regex compileM" =<<+ case compileM regex options of+ Left s -> do S.hPutStrLn stderr ("ERROR in ByteString in compileM " `S.append` (S.pack s))+ return False+ Right r -> return $+ and [ match r i [] == o+ | (i,o) <- zip inputs outputs ]++ assertBool' "String regex" =<<+ case String.compile (S.unpack regex) options of+ r -> return $+ and [ String.match r i [] == o+ | (i,o) <- zip (map (S.unpack) inputs)+ (map (fmap (map S.unpack)) outputs) ]++ assertBool' "String regex" =<<+ case String.compileM (S.unpack regex) options of+ Left s -> do S.hPutStrLn stderr ("ERROR in String compileM: " `S.append` (S.pack s))+ return False+ Right r -> return $+ and [ String.match r i [] == o+ | (i,o) <- zip (map (S.unpack) inputs)+ (map (fmap (map S.unpack)) outputs) ]++testCaptures :: Int+ -> S.ByteString+ -> [(S.ByteString, Int)]+ -> Test+testCaptures expectedTotalCaptures regex expectedCaptureNames = testLabel regex $+ TestCase $ do+ r <- case compileM regex [] of+ Left s -> assertFailure ("ERROR in ByteString in compileM " ++ s)+ Right r -> return r+ assertEqual' "Capture group name mismatch" expectedCaptureNames (captureNames r)+ assertEqual' "Capture count mismatch" expectedTotalCaptures (captureCount r)++main :: IO ()+main = do counts <- runTestTT tests+ when (errors counts > 0 || failures counts > 0) exitFailure++tests :: Test+tests = TestList++ [ testRegex "the quick brown fox" []+ [ "the quick brown fox"+ , "The quick brown FOX"+ , "What do you know about the quick brown fox?"+ , "What do you know about THE QUICK BROWN FOX?"+ ]+ [ Just ["the quick brown fox"]+ , Nothing+ , Just ["the quick brown fox"]+ , Nothing+ ]++ , testLabel "compile failure" $+ TestCase $ (assertBool' "compile failure" $+ Left ("nothing to repeat" ) == compileM "*" [])++ , testLabel "compile failure" $+ TestCase $ (assertEqual' "compile failure"+ (Just ("Text.Regex.PCRE.Light: Error in regex: nothing to repeat"))+ (fmap (head . S.lines) . unsafePerformIO $ do+ handle (\e -> return (Just (S.pack $ displayException (e :: SomeException))))+ (compile "*" [] `seq` return Nothing)))++-- , testRegex "\0*" [] -- the embedded null in the pattern seems to be a problem+-- ["\0\0\0\0"]+-- [Just ["\0\0\0\0"]]++ , testRegex "\1*" [] -- the embedded null in the pattern seems to be a problem+ ["\1\1\1\1"]+ [Just ["\1\1\1\1"]]++ , testRegex "The quick brown fox" [caseless]+ ["the quick brown fox"+ ,"The quick brown FOX"+ ,"What do you know about the quick brown fox?"+ ,"What do you know about THE QUICK BROWN FOX?"+ ]+ [ Just ["the quick brown fox"]+ , Just ["The quick brown FOX"]+ , Just ["the quick brown fox"]+ , Just ["THE QUICK BROWN FOX"]+ ]++ , testRegex "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" []+ ["abxyzpqrrrabbxyyyypqAzz"+ ,"abxyzpqrrrabbxyyyypqAzz"+ ,"aabxyzpqrrrabbxyyyypqAzz"+ ,"aaabxyzpqrrrabbxyyyypqAzz"+ ,"aaaabxyzpqrrrabbxyyyypqAzz"+ ,"abcxyzpqrrrabbxyyyypqAzz"+ ,"aabcxyzpqrrrabbxyyyypqAzz"+ ,"aaabcxyzpqrrrabbxyyyypAzz"+ ,"aaabcxyzpqrrrabbxyyyypqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqqqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqqqqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqqqqqAzz"+ ,"aaaabcxyzpqrrrabbxyyyypqAzz"+ ,"abxyzzpqrrrabbxyyyypqAzz"+ ,"aabxyzzzpqrrrabbxyyyypqAzz"+ ,"aaabxyzzzzpqrrrabbxyyyypqAzz"+ ,"aaaabxyzzzzpqrrrabbxyyyypqAzz"+ ,"abcxyzzpqrrrabbxyyyypqAzz"+ ,"aabcxyzzzpqrrrabbxyyyypqAzz"+ ,"aaabcxyzzzzpqrrrabbxyyyypqAzz"+ ,"aaaabcxyzzzzpqrrrabbxyyyypqAzz"+ ,"aaaabcxyzzzzpqrrrabbbxyyyypqAzz"+ ,"aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"+ ,"aaabcxyzpqrrrabbxyyyypABzz"+ ,"aaabcxyzpqrrrabbxyyyypABBzz"+ ,">>>aaabxyzpqrrrabbxyyyypqAzz"+ ,">aaaabxyzpqrrrabbxyyyypqAzz"+ ,">>>>abcxyzpqrrrabbxyyyypqAzz"+ ,"abxyzpqrrabbxyyyypqAzz"+ ,"abxyzpqrrrrabbxyyyypqAzz"+ ,"abxyzpqrrrabxyyyypqAzz"+ ,"aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz"+ ,"aaaabcxyzzzzpqrrrabbbxyyypqAzz"+ ,"aaabcxyzpqrrrabbxyyyypqqqqqqqAzz"+ ]++ [ Just ["abxyzpqrrrabbxyyyypqAzz"]+ , Just ["abxyzpqrrrabbxyyyypqAzz"]+ , Just ["aabxyzpqrrrabbxyyyypqAzz"]+ , Just ["aaabxyzpqrrrabbxyyyypqAzz"]+ , Just ["aaaabxyzpqrrrabbxyyyypqAzz"]+ , Just ["abcxyzpqrrrabbxyyyypqAzz"]+ , Just ["aabcxyzpqrrrabbxyyyypqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqqqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqqqqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqqqqqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypqqqqqqAzz"]+ , Just ["aaaabcxyzpqrrrabbxyyyypqAzz"]+ , Just ["abxyzzpqrrrabbxyyyypqAzz"]+ , Just ["aabxyzzzpqrrrabbxyyyypqAzz"]+ , Just ["aaabxyzzzzpqrrrabbxyyyypqAzz"]+ , Just ["aaaabxyzzzzpqrrrabbxyyyypqAzz"]+ , Just ["abcxyzzpqrrrabbxyyyypqAzz"]+ , Just ["aabcxyzzzpqrrrabbxyyyypqAzz"]+ , Just ["aaabcxyzzzzpqrrrabbxyyyypqAzz"]+ , Just ["aaaabcxyzzzzpqrrrabbxyyyypqAzz"]+ , Just ["aaaabcxyzzzzpqrrrabbbxyyyypqAzz"]+ , Just ["aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypABzz"]+ , Just ["aaabcxyzpqrrrabbxyyyypABBzz"]+ , Just ["aaabxyzpqrrrabbxyyyypqAzz"]+ , Just ["aaaabxyzpqrrrabbxyyyypqAzz"]+ , Just ["abcxyzpqrrrabbxyyyypqAzz"]+ , Nothing+ , Nothing+ , Nothing+ , Nothing+ , Nothing+ , Nothing+ ]++ , testRegex "^(abc){1,2}zz" []+ ["abczz"+ ,"abcabczz"+ ,"zz"+ ,"abcabcabczz"+ ,">>abczz"]+ [ Just ["abczz","abc"]+ , Just ["abcabczz", "abc"]+ , Nothing+ , Nothing+ , Nothing ]++ , testRegex "^(b+?|a){1,2}?c" []+ ["bc",+ "bbc",+ "bbbc",+ "bac",+ "bbac",+ "aac",+ "abbbbbbbbbbbc",+ "bbbbbbbbbbbac",+ "aaac",+ "abbbbbbbbbbbac"]++ [Just ["bc", "b"],+ Just ["bbc", "b"],+ Just ["bbbc", "bb"],+ Just ["bac", "a"],+ Just ["bbac", "a"],+ Just ["aac", "a"],+ Just ["abbbbbbbbbbbc", "bbbbbbbbbbb"],+ Just ["bbbbbbbbbbbac", "a"],+ Nothing,+ Nothing]++ , testRegex "^(b+|a){1,2}c" []+ ["bc",+ "bbc",+ "bbbc",+ "bac",+ "bbac",+ "aac",+ "abbbbbbbbbbbc",+ "bbbbbbbbbbbac",+ "aaac",+ "abbbbbbbbbbbac"]+ [Just ["bc", "b"],+ Just ["bbc", "bb"],+ Just ["bbbc", "bbb"],+ Just ["bac", "a"],+ Just ["bbac", "a"],+ Just ["aac", "a"],+ Just ["abbbbbbbbbbbc", "bbbbbbbbbbb"],+ Just ["bbbbbbbbbbbac", "a"],+ Nothing,+ Nothing]++ , testRegex "^(b+|a){1,2}?bc" []+ ["bbc"]+ [Just ["bbc", "b"]]++ , testRegex "^(b*|ba){1,2}?bc" []+ ["babc",+ "bbabc",+ "bababc",+ "bababbc",+ "babababc"]+ [Just ["babc","ba"],+ Just ["bbabc","ba"],+ Just ["bababc","ba"],+ Nothing,+ Nothing]++ , testRegex "^(ba|b*){1,2}?bc" []+ ["babc",+ "bbabc",+ "bababc",+ "bababbc",+ "babababc"]+ [Just ["babc","ba"],+ Just ["bbabc","ba"],+ Just ["bababc","ba"],+ Nothing,+ Nothing]++ , testRegex "^[ab\\]cde]" []+ ["athing",+ "bthing",+ "]thing",+ "cthing",+ "dthing",+ "ething",+ "fthing",+ "[thing",+ "\\\\thing"]+ [Just ["a"],+ Just ["b"],+ Just ["]"],+ Just ["c"],+ Just ["d"],+ Just ["e"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^[]cde]" []+ ["]thing",+ "cthing",+ "dthing",+ "ething",+ "athing",+ "fthing"]+ [Just ["]"],+ Just ["c"],+ Just ["d"],+ Just ["e"],+ Nothing,+ Nothing]++ , testRegex "^[^ab\\]cde]" []+ ["fthing",+ "[thing",+ "\\\\thing",+ "athing",+ "bthing",+ "]thing",+ "cthing",+ "dthing",+ "ething"]+ [Just ["f"],+ Just ["["],+ Just ["\\"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^\129" []+ ["\129"]+ [Just ["\x81"]]++ , testRegex "^\255" []+ ["\255"]+ [Just ["\xff"]]++ , testRegex "^[0-9]+$" []+ ["0",+ "1",+ "2",+ "3",+ "4",+ "5",+ "6",+ "7",+ "8",+ "9",+ "10",+ "100",+ "abc"]+ [Just ["0"],+ Just ["1"],+ Just ["2"],+ Just ["3"],+ Just ["4"],+ Just ["5"],+ Just ["6"],+ Just ["7"],+ Just ["8"],+ Just ["9"],+ Just ["10"],+ Just ["100"],+ Nothing]++ , testRegex "^.*nter" []+ ["enter",+ "inter",+ "uponter"]+ [Just ["enter"],+ Just ["inter"],+ Just ["uponter"]]++ , testRegex "^xxx[0-9]+$" []+ ["xxx0",+ "xxx1234",+ "xxx"]+ [Just ["xxx0"],+ Just ["xxx1234"],+ Nothing]++ , testRegex "^.+[0-9][0-9][0-9]$" []+ ["x123",+ "xx123",+ "123456",+ "123",+ "x1234"]+ [Just ["x123"],+ Just ["xx123"],+ Just ["123456"],+ Nothing,+ Just ["x1234"]]++ , testRegex "^.+?[0-9][0-9][0-9]$" []+ ["x123",+ "xx123",+ "123456",+ "123",+ "x1234"]+ [Just ["x123"],+ Just ["xx123"],+ Just ["123456"],+ Nothing,+ Just ["x1234"]]++ -- test matching more than 1 subpattern+ , testRegex "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" []+ ["abc!pqr=apquxz.ixr.zzz.ac.uk",+ "!pqr=apquxz.ixr.zzz.ac.uk",+ "abc!=apquxz.ixr.zzz.ac.uk",+ "abc!pqr=apquxz:ixr.zzz.ac.uk",+ "abc!pqr=apquxz.ixr.zzz.ac.ukk"]+ [Just ["abc!pqr=apquxz.ixr.zzz.ac.uk", "abc", "pqr"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex ":" []+ ["Well, we need a colon: somewhere",+ "*** Fail if we don't"]+ [Just [":"],+ Nothing]++ , testRegex "([\\da-f:]+)$" [caseless]+ ["0abc",+ "abc",+ "fed",+ "E",+ "::",+ "5f03:12C0::932e",+ "fed def",+ "Any old stuff",+ "*** Failers",+ "0zzz",+ "gzzz",+ "fed\x20",+ "Any old rubbish"]+ [Just ["0abc", "0abc"],+ Just ["abc", "abc"],+ Just ["fed", "fed"],+ Just ["E", "E"],+ Just ["::", "::"],+ Just ["5f03:12C0::932e", "5f03:12C0::932e"],+ Just ["def", "def"],+ Just ["ff", "ff"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" []+ [".1.2.3",+ "A.12.123.0",+ ".1.2.3333",+ "1.2.3",+ "1234.2.3"]+ [Just [".1.2.3", "1", "2", "3"],+ Just ["A.12.123.0", "12", "123", "0"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$" []+ ["1 IN SOA non-sp1 non-sp2(",+ "1 IN SOA non-sp1 non-sp2 (",+ "1IN SOA non-sp1 non-sp2("]+ [Just ["1 IN SOA non-sp1 non-sp2(", "1", "non-sp1", "non-sp2"],+ Just ["1 IN SOA non-sp1 non-sp2 (", "1", "non-sp1", "non-sp2"],+ Nothing]++ , testRegex "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" []+ ["a.",+ "Z.",+ "2.",+ "ab-c.pq-r.",+ "sxk.zzz.ac.uk.",+ "x-.y-.",+ "*** Failers",+ "-abc.peq."]+ [Just ["a."],+ Just ["Z."],+ Just ["2."],+ Just ["ab-c.pq-r.", ".pq-r"],+ Just ["sxk.zzz.ac.uk.", ".uk"],+ Just ["x-.y-.", ".y-"],+ Nothing,+ Nothing]++ , testRegex "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" []+ ["*.a",+ "*.b0-a",+ "*.c3-b.c",+ "*.c-a.b-c",+ "*** Failers",+ "*.0",+ "*.a-",+ "*.a-b.c-",+ "*.c-a.0-c"]+ [Just ["*.a"],+ Just ["*.b0-a", "0-a"],+ Just ["*.c3-b.c", "3-b", ".c"],+ Just ["*.c-a.b-c", "-a", ".b-c", "-c"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^(?=ab(de))(abd)(e)" []+ ["abde"]+ [Just ["abde", "de", "abd", "e"]]++ , testRegex "^(?!(ab)de|x)(abd)(f)" []+ ["abdf"]+ [Just ["abdf", "", "abd", "f"]]++ , testRegex "^(?=(ab(cd)))(ab)" []+ ["abcd"]+ [Just ["ab", "abcd", "cd", "ab"]]++ , testRegex "^[\\da-f](\\.[\\da-f])*$" [caseless]+ ["a.b.c.d",+ "A.B.C.D",+ "a.b.c.1.2.3.C"]+ [Just ["a.b.c.d", ".d"],+ Just ["A.B.C.D", ".D"],+ Just ["a.b.c.1.2.3.C", ".C"]]++ , testRegex "^\".*\"\\s*(;.*)?$" []+ ["\"1234\"",+ "\"abcd\" ;",+ "\"\" ; rhubarb",+ "*** Failers",+ "\\\"1234\\\" : things"]+ [Just ["\"1234\""],+ Just ["\"abcd\" ;", ";"],+ Just ["\"\" ; rhubarb", "; rhubarb"],+ Nothing,+ Nothing]++ , testRegex "^$" []+ ["",+ "*** Failers"]+ [Just [""],+ Nothing]++ , testRegex " ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" [extended]+ ["ab c",+ "*** Failers",+ "abc",+ "ab cde"]+ [Just ["ab c"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" []+ ["ab c",+ "*** Failers",+ "abc",+ "ab cde"]+ [Just ["ab c"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^ a\\ b[c ]d $" [extended]+ ["a bcd",+ "a b d",+ "*** Failers",+ "abcd",+ "ab d"]+ [Just ["a bcd"],+ Just ["a b d"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$" []+ ["abcdefhijklm"]+ [Just ["abcdefhijklm",+ "abc", "bc",+ "c", "def",+ "ef", "f",+ "hij", "ij",+ "j", "klm",+ "lm", "m"]]++ , testRegex "^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$" []+ ["abcdefhijklm"]+ [Just ["abcdefhijklm",+ "bc", "c", "ef", "f", "ij", "j", "lm", "m"]]++ , testRegex "^[.^$|()*+?{,}]+" []+ [".^$(*+)|{?,?}"]+ [Just [".^$(*+)|{?,?}"]]++ , testRegex "^a*\\w" []+ ["z",+ "az",+ "aaaz",+ "a",+ "aa",+ "aaaa",+ "a+",+ "aa+"]+ [Just ["z"],+ Just ["az"],+ Just ["aaaz"],+ Just ["a"],+ Just ["aa"],+ Just ["aaaa"],+ Just ["a"],+ Just ["aa"]]++ , testRegex "^a*?\\w" []+ ["z",+ "az",+ "aaaz",+ "a",+ "aa",+ "aaaa",+ "a+",+ "aa+"]+ [Just ["z"],+ Just ["a"],+ Just ["a"],+ Just ["a"],+ Just ["a"],+ Just ["a"],+ Just ["a"],+ Just ["a"]]++ , testRegex "^a+\\w" []+ ["az",+ "aaaz",+ "aa",+ "aaaa",+ "aa+"]+ [Just ["az"],+ Just ["aaaz"],+ Just ["aa"],+ Just ["aaaa"],+ Just ["aa"]]++ , testRegex "^a+?\\w" []+ ["az",+ "aaaz",+ "aa",+ "aaaa",+ "aa+"]+ [Just ["az"],+ Just ["aa"],+ Just ["aa"],+ Just ["aa"],+ Just ["aa"]]++ , testRegex "^\\d{8}\\w{2,}" []+ ["1234567890",+ "12345678ab",+ "12345678__",+ "*** Failers",+ "1234567"]+ [Just ["1234567890"],+ Just ["12345678ab"],+ Just ["12345678__"],+ Nothing,+ Nothing]++ , testRegex "^[aeiou\\d]{4,5}$" []+ ["uoie",+ "1234",+ "12345",+ "aaaaa",+ "*** Failers",+ "123456"]+ [Just ["uoie"],+ Just ["1234"],+ Just ["12345"],+ Just ["aaaaa"],+ Nothing,+ Nothing]++ , testRegex "^[aeiou\\d]{4,5}?" []+ ["uoie",+ "1234",+ "12345",+ "aaaaa",+ "123456"]+ [Just ["uoie"],+ Just ["1234"],+ Just ["1234"],+ Just ["aaaa"],+ Just ["1234"]]++ , testRegex "\\A(abc|def)=(\\1){2,3}\\Z" []+ ["abc=abcabc",+ "def=defdefdef",+ "*** Failers",+ "abc=defdef"]+ [Just ["abc=abcabc", "abc", "abc"],+ Just ["def=defdefdef", "def", "def"],+ Nothing,+ Nothing]++ , testRegex "^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$" []+ ["abcdefghijkcda2",+ "abcdefghijkkkkcda2"]+ [Just ["abcdefghijkcda2", "a", "b",+ "c", "d", "e", "f", "g", "h", "i", "j", "k", "cd"],++ Just ["abcdefghijkkkkcda2", "a", "b", "c", "d",+ "e", "f", "g", "h", "i", "j", "k", "cd"]]++ , testRegex "(cat(a(ract|tonic)|erpillar)) \\1()2(3)" []+ ["cataract cataract23",+ "catatonic catatonic23",+ "caterpillar caterpillar23"]++ [Just ["cataract cataract23", "cataract", "aract", "ract", "", "3"],++ Just ["catatonic catatonic23", "catatonic", "atonic", "tonic", "", "3"],++ Just ["caterpillar caterpillar23", "caterpillar", "erpillar", "", "", "3"]]++ , testRegex "^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]" []+ ["From abcd Mon Sep 01 12:33:02 1997"]+ [Just ["From abcd Mon Sep 01 12:33", "abcd"]]++ , testRegex "^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d" []+ ["From abcd Mon Sep 01 12:33:02 1997",+ "From abcd Mon Sep 1 12:33:02 1997",+ "*** Failers",+ "From abcd Sep 01 12:33:02 1997"]+ [Just ["From abcd Mon Sep 01 12:33", "Sep "],+ Just ["From abcd Mon Sep 1 12:33", "Sep "],+ Nothing,+ Nothing]++ , testRegex "\\w+(?=\t)" []+ ["the quick brown\t fox"]+ [Just ["brown"]]++ , testRegex "foo(?!bar)(.*)" []+ ["foobar is foolish see?"]+ [Just ["foolish see?", "lish see?"]]++ , testRegex "(?:(?!foo)...|^.{0,2})bar(.*)" []+ ["foobar crowbar etc",+ "barrel",+ "2barrel",+ "A barrel"]+ [Just ["rowbar etc", " etc"],+ Just ["barrel", "rel"],+ Just ["2barrel", "rel"],+ Just ["A barrel", "rel"]]++ , testRegex "^(\\D*)(?=\\d)(?!123)" []+ ["abc456",+ "*** Failers",+ "abc123"]+ [Just ["abc", "abc"],+ Nothing,+ Nothing]++ , testRegex "^(a)\\1{2,3}(.)" []+ ["aaab",+ "aaaab",+ "aaaaab",+ "aaaaaab"]+ [Just ["aaab", "a","b"],+ Just ["aaaab","a","b"],+ Just ["aaaaa","a","a"],+ Just ["aaaaa","a","a"]]++ , testRegex "(?!^)abc" []+ ["the abc",+ "*** Failers",+ "abc"]+ [Just ["abc"],+ Nothing,+ Nothing]++ , testRegex "(?=^)abc" []+ ["abc",+ "*** Failers",+ "the abc"]+ [Just ["abc"],+ Nothing,+ Nothing]++ , testRegex "^[ab]{1,3}(ab*|b)" []+ ["aabbbbb"]+ [Just ["aabb", "b"]]++ , testRegex "^[ab]{1,3}?(ab*|b)" []+ ["aabbbbb"]+ [Just ["aabbbbb", "abbbbb"]]++ , testRegex "^[ab]{1,3}?(ab*?|b)" []+ ["aabbbbb"]+ [Just ["aa", "a"]]++ , testRegex "^[ab]{1,3}(ab*?|b)" []+ ["aabbbbb"]+ [Just ["aabb", "b"]]++ , testRegex "^(cow|)\\1(bell)" []+ ["cowcowbell",+ "bell",+ "*** Failers",+ "cowbell"]+ [Just ["cowcowbell", "cow", "bell"],+ Just ["bell", "", "bell"],+ Nothing,+ Nothing]++ , testRegex "^\\s" []+ ["\o40abc",+ "\nabc",+ "\rabc",+ "\tabc",+ "abc"]+ [Just [" "],+ Just ["\x0a"],+ Just ["\x0d"],+ Just ["\x09"],+ Nothing]++ , testRegex "^(a|)\\1*b" []+ ["ab",+ "aaaab",+ "b",+ "acb"]+ [Just ["ab", "a"],+ Just ["aaaab", "a"],+ Just ["b", ""],+ Nothing]++ , testRegex "^(a|)\\1+b" []+ ["aab",+ "aaaab",+ "b",+ "*** Failers",+ "ab"]+ [Just ["aab", "a"],+ Just ["aaaab", "a"],+ Just ["b", ""],+ Nothing,+ Nothing]++ , testRegex "^(a|)\\1?b" []+ ["ab",+ "aab",+ "b",+ "acb"]+ [Just ["ab", "a"],+ Just ["aab", "a"],+ Just ["b", ""],+ Nothing]++ , testRegex "^(a|)\\1{2}b" []+ ["aaab",+ "b",+ "ab",+ "aab",+ "aaaab"]+ [Just ["aaab", "a"],+ Just ["b", ""],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^(a|)\\1{2,3}b" []+ ["aaab",+ "aaaab",+ "b",+ "ab",+ "aab",+ "aaaaab"]+ [Just ["aaab", "a"],+ Just ["aaaab", "a"],+ Just ["b", ""],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "ab{1,3}bc" []+ ["abbbbc",+ "abbbc",+ "abbc",+ "abc",+ "abbbbbc"]+ [Just ["abbbbc"],+ Just ["abbbc"],+ Just ["abbc"],+ Nothing,+ Nothing]++ , testRegex "([^.]*)\\.([^:]*):[T ]+(.*)" []+ ["track1.title:TBlah blah blah"]+ [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]++ , testRegex "([^.]*)\\.([^:]*):[T ]+(.*)" [caseless]+ ["track1.title:TBlah blah blah"]+ [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]++ , testRegex "([^.]*)\\.([^:]*):[t ]+(.*)" [caseless]+ ["track1.title:TBlah blah blah"]+ [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]++ , testRegex "^[W-c]+$" []+ ["WXY_^abc",+ "wxy"]+ [Just ["WXY_^abc"],+ Nothing]++ , testRegex "^[W-c]+$" [caseless]+ ["WXY_^abc",+ "wxy_^ABC"]+ [Just ["WXY_^abc"],+ Just ["wxy_^ABC"]]++ , testRegex "^[\\x3f-\\x5F]+$" [caseless]+ ["WXY_^abc",+ "wxy_^ABC"]+ [Just ["WXY_^abc"],+ Just ["wxy_^ABC"]]++ , testRegex "^abc$" []+ ["abc",+ "qqq\\nabc",+ "abc\\nzzz",+ "qqq\\nabc\\nzzz"]+ [Just ["abc"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "(?:b)|(?::+)" []+ ["b::c",+ "c::b"]+ [Just ["b"],+ Just ["::"]]++ , testRegex "[-az]+" []+ ["az-",+ "*** Failers",+ "b"]+ [Just ["az-"],+ Just ["a"],+ Nothing]++ , testRegex "[az-]+" []+ ["za-",+ "*** Failers",+ "b"]+ [Just ["za-"],+ Just ["a"],+ Nothing]++ , testRegex "[a\\-z]+" []+ ["a-z",+ "*** Failers",+ "b"]+ [Just ["a-z"],+ Just ["a"],+ Nothing]++ , testRegex "[a-z]+" []+ ["abcdxyz"]+ [Just ["abcdxyz"]]++ , testRegex "[\\d-]+" []+ ["12-34",+ "aaa"]+ [Just ["12-34"],+ Nothing]+ , testRegex "[\\d-z]+" []+ ["12-34z",+ "aaa"]+ [Just ["12-34z"],+ Nothing]++ , testRegex "\\x20Z" []+ ["the Zoo",+ "*** Failers",+ "Zulu"]+ [Just [" Z"],+ Nothing,+ Nothing]++ , testRegex "(abc)\\1" [caseless]+ ["abcabc",+ "ABCabc",+ "abcABC"]+ [Just ["abcabc", "abc"],+ Just ["ABCabc", "ABC"],+ Just ["abcABC", "abc"]]++ , testRegex "ab{3cd" []+ ["ab{3cd"]+ [Just ["ab{3cd"]]++ , testRegex "ab{3,cd" []+ ["ab{3,cd"]+ [Just ["ab{3,cd"]]++ , testRegex "ab{3,4a}cd" []+ ["ab{3,4a}cd"]+ [Just ["ab{3,4a}cd"]]++ , testRegex "{4,5a}bc" []+ ["{4,5a}bc"]+ [Just ["{4,5a}bc"]]++ , testRegex "abc$" []+ ["abc",+ "abc\n",+ "*** Failers",+ "abc\ndef"]+ [Just ["abc"],+ Just ["abc"],+ Nothing,+ Nothing]++ , testRegex "(abc)\\123" []+ ["abc\x53"]+ [Just ["abcS", "abc"]]++ , testRegex "(abc)\\223" []+ ["abc\x93"]+ [Just ["abc\x93", "abc"]]++ , testRegex "(abc)\\323" []+ ["abc\xd3"]+ [Just ["abc\xd3", "abc"]]++ , testRegex "(abc)\\100" []+ ["abc\x40",+ "abc\o100"]+ [Just ["abc@", "abc"],+ Just ["abc@", "abc"]]++ , testRegex "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\12\\123" []+ ["abcdefghijkllS"]+ [Just ["abcdefghijkllS",+ "a",+ "b",+ "c",+ "d",+ "e",+ "f",+ "g",+ "h",+ "i",+ "j",+ "k",+ "l"]]++ , testRegex "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\12\\123" []+ ["abcdefghijk\o12S"]+ [Just ["abcdefghijk\x0aS",+ "a",+ "b",+ "c",+ "d",+ "e",+ "f",+ "g",+ "h",+ "i",+ "j",+ "k"]]++ , testRegex "ab\\idef" []+ ["abidef"]+ [Just ["abidef"]]++ , testRegex "a{0}bc" []+ ["bc"]+ [Just ["bc"]]++ , testRegex "(a|(bc)){0,0}?xyz" []+ ["xyz"]+ [Just ["xyz"]]++ , testRegex "(?s)a.b" []+ ["a\nb"]+ [Just ["a\nb"]]++ , testRegex "^([^a])([^\\b])([^c]*)([^d]{3,4})" []+ ["baNOTccccd",+ "baNOTcccd",+ "baNOTccd",+ "bacccd",+ "anything",+ "b\bc ",+ "baccd"]+ [Just ["baNOTcccc", "b", "a", "NOT", "cccc"],+ Just ["baNOTccc", "b", "a", "NOT", "ccc"],+ Just ["baNOTcc", "b", "a", "NO", "Tcc"],+ Just ["baccc", "b", "a", "", "ccc"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "^\\d{8,}\\@.+[^k]$" []+ ["12345678@a.b.c.d",+ "123456789@x.y.z",+ "*** Failers",+ "12345678@x.y.uk",+ "1234567@a.b.c.d "]+ [Just ["12345678@a.b.c.d"],+ Just ["123456789@x.y.z"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "(a)\\1{8,}" []+ ["aaaaaaaaa",+ "aaaaaaaaaa",+ "*** Failers",+ "aaaaaaa "]+ [Just ["aaaaaaaaa", "a"],+ Just ["aaaaaaaaaa", "a"],+ Nothing,+ Nothing]++ , testRegex "[^a]" []+ ["aaaabcd",+ "aaAabcd "]+ [Just ["b"],+ Just ["A"]]++ , testRegex "[^a]" [caseless]+ ["aaaabcd",+ "aaAabcd "]+ [Just ["b"],+ Just ["b"]]++ , testRegex "[^az]" []+ ["aaaabcd",+ "aaAabcd "]+ [Just ["b"],+ Just ["A"]]++ , testRegex "[^az]" [caseless]+ ["aaaabcd",+ "aaAabcd "]+ [Just ["b"],+ Just ["b"]]++ , testRegex "P[^*]TAIRE[^*]{1,6}?LL" []+ ["xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"]+ [Just ["PSTAIREISLL"]]++ , testRegex "P[^*]TAIRE[^*]{1,}?LL" []+ ["xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"]+ [Just ["PSTAIREISLL"]]++ , testRegex "(.*?)(\\d+)" []+ ["I have 2 numbers: 53147"]+ [Just ["I have 2", "I have ", "2"]]++ , testRegex "(.*)(\\d+)$" []+ ["I have 2 numbers: 53147"]+ [Just ["I have 2 numbers: 53147", "I have 2 numbers: 5314", "7"]]++ , testRegex "(.*?)(\\d+)$" []+ ["I have 2 numbers: 53147"]+ [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]++ , testRegex "(.*)\\b(\\d+)$" []+ ["I have 2 numbers: 53147"]+ [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]++ , testRegex "(.*\\D)(\\d+)$" []+ ["I have 2 numbers: 53147"]+ [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]++ , testRegex "word (?:[a-zA-Z0-9]+ ){0,10}otherword" []+ ["word cat dog elephant mussel cow horse canary baboon snake shark otherword",+ "word cat dog elephant mussel cow horse canary baboon snake shark"]+ [Just ["word cat dog elephant mussel cow horse canary baboon snake shark otherword"],+ Nothing]++ , testRegex "word (?:[a-zA-Z0-9]+ ){0,300}otherword" []+ ["word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope"]+ [Nothing]+ , testRegex "^(a){0,0}" []+ ["bcd",+ "abc",+ "aab "]+ [Just [""],+ Just [""],+ Just [""]]++ , testRegex "^(a){0,1}" []+ ["bcd",+ "abc",+ "aab "]+ [Just [""],+ Just ["a", "a"],+ Just ["a", "a"]]++ , testRegex "^(a){0,2}" []+ ["bcd",+ "abc",+ "aab "]+ [Just [""],+ Just ["a", "a"],+ Just ["aa", "a"]]++ , testRegex "^(a){0,3}" []+ ["bcd",+ "abc",+ "aab",+ "aaa "]+ [Just [""],+ Just ["a", "a"],+ Just ["aa", "a"],+ Just ["aaa", "a"]]++ , testRegex "^(a){0,3}" []+ ["bcd",+ "abc",+ "aab",+ "aaa "]+ [Just [""],+ Just ["a", "a"],+ Just ["aa", "a"],+ Just ["aaa", "a"]]++ , testRegex "^(a){0,}" []+ ["bcd",+ "abc",+ "aab",+ "aaa",+ "aaaaaaaa "]+ [Just [""],+ Just ["a", "a"],+ Just ["aa", "a"],+ Just ["aaa", "a"],+ Just ["aaaaaaaa", "a"]]++ , testRegex "^(a){1,1}" []+ ["bcd",+ "abc",+ "aab "]+ [Nothing,+ Just ["a", "a"],+ Just ["a", "a"]]++ , testRegex "^(a){1,2}" []+ ["bcd",+ "abc",+ "aab "]+ [Nothing,+ Just ["a", "a"],+ Just ["aa", "a"]]++ , testRegex "^(a){1,3}" []+ ["bcd",+ "abc",+ "aab",+ "aaa "]+ [Nothing,+ Just ["a", "a"],+ Just ["aa", "a"],+ Just ["aaa", "a"]]++ , testRegex ".*\\.gif" []+ ["borfle\nbib.gif\nno"]+ [Just ["bib.gif"]]++ , testRegex ".{0,}\\.gif" []+ ["borfle\nbib.gif\nno"]+ [Just ["bib.gif"]]++ , testRegex ".*\\.gif" [multiline]+ ["borfle\nbib.gif\nno"]+ [Just ["bib.gif"]]++ , testRegex ".*\\.gif" [dotall]+ ["borfle\nbib.gif\nno"]+ [Just ["borfle\nbib.gif"]]++ , testRegex ".*$" [multiline]+ ["borfle\nbib.gif\nno"]+ [Just ["borfle"]]++ , testRegex ".*$" [dotall]+ ["borfle\nbib.gif\nno"]+ [Just ["borfle\nbib.gif\nno"]]++ , testRegex ".*$" [multiline]+ ["borfle\nbib.gif\nno\\n"]+ [Just ["borfle"]]++ , testRegex "(?ms)^B" []+ ["abc\nB"]+ [Just ["B"]]++ , testRegex "(?s)B$" []+ ["B\n"]+ [Just ["B"]]++ , testRegex "^[abcdefghijklmnopqrstuvwxy0123456789]" []+ ["n",+ "z "]+ [Just ["n"],+ Nothing]++ , testRegex "abcde{0,0}" []+ ["abcd",+ "abce "]+ [Just ["abcd"],+ Nothing]++ , testRegex "^(b+?|a){1,2}?c" []+ ["bac",+ "bbac",+ "bbbac",+ "bbbbac",+ "bbbbbac "]+ [Just ["bac","a"],+ Just ["bbac","a"],+ Just ["bbbac","a"],+ Just ["bbbbac","a"],+ Just ["bbbbbac","a"]]++ , testRegex "(AB)*?\\1" []+ ["ABABAB"]+ [Just ["ABAB", "AB"]]++ , testRegex "(.*(.)?)*" []+ ["abcd"]+ [Just ["abcd", ""]]++{-+ , testRegex "(?:a|)*\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]+ [Nothing,+ Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]]+-}++ , testRegex "^(?:a(?:(?:))+)+" []+ ["aaaa"]+ [Just ["aaaa"]]++ , testRegex "^(a()+)+" []+ ["aaaa"]+ [Just ["aaaa", "a", ""]]++ , testRegex "^(?:a(?:(?:))*)*" []+ ["aaaa"]+ [Just ["aaaa"]]++ , testRegex "^(a()*)*" []+ ["aaaa"]+ [Just ["aaaa", "a", ""]]++ , testRegex "^(a){1,}" []+ ["bcd",+ "abc",+ "aab",+ "aaa",+ "aaaaaaaa "]+ [Nothing,+ Just ["a", "a"],+ Just ["aa", "a"],+ Just ["aaa", "a"],+ Just ["aaaaaaaa", "a"]]++ , testRegex "(?s)(.*X|^B)" []+ ["abcde\n1234Xyz",+ "BarFoo ",+ "*** Failers ",+ "abcde\nBar "]+ [Just ["abcde\n1234X", "abcde\n1234X"],+ Just ["B", "B"],+ Nothing,+ Nothing]++ , testRegex "(?s:.*X|^B)" []+ ["abcde\n1234Xyz",+ "BarFoo ",+ "*** Failers ",+ "abcde\nBar "]+ [Just ["abcde\n1234X"],+ Just ["B"],+ Nothing,+ Nothing]++ , testRegex "\\w{3}(?<!bar)foo" []+ ["catfood",+ "*** Failers",+ "foo",+ "barfoo",+ "towbarfoo"]+ [Just ["catfoo"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex "(?>(\\.\\d\\d[1-9]?))\\d+" []+ ["1.230003938",+ "1.875000282",+ "1.235 "]+ [Just [".230003938", ".23"],+ Just [".875000282", ".875"],+ Nothing]++ , testRegex "^((?>\\w+)|(?>\\s+))*$" []+ ["now is the time for all good men to come to the aid of the party",+ "this is not a line with only words and spaces!"]+ [Just ["now is the time for all good men to come to the aid of the party", "party"],+ Nothing]++ , testRegex "((?>\\d+))(\\w)" []+ ["12345a",+ "12345+ "]+ [Just ["12345a", "12345", "a"],+ Nothing]++ , testRegex "(?>a+)b" []+ ["aaab"]+ [Just ["aaab"]]++ , testRegex "((?>a+)b)" []+ ["aaab"]+ [Just ["aaab", "aaab"]]++ , testRegex "(?>(a+))b" []+ ["aaab"]+ [Just ["aaab", "aaa"]]+ , testRegex "(?>b)+" []+ ["aaabbbccc"]+ [Just ["bbb"]]++ , testRegex "(?>a+|b+|c+)*c" []+ ["aaabbbbccccd"]+ [Just ["aaabbbbc"]]++ , testRegex "(?:(a)|b)(?(1)A|B)" []+ ["aA",+ "bB",+ "aB",+ "bA "]+ [Just ["aA", "a"],+ Just ["bB"],+ Nothing,+ Nothing]++ , testRegex "^(a)?(?(1)a|b)+$" []+ ["aa",+ "b",+-- "bb ", -- ?+ "ab "]+ [Just ["aa", "a"],+ Just ["b"],+-- Just ["bb"],+ Nothing]++ , testRegex "^(?(?=abc)\\w{3}:|\\d\\d)$" []+ ["abc:",+ "12",+ "123",+ "xyz "]+ [Just ["abc:"],+ Just ["12"],+ Nothing,+ Nothing]++ , testRegex "(?(?<!foo)cat|bar)" []+ ["foobar",+ "cat",+ "fcat",+ "focat ",+ "foocat "]+ [Just ["bar"],+ Just ["cat"],+ Just ["cat"],+ Just ["cat"],+ Nothing]++ , testRegex "^(?(2)a|(1)(2))+$" []+ ["12",+ "12a",+ "12aa",+ "*** Failers",+ "1234 "]+ [Just ["12", "1", "2"],+ Just ["12a", "1", "2"],+ Just ["12aa", "1", "2"],+ Nothing,+ Nothing]++ , testRegex "(?<=foo\\n)^bar" [multiline]+ ["foo\nbar",+ "*** Failers",+ "bar",+ "baz\nbar "]+ [Just ["bar"],+ Nothing,+ Nothing,+ Nothing]++ , testRegex "(?<=(?<!foo)bar)baz" []+ ["barbaz",+ "barbarbaz ",+ "koobarbaz ",+ "*** Failers",+ "baz",+ "foobarbaz "]+ [Just ["baz"],+ Just ["baz"],+ Just ["baz"],+ Nothing,+ Nothing,+ Nothing]++{-+ , testRegex "^(a\\1?){4}$" []+ ["a",+ "aa",+ "aaa",+ "aaaa",+ "aaaaa",+ "aaaaaaa",+ "aaaaaaaa",+ "aaaaaaaaa",+ "aaaaaaaaaa",+ "aaaaaaaaaaa",+ "aaaaaaaaaaaa",+ "aaaaaaaaaaaaa",+ "aaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaa "]+ [Nothing,+ Nothing,+ Nothing,+ Just ["aaaa", "a"],+ Just ["aaaaa", "a"],+ Just ["aaaaaaa", "a"],+ Nothing,+ Nothing,+ Just ["aaaaaaaaaa", "aaaa"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]+-}++ , testRegex "abc" []+ ["abc",+ "xabcy",+ "ababc",+ "*** Failers",+ "xbc",+ "axc",+ "abx"]+ [Just ["abc"],+ Just ["abc"],+ Just ["abc"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ , testRegex "ab*c" []+ ["abc"]+ [Just ["abc"]]+ , testRegex "ab*bc" []+ ["abc",+ "abbc",+ "abbbbc"]+ [Just ["abc"],+ Just ["abbc"],+ Just ["abbbbc"]]++ , testRegex ".{1}" []+ ["abbbbc"]+ [Just ["a"]]++ , testRegex ".{3,4}" []+ ["abbbbc"]+ [Just ["abbb"]]++ , testRegex "ab{0,}bc" []+ ["abbbbc"]+ [Just ["abbbbc"]]++ , testRegex "ab+bc" []+ ["abbc",+ "abc",+ "abq"]+ [Just ["abbc"],+ Nothing,+ Nothing]++ , testRegex "ab{1,}bc" []+ []+ []++ , testRegex "ab+bc" []+ ["abbbbc"]+ [Just ["abbbbc"]]++ , testRegex "ab{1,}bc" []+ ["abbbbc"]+ [Just ["abbbbc"]]++ , testRegex "ab{1,3}bc" []+ ["abbbbc"]+ [Just ["abbbbc"]]++ , testRegex "ab{3,4}bc" []+ ["abbbbc"]+ [Just ["abbbbc"]]++ , testRegex "ab{4,5}bc" []+ ["*** Failers",+ "abq",+ "abbbbc"]+ [Nothing,+ Nothing,+ Nothing]++ , testRegex "ab?bc" []+ ["abbc",+ "abc"]+ [Just ["abbc"],+ Just ["abc"]]++ , testRegex "ab{0,1}bc" []+ ["abc"]+ [Just ["abc"]]++ , testRegex "ab?bc" []+ []+ []++ , testRegex "ab?c" []+ ["abc"]+ [Just ["abc"]]++ , testRegex "ab{0,1}c" []+ ["abc"]+ [Just ["abc"]]++ , testRegex "^abc$" []+ ["abc",+ "abbbbc",+ "abcc"]+ [Just ["abc"],+ Nothing,+ Nothing]++ , testRegex "^abc" []+ ["abcc"]+ [Just ["abc"]]++ , testRegex "^abc$" []+ []+ []++ , testRegex "abc$" []+ ["aabc",+ "*** Failers",+ "aabc",+ "aabcd"]+ [Just ["abc"],+ Nothing,+ Just ["abc"],+ Nothing]++ , testRegex "^" []+ ["abc"]+ [Just [""]]+ ,++ testRegex "$" []+ ["abc"]+ [Just [""]]+ ,++ testRegex "a.c" []+ ["abc",+ "axc"]+ [Just ["abc"],+ Just ["axc"]]+ ,++ testRegex "a.*c" []+ ["axyzc"]+ [Just ["axyzc"]]+ ,++ testRegex "a[bc]d" []+ ["abd",+ "*** Failers",+ "axyzd",+ "abc"]+ [Just ["abd"],+ Nothing,+ Nothing,+ Nothing]+ ,++ testRegex "a[b-d]e" []+ ["ace"]+ [Just ["ace"]]+ ,++ testRegex "a[b-d]" []+ ["aac"]+ [Just ["ac"]]+ ,++ testRegex "a[-b]" []+ ["a-"]+ [Just ["a-"]]+ ,++ testRegex "a[b-]" []+ ["a-"]+ [Just ["a-"]]+ ,+++ testRegex "a]" []+ ["a]"]+ [Just ["a]"]]+ ,+++ testRegex "a[]]b" []+ ["a]b"]+ [Just ["a]b"]]+ ,++ testRegex "a[^bc]d" []+ ["aed",+ "*** Failers",+ "abd",+ "abd"]+ [Just ["aed"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "a[^-b]c" []+ ["adc"]+ [Just ["adc"]]+ ,++ testRegex "a[^]b]c" []+ ["adc",+ "*** Failers",+ "a-c",+ "a]c"]+ [Just ["adc"],+ Nothing,+ Just ["a-c"],+ Nothing]+ ,+++ testRegex "\\ba\\b" []+ ["a-",+ "-a",+ "-a-"]+ [Just ["a"],+ Just ["a"],+ Just ["a"]]+ ,+++ testRegex "\\by\\b" []+ ["*** Failers",+ "xy",+ "yz",+ "xyz"]+ [Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "\\Ba\\B" []+ ["*** Failers",+ "a-",+ "-a",+ "-a-"]+ [Just ["a"],+ Nothing,+ Nothing,+ Nothing]+ ,++ testRegex "\\By\\b" []+ ["xy"]+ [Just ["y"]]+ ,+++ testRegex "\\by\\B" []+ ["yz"]+ [Just ["y"]]+ ,+++ testRegex "\\By\\B" []+ ["xyz"]+ [Just ["y"]]+ ,++ testRegex "\\w" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "\\W" []+ ["-",+ "*** Failers",+ "-",+ "a"]+ [Just ["-"],+ Just ["*"],+ Just ["-"],+ Nothing]+ ,+++ testRegex "a\\sb" []+ ["a b"]+ [Just ["a b"]]+ ,+++ testRegex "a\\Sb" []+ ["a-b",+ "*** Failers",+ "a-b",+ "a b"]+ [Just ["a-b"],+ Nothing,+ Just ["a-b"],+ Nothing]+ ,+++ testRegex "\\d" []+ ["1"]+ [Just ["1"]]+ ,+++ testRegex "\\D" []+ ["-",+ "*** Failers",+ "-",+ "1"]+ [Just ["-"],+ Just ["*"],+ Just ["-"],+ Nothing]+ ,+++ testRegex "[\\w]" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "[\\W]" []+ ["-",+ "*** Failers",+ "-",+ "a"]+ [Just ["-"],+ Just ["*"],+ Just ["-"],+ Nothing]+ ,+++ testRegex "a[\\s]b" []+ ["a b"]+ [Just ["a b"]]+ ,+++ testRegex "a[\\S]b" []+ ["a-b",+ "*** Failers",+ "a-b",+ "a b"]+ [Just ["a-b"],+ Nothing,+ Just ["a-b"],+ Nothing]+ ,++ testRegex "[\\d]" []+ ["1"]+ [Just ["1"]]+ ,+++ testRegex "[\\D]" []+ ["-",+ "*** Failers",+ "-",+ "1"]+ [Just ["-"],+ Just ["*"],+ Just ["-"],+ Nothing]+ ,+++ testRegex "ab|cd" []+ ["abc",+ "abcd"]+ [Just ["ab"],+ Just ["ab"]]+ ,++++ testRegex "$b" []+ []+ []+ ,+++ testRegex "a\\(b" []+ ["a(b"]+ [Just ["a(b"]]+ ,+++ testRegex "a\\(*b" []+ ["ab",+ "a((b"]+ [Just ["ab"],+ Just ["a((b"]]+ ,+++ testRegex "((a))" []+ ["abc"]+ [Just ["a", "a", "a"]]+ ,+++ testRegex "(a)b(c)" []+ ["abc"]+ [Just ["abc", "a", "c"]]++ ,+ testRegex "a+b+c" []+ ["aabbabc"]+ [Just ["abc"]]+ ,+++ testRegex "a{1,}b{1,}c" []+ ["aabbabc"]+ [Just ["abc"]]+ ,+++ testRegex "a.+?c" []+ ["abcabc"]+ [Just ["abc"]]+ ,+++ testRegex "(a+|b)*" []+ ["ab"]+ [Just ["ab", "b"]]+ ,+++ testRegex "(a+|b){0,}" []+ ["ab"]+ [Just ["ab", "b"]]+ ,+++ testRegex "(a+|b)+" []+ ["ab"]+ [Just ["ab","b"]]+ ,+++ testRegex "(a+|b){1,}" []+ ["ab"]+ [Just ["ab", "b"]]+ ,+++ testRegex "(a+|b)?" []+ ["ab"]+ [Just ["a", "a"]]+ ,+++ testRegex "(a+|b){0,1}" []+ ["ab"]+ [Just ["a", "a"]]+ ,+++ testRegex "[^ab]*" []+ ["cde"]+ [Just ["cde"]]++ ,++ testRegex "abc" []+ ["b"]+ [Nothing]+ ,+++ testRegex "a*" []+ [""]+ [Just [""]]+ ,+++ testRegex "([abc])*d" []+ ["abbbcd"]+ [Just ["abbbcd", "c"]]+ ,+++ testRegex "([abc])*bcd" []+ ["abcd"]+ [Just ["abcd", "a"]]+ ,+++ testRegex "a|b|c|d|e" []+ ["e"]+ [Just ["e"]]+ ,+++ testRegex "(a|b|c|d|e)f" []+ ["ef"]+ [Just ["ef", "e"]]+ ,+++ testRegex "abcd*efg" []+ ["abcdefg"]+ [Just ["abcdefg"]]+ ,+++ testRegex "ab*" []+ ["xabyabbbz",+ "xayabbbz"]+ [Just ["ab"],+ Just ["a"]]+ ,+++ testRegex "(ab|cd)e" []+ ["abcde"]+ [Just ["cde", "cd"]]+ ,+++ testRegex "[abhgefdc]ij" []+ ["hij"]+ [Just ["hij"]]++ , testRegex "^(ab|cd)e" []+ []+ []+ ,++ testRegex "(abc|)ef" []+ ["abcdef"]+ [Just ["ef", ""]]+ ,+++ testRegex "(a|b)c*d" []+ ["abcd"]+ [Just ["bcd", "b"]]+ ,+++ testRegex "(ab|ab*)bc" []+ ["abc"]+ [Just ["abc", "a"]]+ ,+++ testRegex "a([bc]*)c*" []+ ["abc"]+ [Just ["abc", "bc"]]+ ,+++ testRegex "a([bc]*)(c*d)" []+ ["abcd"]+ [Just ["abcd", "bc", "d"]]+ ,+++ testRegex "a([bc]+)(c*d)" []+ ["abcd"]+ [Just ["abcd", "bc", "d"]]+ ,+++ testRegex "a([bc]*)(c+d)" []+ ["abcd"]+ [Just ["abcd", "b", "cd"]]+ ,+++ testRegex "a[bcd]*dcdcde" []+ ["adcdcde"]+ [Just ["adcdcde"]]+ ,+++ testRegex "a[bcd]+dcdcde" []+ ["*** Failers",+ "abcde",+ "adcdcde"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(ab|a)b*c" []+ ["abc"]+ [Just ["abc", "ab"]]++ ,++ testRegex "((a)(b)c)(d)" []+ ["abcd"]+ [Just ["abcd", "abc", "a", "b", "d"]]+ ,+++ testRegex "[a-zA-Z_][a-zA-Z0-9_]*" []+ ["alpha"]+ [Just ["alpha"]]+ ,+++ testRegex "^a(bc+|b[eh])g|.h$" []+ ["abh"]+ [Just ["bh"]]+ ,+++ testRegex "(bc+d$|ef*g.|h?i(j|k))" []+ ["effgz",+ "ij",+ "reffgz",+ "*** Failers",+ "effg",+ "bcdd"]+ [Just ["effgz", "effgz"],+ Just ["ij", "ij", "j"],+ Just ["effgz", "effgz"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((((((((((a))))))))))" []+ ["a"]+ [Just ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]]+ ,+++ testRegex "((((((((((a))))))))))\\10" []+ ["aa"]+ [Just ["aa", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]]+ ,+++ testRegex "(((((((((a)))))))))" []+ ["a"]+ [Just ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]]+ ,+++ testRegex "multiple words of text" []+ ["*** Failers",+ "aa",+ "uh-uh"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "multiple words" []+ ["multiple words, yeah"]+ [Just ["multiple words"]]+ ,+++ testRegex "(.*)c(.*)" []+ ["abcde"]+ [Just ["abcde", "ab", "de"]]+ ,++ testRegex "\\((.*), (.*)\\)" []+ ["(a, b)"]+ [Just ["(a, b)", "a", "b"]]+ ,+++ testRegex "[k]" []+ []+ []+ ,+++ testRegex "abcd" []+ ["abcd"]+ [Just ["abcd"]]+ ,+++ testRegex "a(bc)d" []+ ["abcd"]+ [Just ["abcd", "bc"]]+ ,+++ testRegex "a[-]?c" []+ ["ac"]+ [Just ["ac"]]+ ,+++ testRegex "(abc)\\1" []+ ["abcabc"]+ [Just ["abcabc", "abc"]]+ ,+++ testRegex "([a-c]*)\\1" []+ ["abcabc"]+ [Just ["abcabc", "abc"]]+ ,+++ testRegex "(a)|\\1" []+ ["a",+ "*** Failers",+ "ab",+ "x"]+ [Just ["a", "a"],+ Just ["a", "a"],+ Just ["a", "a"],+ Nothing]+ ,+++ testRegex "(([a-c])b*?\\2)*" []+ ["ababbbcbc"]+ [Just ["ababb", "bb", "b"]]+ ,+++ testRegex "(([a-c])b*?\\2){3}" []+ ["ababbbcbc"]+ [Just ["ababbbcbc", "cbc", "c"]]+ ,+ testRegex "((\\3|b)\\2(a)x)+" []+ ["aaaxabaxbaaxbbax"]+ [Just ["bbax", "bbax", "b", "a"]]+ ,+++ testRegex "((\\3|b)\\2(a)){2,}" []+ ["bbaababbabaaaaabbaaaabba"]+ [Just ["bbaaaabba", "bba", "b", "a"]]+ ,+++ testRegex "abc" [caseless]+ ["ABC",+ "XABCY",+ "ABABC",+ "*** Failers",+ "aaxabxbaxbbx",+ "XBC",+ "AXC",+ "ABX"]+ [Just ["ABC"],+ Just ["ABC"],+ Just ["ABC"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "ab*c" [caseless]+ ["ABC"]+ [Just ["ABC"]]+ ,+++ testRegex "ab*bc" [caseless]+ ["ABC",+ "ABBC"]+ [Just ["ABC"],+ Just ["ABBC"]]+ ,+++ testRegex "ab*?bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab{0,}?bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab+?bc" [caseless]+ ["ABBC"]+ [Just ["ABBC"]]+ ,+++ testRegex "ab+bc" [caseless]+ ["*** Failers",+ "ABC",+ "ABQ"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "ab{1,}bc" [caseless]+ []+ []+ ,++ testRegex "ab+bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab{1,}?bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab{1,3}?bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab{3,4}?bc" [caseless]+ ["ABBBBC"]+ [Just ["ABBBBC"]]+ ,+++ testRegex "ab{4,5}?bc" [caseless]+ ["*** Failers",+ "ABQ",+ "ABBBBC"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "ab??bc" [caseless]+ ["ABBC",+ "ABC"]+ [Just ["ABBC"],+ Just ["ABC"]]+ ,+++ testRegex "ab{0,1}?bc" [caseless]+ ["ABC"]+ [Just ["ABC"]]+ ,+++ testRegex "ab??bc" [caseless]+ []+ []+ ,+++ testRegex "ab??c" [caseless]+ ["ABC"]+ [Just ["ABC"]]+ ,++ testRegex "ab{0,1}?c" [caseless]+ ["ABC"]+ [Just ["ABC"]]+ ,+ testRegex "^abc$" [caseless]+ ["ABC",+ "*** Failers",+ "ABBBBC",+ "ABCC"]+ [Just ["ABC"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "^abc" [caseless]+ ["ABCC"]+ [Just ["ABC"]]+ ,+++ testRegex "^abc$" [caseless]+ []+ []+ ,+++ testRegex "abc$" [caseless]+ ["AABC"]+ [Just ["ABC"]]+ ,+++ testRegex "^" [caseless]+ ["ABC"]+ [Just [""]]+ ,+++ testRegex "$" [caseless]+ ["ABC"]+ [Just [""]]+ ,+++ testRegex "a.c" [caseless]+ ["ABC",+ "AXC"]+ [Just ["ABC"],+ Just ["AXC"]]+ ,+++ testRegex "a.*?c" [caseless]+ ["AXYZC"]+ [Just ["AXYZC"]]+ ,+++ testRegex "a.*c" [caseless]+ ["*** Failers",+ "AABC",+ "AXYZD"]+ [Nothing,+ Just ["AABC"],+ Nothing]+ ,+++ testRegex "a[bc]d" [caseless]+ ["ABD"]+ [Just ["ABD"]]+ ,++ testRegex "a[b-d]e" [caseless]+ ["ACE",+ "ABC",+ "ABD"]+ [Just ["ACE"],+ Nothing,+ Nothing]+ ,+++ testRegex "a[b-d]" [caseless]+ ["AAC"]+ [Just ["AC"]]+ ,+++ testRegex "a[-b]" [caseless]+ ["A-"]+ [Just ["A-"]]+ ,+++ testRegex "a[b-]" [caseless]+ ["A-"]+ [Just ["A-"]]+ ,+++ testRegex "a]" [caseless]+ ["A]"]+ [Just ["A]"]]+ ,+++ testRegex "a[]]b" [caseless]+ ["A]B"]+ [Just ["A]B"]]+ ,+++ testRegex "a[^bc]d" [caseless]+ ["AED"]+ [Just ["AED"]]+ ,+++ testRegex "a[^-b]c" [caseless]+ ["ADC",+ "ABD",+ "A-C"]+ [Just ["ADC"],+ Nothing,+ Nothing]+ ,+++ testRegex "a[^]b]c" [caseless]+ ["ADC"]+ [Just ["ADC"]]+ ,+++ testRegex "ab|cd" [caseless]+ ["ABC",+ "ABCD"]+ [Just ["AB"],+ Just ["AB"]]++ ,+ testRegex "()ef" [caseless]+ ["DEF"]+ [Just ["EF", ""]]+ ,+++ testRegex "$b" [caseless]+ ["A]C",+ "B"]+ [Nothing,+ Nothing]+ ,+++ testRegex "a\\(b" [caseless]+ ["A(B"]+ [Just ["A(B"]]+ ,+++ testRegex "a\\(*b" [caseless]+ ["AB",+ "A((B"]+ [Just ["AB"],+ Just ["A((B"]]+ ,++++ testRegex "((a))" [caseless]+ ["ABC"]+ [Just ["A", "A", "A"]]+ ,+++ testRegex "(a)b(c)" [caseless]+ ["ABC"]+ [Just ["ABC", "A", "C"]]+ ,+++ testRegex "a+b+c" [caseless]+ ["AABBABC"]+ [Just ["ABC"]]+ ,+++ testRegex "a{1,}b{1,}c" [caseless]+ ["AABBABC"]+ [Just ["ABC"]]+ ,+++ testRegex "a.+?c" [caseless]+ ["ABCABC"]+ [Just ["ABC"]]+ ,++ testRegex "a.*?c" [caseless]+ ["ABCABC"]+ [Just ["ABC"]]+ ,+++ testRegex "a.{0,5}?c" [caseless]+ ["ABCABC"]+ [Just ["ABC"]]+ ,+++ testRegex "(a+|b)*" [caseless]+ ["AB"]+ [Just ["AB", "B"]]+ ,+++ testRegex "(a+|b){0,}" [caseless]+ ["AB"]+ [Just ["AB", "B"]]+ ,+++ testRegex "(a+|b)+" [caseless]+ ["AB"]+ [Just ["AB","B"]]+ ,+++ testRegex "(a+|b){1,}" [caseless]+ ["AB"]+ [Just ["AB", "B"]]+ ,+++ testRegex "(a+|b)?" [caseless]+ ["AB"]+ [Just ["A", "A"]]+ ,+++ testRegex "(a+|b){0,1}" [caseless]+ ["AB"]+ [Just ["A", "A"]]+ ,+++ testRegex "(a+|b){0,1}?" [caseless]+ ["AB"]+ [Just [""]]+ ,+++ testRegex "[^ab]*" [caseless]+ ["CDE"]+ [Just ["CDE"]]+ ,++ testRegex "abc" [caseless]+ []+ []+ ,+++ testRegex "a*" [caseless]+ [""]+ [Just [""]]+ ,+++ testRegex "([abc])*d" [caseless]+ ["ABBBCD"]+ [Just ["ABBBCD", "C"]]+ ,+++ testRegex "([abc])*bcd" [caseless]+ ["ABCD"]+ [Just ["ABCD","A"]]+ ,+++ testRegex "a|b|c|d|e" [caseless]+ ["E"]+ [Just ["E"]]+ ,+++ testRegex "(a|b|c|d|e)f" [caseless]+ ["EF"]+ [Just ["EF", "E"]]+ ,+++ testRegex "abcd*efg" [caseless]+ ["ABCDEFG"]+ [Just ["ABCDEFG"]]+ ,+++ testRegex "ab*" [caseless]+ ["XABYABBBZ",+ "XAYABBBZ"]+ [Just ["AB"],+ Just ["A"]]+ ,+++ testRegex "(ab|cd)e" [caseless]+ ["ABCDE"]+ [Just ["CDE", "CD"]]+ ,+++ testRegex "[abhgefdc]ij" [caseless]+ ["HIJ"]+ [Just ["HIJ"]]+ ,+++ testRegex "^(ab|cd)e" [caseless]+ ["ABCDE"]+ [Nothing]+ ,+++ testRegex "(abc|)ef" [caseless]+ ["ABCDEF"]+ [Just ["EF", ""]]+ ,+++ testRegex "(a|b)c*d" [caseless]+ ["ABCD"]+ [Just ["BCD", "B"]]+ ,+++ testRegex "(ab|ab*)bc" [caseless]+ ["ABC"]+ [Just ["ABC", "A"]]+ ,+++ testRegex "a([bc]*)c*" [caseless]+ ["ABC"]+ [Just ["ABC", "BC"]]+ ,+++ testRegex "a([bc]*)(c*d)" [caseless]+ ["ABCD"]+ [Just ["ABCD","BC","D"]]+ ,+++ testRegex "a([bc]+)(c*d)" [caseless]+ ["ABCD"]+ [Just ["ABCD","BC","D"]]+ ,+++ testRegex "a([bc]*)(c+d)" [caseless]+ ["ABCD"]+ [Just ["ABCD","B","CD"]]+ ,+++ testRegex "a[bcd]*dcdcde" [caseless]+ ["ADCDCDE"]+ [Just ["ADCDCDE"]]+ ,++ testRegex "a[bcd]+dcdcde" [caseless]+ []+ []+ ,++ testRegex "(ab|a)b*c" [caseless]+ ["ABC"]+ [Just ["ABC", "AB"]]+ ,+++ testRegex "((a)(b)c)(d)" [caseless]+ ["ABCD"]+ [Just ["ABCD", "ABC", "A", "B", "D"]]+ ,+++ testRegex "[a-zA-Z_][a-zA-Z0-9_]*" [caseless]+ ["ALPHA"]+ [Just ["ALPHA"]]+ ,+++ testRegex "^a(bc+|b[eh])g|.h$" [caseless]+ ["ABH"]+ [Just ["BH"]]+ ,+++ testRegex "(bc+d$|ef*g.|h?i(j|k))" [caseless]+ ["EFFGZ",+ "IJ",+ "REFFGZ",+ "*** Failers",+ "ADCDCDE",+ "EFFG",+ "BCDD"]+ [Just ["EFFGZ", "EFFGZ"],+ Just ["IJ", "IJ", "J"],+ Just ["EFFGZ", "EFFGZ"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((((((((((a))))))))))" [caseless]+ ["A"]+ [Just ["A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]]+ ,+++ testRegex "((((((((((a))))))))))\\10" [caseless]+ ["AA"]+ [Just ["AA", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]]+ ,+++ testRegex "(((((((((a)))))))))" [caseless]+ ["A"]+ [Just ["A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]]+ ,+++ testRegex "(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))" [caseless]+ ["A"]+ [Just ["A", "A"]]+ ,+++ testRegex "(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))" [caseless]+ ["C"]+ [Just ["C", "C"]]+ ,+++ testRegex "multiple words of text" [caseless]+ ["AA",+ "UH-UH"]+ [Nothing,+ Nothing]+ ,+++ testRegex "multiple words" [caseless]+ ["MULTIPLE WORDS, YEAH"]+ [Just ["MULTIPLE WORDS"]]+ ,+++ testRegex "(.*)c(.*)" [caseless]+ ["ABCDE"]+ [Just ["ABCDE", "AB", "DE"]]+ ,+++ testRegex "\\((.*), (.*)\\)" [caseless]+ ["(A, B)"]+ [Just ["(A, B)", "A", "B"]]+ ,+++ testRegex "[k]" [caseless]+ []+ []+ ,+++ testRegex "abcd" [caseless]+ ["ABCD"]+ [Just ["ABCD"]]+ ,+++ testRegex "a(bc)d" [caseless]+ ["ABCD"]+ [Just ["ABCD", "BC"]]+ ,+++ testRegex "a[-]?c" [caseless]+ ["AC"]+ [Just ["AC"]]+ ,+++ testRegex "(abc)\\1" [caseless]+ ["ABCABC"]+ [Just ["ABCABC", "ABC"]]+ ,+++ testRegex "([a-c]*)\\1" [caseless]+ ["ABCABC"]+ [Just ["ABCABC", "ABC"]]+ ,++ testRegex "a(?!b)." []+ ["abad"]+ [Just ["ad"]]+ ,+++ testRegex "a(?=d)." []+ ["abad"]+ [Just ["ad"]]+ ,+++ testRegex "a(?=c|d)." []+ ["abad"]+ [Just ["ad"]]+ ,+++ testRegex "a(?:b|c|d)(.)" []+ ["ace"]+ [Just ["ace", "e"]]+ ,+++ testRegex "a(?:b|c|d)*(.)" []+ ["ace"]+ [Just ["ace", "e"]]+ ,+++ testRegex "a(?:b|c|d)+?(.)" []+ ["ace",+ "acdbcdbe"]+ [Just ["ace", "e"],+ Just ["acd", "d"]]+ ,+++ testRegex "a(?:b|c|d)+(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdbe", "e"]]+ ,+++ testRegex "a(?:b|c|d){2}(.)" []+ ["acdbcdbe"]+ [Just ["acdb", "b"]]+ ,+++ testRegex "a(?:b|c|d){4,5}(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdb", "b"]]+ ,+++ testRegex "a(?:b|c|d){4,5}?(.)" []+ ["acdbcdbe"]+ [Just ["acdbcd", "d"]]+ ,+++ testRegex "((foo)|(bar))*" []+ ["foobar"]+ [Just ["foobar", "bar", "foo", "bar"]]+ ,+++ testRegex "a(?:b|c|d){6,7}(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdbe", "e"]]+ ,+++ testRegex "a(?:b|c|d){6,7}?(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdbe", "e"]]+ ,+++ testRegex "a(?:b|c|d){5,6}(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdbe", "e"]]+ ,+++ testRegex "a(?:b|c|d){5,6}?(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdb", "b"]]+ ,+++ testRegex "a(?:b|c|d){5,7}(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdbe", "e"]]+ ,+++ testRegex "a(?:b|c|d){5,7}?(.)" []+ ["acdbcdbe"]+ [Just ["acdbcdb", "b"]]+ ,+++ testRegex "a(?:b|(c|e){1,2}?|d)+?(.)" []+ ["ace"]+ [Just ["ace", "c", "e"]]+ ,+++ testRegex "^(.+)?B" []+ ["AB"]+ [Just ["AB", "A"]]+ ,+++ testRegex "^([^a-z])|(\\^)$" []+ ["."]+ [Just [".", "."]]+ ,++ testRegex "^[<>]&" []+ ["<&OUT"]+ [Just ["<&"]]+ ,+++ testRegex "^(a\\1?){4}$" []+ ["aaaaaaaaaa",+ "*** Failers",+ "AB",+ "aaaaaaaaa",+ "aaaaaaaaaaa"]+ [Just ["aaaaaaaaaa", "aaaa"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "^(a(?(1)\\1)){4}$" []+ ["aaaaaaaaaa",+ "*** Failers",+ "aaaaaaaaa",+ "aaaaaaaaaaa"]+ [Just ["aaaaaaaaaa", "aaaa"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(?:(f)(o)(o)|(b)(a)(r))*" []+ ["foobar"]+ [Just ["foobar", "f", "o", "o", "b", "a", "r"]]+ ,+++ testRegex "(?<=a)b" []+ ["ab",+ "*** Failers",+ "cb",+ "b"]+ [Just ["b"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(?<!c)b" []+ ["ab",+ "b",+ "b"]+ [Just ["b"],+ Just ["b"],+ Just ["b"]]+ ,+++ testRegex "(?:..)*a" []+ ["aba"]+ [Just ["aba"]]+ ,+++ testRegex "(?:..)*?a" []+ ["aba"]+ [Just ["a"]]+ ,+++ testRegex "^(?:b|a(?=(.)))*\\1" []+ ["abc"]+ [Just ["ab", "b"]]+ ,+++ testRegex "^(){3,5}" []+ ["abc"]+ [Just ["", ""]]+ ,+++ testRegex "^(a+)*ax" []+ ["aax"]+ [Just ["aax", "a"]]+ ,+++ testRegex "^((a|b)+)*ax" []+ ["aax"]+ [Just ["aax", "a", "a"]]+ ,+++ testRegex "^((a|bc)+)*ax" []+ ["aax"]+ [Just ["aax", "a", "a"]]+ ,+++ testRegex "(a|x)*ab" []+ ["cab"]+ [Just ["ab"]]+ ,+++ testRegex "(a)*ab" []+ ["cab"]+ [Just ["ab"]]+ ,+++ testRegex "(?:(?i)a)b" []+ ["ab"]+ [Just ["ab"]]+ ,+++ testRegex "((?i)a)b" []+ ["ab"]+ [Just ["ab", "a"]]+ ,+++ testRegex "(?:(?i)a)b" []+ ["Ab"]+ [Just ["Ab"]]+ ,+++ testRegex "((?i)a)b" []+ ["Ab"]+ [Just ["Ab", "A"]]+ ,+++ testRegex "(?:(?i)a)b" []+ ["*** Failers",+ "cb",+ "aB"]+ [Nothing,+ Nothing,+ Nothing]+ ,+ testRegex "((?i)a)b" []+ []+ []+ ,+++ testRegex "(?i:a)b" []+ ["ab"]+ [Just ["ab"]]+ ,+++ testRegex "((?i:a))b" []+ ["ab"]+ [Just ["ab", "a"]]+ ,+++ testRegex "(?i:a)b" []+ ["Ab"]+ [Just ["Ab"]]+ ,+++ testRegex "((?i:a))b" []+ ["Ab"]+ [Just ["Ab", "A"]]+ ,+++ testRegex "(?i:a)b" []+ ["*** Failers",+ "aB",+ "aB"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?i:a))b" []+ []+ []+ ,+++ testRegex "(?:(?-i)a)b" [caseless]+ ["ab"]+ [Just ["ab"]]+ ,+++ testRegex "((?-i)a)b" [caseless]+ ["ab"]+ [Just ["ab", "a"]]+ ,+++ testRegex "(?:(?-i)a)b" [caseless]+ ["aB"]+ [Just ["aB"]]+ ,+++ testRegex "((?-i)a)b" [caseless]+ ["aB"]+ [Just ["aB", "a"]]+ ,+++ testRegex "(?:(?-i)a)b" [caseless]+ ["*** Failers",+ "aB",+ "Ab"]+ [Nothing,+ Just ["aB"],+ Nothing]+ ,+++ testRegex "((?-i)a)b" [caseless]+ []+ []+ ,+++ testRegex "(?:(?-i)a)b" [caseless]+ ["aB"]+ [Just ["aB"]]+ ,+++ testRegex "((?-i)a)b" [caseless]+ ["aB"]+ [Just ["aB", "a"]]+ ,+++ testRegex "(?:(?-i)a)b" [caseless]+ ["*** Failers",+ "Ab",+ "AB"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?-i)a)b" [caseless]+ []+ []+ ,+++ testRegex "(?-i:a)b" [caseless]+ ["ab"]+ [Just ["ab"]]+ ,+++ testRegex "((?-i:a))b" [caseless]+ ["ab"]+ [Just ["ab", "a"]]+ ,+++ testRegex "(?-i:a)b" [caseless]+ ["aB"]+ [Just ["aB"]]+ ,+++ testRegex "((?-i:a))b" [caseless]+ ["aB"]+ [Just ["aB", "a"]]+ ,+++ testRegex "(?-i:a)b" [caseless]+ ["*** Failers",+ "AB",+ "Ab"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?-i:a))b" [caseless]+ []+ []+ ,+++ testRegex "(?-i:a)b" [caseless]+ ["aB"]+ [Just ["aB"]]+ ,+++ testRegex "((?-i:a))b" [caseless]+ ["aB"]+ [Just ["aB", "a"]]+ ,+++ testRegex "(?-i:a)b" [caseless]+ ["*** Failers",+ "Ab",+ "AB"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?-i:a))b" [caseless]+ []+ []+ ,+++ testRegex "((?-i:a.))b" [caseless]+ ["*** Failers",+ "AB",+ "a\nB"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?s-i:a.))b" [caseless]+ ["a\nB"]+ [Just ["a\nB", "a\n"]]+ ,+++ testRegex "(?:c|d)(?:)(?:a(?:)(?:b)(?:b(?:))(?:b(?:)(?:b)))" []+ ["cabbbb"]+ [Just ["cabbbb"]]+ ,++ testRegex "(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))" []+ ["caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]+ [Just ["caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]]+ ,+++ testRegex "(ab)\\d\\1" [caseless]+ ["Ab4ab",+ "ab4Ab"]+ [Just ["Ab4ab", "Ab"],+ Just ["ab4Ab", "ab"]]+ ,+++ testRegex "foo\\w*\\d{4}baz" []+ ["foobar1234baz"]+ [Just ["foobar1234baz"]]+ ,+++ testRegex "x(~~)*(?:(?:F)?)?" []+ ["x~~"]+ [Just ["x~~", "~~"]]+ ,+++ testRegex "^a(?#xxx){3}c" []+ ["aaac"]+ [Just ["aaac"]]+ ,+++ testRegex "^a (?#xxx) (?#yyy) {3}c" [extended]+ ["aaac"]+ [Just ["aaac"]]+ ,+++ testRegex "(?<![cd])b" []+ ["*** Failers",+ "B\nB",+ "dbcb"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(?<![cd])[ab]" []+ ["dbaacb"]+ [Just ["a"]]+ ,+++ testRegex "(?<!(c|d))b" []+ []+ []+ ,+++ testRegex "(?<!(c|d))[ab]" []+ ["dbaacb"]+ [Just ["a"]]+ ,+++ testRegex "(?<!cd)[ab]" []+ ["cdaccb"]+ [Just ["b"]]+ ,++{-+ testRegex "^(?:a?b?)*$" []+ ["a",+ "ab",+ "aaa ",+ "*** Failers",+ "dbcb",+ "a--",+ "aa-- "]+ [Just ["a"],+ Just ["ab"],+ Just ["aaa"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+ -}+++ testRegex "((?s)^a(.))((?m)^b$)" []+ ["a\nb\nc\n"]+ [Just ["a\nb", "a\n", "\n", "b"]]+ ,+++ testRegex "((?m)^b$)" []+ ["a\nb\nc\n"]+ [Just ["b", "b"]]+ ,+++ testRegex "(?m)^b" []+ ["a\nb\n"]+ [Just ["b"]]+ ,+++ testRegex "(?m)^(b)" []+ ["a\nb\n"]+ [Just ["b", "b"]]+ ,+++ testRegex "((?m)^b)" []+ ["a\nb\n"]+ [Just ["b", "b"]]+ ,+++ testRegex "\\n((?m)^b)" []+ ["a\nb\n"]+ [Just ["\nb", "b"]]+ ,+++ testRegex "((?s).)c(?!.)" []+ ["a\nb\nc\n",+ "a\nb\nc\n"]+ [Just ["\nc", "\n"],+ Just ["\nc", "\n"]]+ ,+++ testRegex "((?s)b.)c(?!.)" []+ ["a\nb\nc\n",+ "a\nb\nc\n"]+ [Just ["b\nc", "b\n"],+ Just ["b\nc", "b\n"]]+ ,+++ testRegex "^b" []+ []+ []+ ,+++ testRegex "()^b" []+ ["*** Failers",+ "a\nb\nc\n",+ "a\nb\nc\n"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "((?m)^b)" []+ ["a\nb\nc\n"]+ [Just ["b", "b"]]+ ,++{-+ testRegex "(?(1)a|b)" []+ []+ []+ ,+++ testRegex "(?(1)b|a)" []+ ["a"]+ [Just ["a"]]+ ,++-}++ testRegex "(x)?(?(1)a|b)" []+ ["*** Failers",+ "a",+ "a"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(x)?(?(1)b|a)" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "()?(?(1)b|a)" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "()(?(1)b|a)" []+ []+ []+ ,+++ testRegex "()?(?(1)a|b)" []+ ["a"]+ [Just ["a", ""]]+ ,+++ testRegex "^(\\()?blah(?(1)(\\)))$" []+ ["(blah)",+ "blah",+ "a",+ "blah)",+ "(blah"]+ [Just ["(blah)", "(", ")"],+ Just ["blah"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "^(\\(+)?blah(?(1)(\\)))$" []+ ["(blah)",+ "blah",+ "*** Failers",+ "blah)",+ "(blah"]+ [Just ["(blah)", "(", ")"],+ Just ["blah"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(?(?!a)a|b)" []+ []+ []+ ,+++ testRegex "(?(?!a)b|a)" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "(?(?=a)b|a)" []+ ["*** Failers",+ "a",+ "a"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(?(?=a)a|b)" []+ ["a"]+ [Just ["a"]]+ ,+++ testRegex "(?=(a+?))(\\1ab)" []+ ["aaab"]+ [Just ["aab", "a", "aab"]]+ ,+++ testRegex "^(?=(a+?))\\1ab" []+ []+ []+ ,+++ testRegex "(\\w+:)+" []+ ["one:"]+ [Just ["one:", "one:"]]+ ,+++ testRegex "$(?<=^(a))" []+ ["a"]+ [Just ["", "a"]]+ ,+++ testRegex "(?=(a+?))(\\1ab)" []+ ["aaab"]+ [Just ["aab", "a", "aab"]]+ ,+++ testRegex "^(?=(a+?))\\1ab" []+ ["*** Failers",+ "aaab",+ "aaab"]+ [Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "([\\w:]+::)?(\\w+)$" []+ ["abcd",+ "xy:z:::abcd"]+ [Just ["abcd", "", "abcd"],+ Just ["xy:z:::abcd", "xy:z:::", "abcd"]]+ ,+++ testRegex "^[^bcd]*(c+)" []+ ["aexycd"]+ [Just ["aexyc", "c"]]+ ,+++ testRegex "(a*)b+" []+ ["caab"]+ [Just ["aab", "aa"]]+ ,+++ testRegex "([\\w:]+::)?(\\w+)$" []+ ["abcd",+ "xy:z:::abcd",+ "*** Failers",+ "abcd:",+ "abcd:"]+ [Just ["abcd", "", "abcd"],+ Just ["xy:z:::abcd", "xy:z:::", "abcd"],+ Just ["Failers", "", "Failers"],+ Nothing,+ Nothing]+ ,+++ testRegex "^[^bcd]*(c+)" []+ ["aexycd"]+ [Just ["aexyc", "c"]]+ ,+++ testRegex "(>a+)ab" []+ []+ []+ ,+++ testRegex "(?>a+)b" []+ ["aaab"]+ [Just ["aaab"]]+ ,+++ testRegex "([[:]+)" []+ ["a:[b]:"]+ [Just [":[", ":["]]++ ,+ testRegex "([[=]+)" []+ ["a=[b]="]+ [Just ["=[", "=["]]+ ,+++ testRegex "([[.]+)" []+ ["a.[b]."]+ [Just [".[", ".["]]+ ,+++ testRegex "((?>a+)b)" []+ ["aaab"]+ [Just ["aaab", "aaab"]]+ ,+++ testRegex "(?>(a+))b" []+ ["aaab"]+ [Just ["aaab", "aaa"]]+ ,+++ testRegex "((?>[^()]+)|\\([^()]*\\))+" []+ ["((abc(ade)ufh()()x"]+ [Just ["abc(ade)ufh()()x", "x"]]+ ,+++ testRegex "a\\Z" []+ ["aaab",+ "a\nb\n"]+ [Nothing,+ Nothing]+ ,+++ testRegex "b\\Z" []+ ["a\nb\n"]+ [Just ["b"]]+ ,+++ testRegex "b\\z" []+ []+ []+ ,+++ testRegex "b\\Z" []+ ["a\\nb"]+ [Just ["b"]]+ ,++ testRegex "(?>.*)(?<=(abcd|wxyz))" []+ ["alphabetabcd",+ "endingwxyz",+ "*** Failers",+ "a rather long string that doesn't end with one of them"]+ [Just ["alphabetabcd", "abcd"],+ Just ["endingwxyz", "wxyz"],+ Nothing,+ Nothing]+ ,+++ testRegex "word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword" []+ ["word cat dog elephant mussel cow horse canary baboon snake shark otherword",+ "word cat dog elephant mussel cow horse canary baboon snake shark"+ ]+ [Just ["word cat dog elephant mussel cow horse canary baboon snake shark otherword"],+ Nothing]+ ,++ testRegex "((Z)+|A)*" []+ ["ZABCDEFG"]+ [Just ["ZA", "A", "Z"]]+ ,+++ testRegex "(Z()|A)*" []+ ["ZABCDEFG"]+ [Just ["ZA", "A", ""]]+ ,+++ testRegex "(Z(())|A)*" []+ ["ZABCDEFG"]+ [Just ["ZA", "A", "", ""]]+ ,++ testRegex "((?>Z)+|A)*" []+ ["ZABCDEFG"]+ [Just ["ZA", "A"]]+ ,+++ testRegex "((?>)+|A)*" []+ ["ZABCDEFG"]+ [Just ["", ""]]+ ,++ testRegex "\\Qabc\\$xyz\\E" []+ ["abc\\$xyz"]+ [Just ["abc\\$xyz"]]+ ,+ testRegex "\\Qabc\\E\\$\\Qxyz\\E" []+ ["abc$xyz"]+ [Just ["abc$xyz"]]+ ,+ testRegex "\\Gabc" []+ ["abc",+ "*** Failers",+ "xyzabc "]+ [Just ["abc"],+ Nothing,+ Nothing]+ ,++ testRegex "a(?x: b c )d" []+ ["XabcdY",+ "*** Failers ",+ "Xa b c d Y "]+ [Just ["abcd"],+ Nothing,+ Nothing]+ ,+++ testRegex "((?x)x y z | a b c)" []+ ["XabcY",+ "AxyzB "]+ [Just ["abc", "abc"],+ Just ["xyz", "xyz"]]+ ,+++ testRegex "(?i)AB(?-i)C" []+ ["XabCY",+ "*** Failers",+ "XabcY "]+ [Just ["abC"],+ Nothing,+ Nothing]+ ,+++ testRegex "((?i)AB(?-i)C|D)E" []+ ["abCE",+ "DE",+ "*** Failers",+ "abcE",+ "abCe ",+ "dE",+ "De "]+ [Just ["abCE", "abC"],+ Just ["DE", "D"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(.*)\\d+\\1" []+ ["abc123abc",+ "abc123bc "]+ [Just ["abc123abc", "abc"],+ Just ["bc123bc", "bc"]]+ ,++ testRegex "[z\\Qa-d]\\E]" []+ ["z",+ "a",+ "-",+ "d",+ "] ",+ "*** Failers",+ "b "]+ [Just ["z"],+ Just ["a"],+ Just ["-"],+ Just ["d"],+ Just ["]"],+ Just ["a"],+ Nothing]++ , testRegex "(?<=Z)X." []+ ["\\x84XAZXB"]+ [Just ["XB"]]+ ,++ testRegex "ab cd (?x) de fg" []+ ["ab cd defg"]+ [Just ["ab cd defg"]]+ ,+++ testRegex "ab cd(?x) de fg" []+ ["ab cddefg",+ "** Failers ",+ "abcddefg"]+ [Just ["ab cddefg"],+ Nothing,+ Nothing]+ ,+++ testRegex "(?<![^f]oo)(bar)" []+ ["foobarX ",+ "** Failers ",+ "boobarX"]+ [Just ["bar", "bar"],+ Nothing,+ Nothing]+ ,+++ testRegex "(?<![^f])X" []+ ["offX",+ "** Failers",+ "onyX "]+ [Just ["X"],+ Nothing,+ Nothing]+ ,+++ testRegex "(?<=[^f])X" []+ ["onyX",+ "** Failers",+ "offX "]+ [Just ["X"],+ Nothing,+ Nothing]+ ,++++ testRegex "(?:(?(1)a|b)(X))+" []+ ["bXaX"]+ [Just ["bXaX", "X"]]+ ,++ testRegex "(?:(?(1)\\1a|b)(X|Y))+" []+ ["bXXaYYaY",+ "bXYaXXaX "]+ [Just ["bXXaYYaY", "Y"],+ Just ["bX", "X"]]+ ,+++ testRegex "()()()()()()()()()(?:(?(10)\\10a|b)(X|Y))+" []+ ["bXXaYYaY"]+ [Just ["bX", "", "", "", "", "", "", "", "", "", "X"]]+ ,+++ testRegex "[[,abc,]+]" []+ ["abc]",+ "a,b]",+ "[a,b,c] "]+ [Just ["abc]"],+ Just ["a,b]"],+ Just ["[a,b,c]"]]+ ,+++++ testRegex "a*b*\\w" []+ ["aaabbbb",+ "aaaa",+ "a"]+ [Just ["aaabbbb"],+ Just ["aaaa"],+ Just ["a"]]+ ,+++ testRegex "a*b?\\w" []+ ["aaabbbb",+ "aaaa",+ "a"]+ [Just ["aaabb"],+ Just ["aaaa"],+ Just ["a"]]+ ,+++ testRegex "a*b{0,4}\\w" []+ ["aaabbbb",+ "aaaa",+ "a"]+ [Just ["aaabbbb"],+ Just ["aaaa"],+ Just ["a"]]+ ,+++ testRegex "(?=(\\w+))\\1:" []+ ["abcd:"]+ [Just ["abcd:", "abcd"]]+ ,+++ testRegex "^(?=(\\w+))\\1:" []+ ["abcd:"]+ [Just ["abcd:", "abcd"]]+ ,++++ testRegex "^[a\\E\\E-\\Ec]" []+ ["b",+ "** Failers",+ "-",+ "E "]+ [Just ["b"],+ Nothing,+ Nothing,+ Nothing]+ ,+++ testRegex "(a){0,3}(?(1)b|(c|))*D" []+ ["abbD",+ "ccccD",+ "D "]+ [Just ["abbD", "a"],+ Just ["ccccD", "", ""],+ Just ["D", "", ""]]+ ,+++ -- WARNING: at around this point, the file starts segfaulting ghci....+ testRegex "(a|)*\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]+ [Nothing,+ Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4", ""]]++ ,+ testRegex "(?>a|)*\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]+ [Nothing,+ Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]]++ ,++ testRegex "(?=(\\w+))\\1:" []+ ["abcd:"]+ [Just ["abcd:", "abcd"]]+ ,+++ testRegex "^(?=(\\w+))\\1:" []+ ["abcd:"]+ [Just ["abcd:", "abcd"]]+ ,++++ testRegex "^[a\\E\\E-\\Ec]" []+ ["b",+ "** Failers",+ "-",+ "E "]+ [Just ["b"],+ Nothing,+ Nothing,+ Nothing]+ ,++++++++ testRegex "(a){0,3}(?(1)b|(c|))*D" []+ ["abbD",+ "ccccD",+ "D "]+ [Just ["abbD", "a"],+ Just ["ccccD", "", ""],+ Just ["D", "", ""]]+ ,+++ testRegex "(a|)*\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]+ [Nothing,+ Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4", ""]]+ ,+++ testRegex "(?>a|)*\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]+ [Nothing,+ Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]]+ ,++ testRegex "( (A | (?(1)0|) )* )" [extended]+ ["abcd"]+ [Just ["", "", ""]]++ ,+ testRegex "^[\\w]+" []+ ["*** Failers",+ "\201cole"]+ [Nothing,+ Nothing]++++ ,+ testRegex "^[\\w]+" []+ ["*** Failers",+ "\201cole"]+ [Nothing,+ Nothing]++{-+ ,++ testRegex "(a.b(?s)c.d|x.y)p.q" []+ ["a+bc+dp+q",+ "a+bc\ndp+q",+ "x\nyp+q ",+ "a\nbc\ndp+q",+ "a+bc\ndp\nq",+ "x\nyp\nq "+ ]+ [Just ["a+bc+dp+q"],+ Just ["a+bc\ndp+q"],+ Just ["x\nyp+q"],+ Nothing,+ Nothing,+ Nothing+ ]+ -}++ ,+ testRegex "a\\d\\z" []+ ["ba0",+ "*** Failers",+ "ba0\n",+ "ba0\ncd "]+ [Just ["a0"],+ Nothing,+ Nothing,+ Nothing]++ ,+ testRegex "a\\d\\Z" []+ ["ba0",+ "ba0\n",+ "ba0\ncd "]+ [Just ["a0"],+ Just ["a0"],+ Nothing]++ ,+ testRegex "a\\d$" []+ ["ba0",+ "ba0\n",+ "*** Failers",+ "ba0\ncd "]+ [Just ["a0"],+ Just ["a0"],+ Nothing,+ Nothing]+ ,+ testRegex "a+" []+ ["aaaa"]+ [Just ["aaaa"]]++++ ,+ testRegex "^\\d{2,3}X" []+ ["12X",+ "123X",+ "*** Failers",+ "X",+ "1X",+ "1234X "]+ [Just ["12X"],+ Just ["123X"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]+++ ,+ testRegex "^[abcd]\\d" []+ ["a45",+ "b93",+ "c99z",+ "d04",+ "*** Failers",+ "e45",+ "abcd ",+ "abcd1234",+ "1234 "]+ [Just ["a4"],+ Just ["b9"],+ Just ["c9"],+ Just ["d0"],+ Nothing,+ Nothing,+ Nothing,+ Nothing,+ Nothing]+++{-+ ,+ testRegex "^(a*\\w|ab)=(a*\\w|ab)" []+ ["ab=ab"]+ [Just ["ab=ab", "ab"]]+ -}+++ ,+ testRegex "^(a*\\w|ab)=(?1)" []+ ["ab=ab"]+ [Just ["ab=ab", "ab"]]+++{-+ ,+ testRegex "^([^()]|\\((?1)*\\))*$" []+ ["abc",+ "a(b)c",+ "a(b(c))d ",+ "*** Failers)",+ "a(b(c)d "]+ [Just ["abc"],+ Just ["a(b)c"],+ Just ["a(b(c))d"],+ Nothing,+ Nothing]++ ,+ testRegex "^>abc>([^()]|\\((?1)*\\))*<xyz<$" []+ [">abc>123<xyz<",+ ">abc>1(2)3<xyz<",+ ">abc>(1(2)3)<xyz<"]+ [Just [">abc>123<xyz<"],+ Just [">abc>1(2)3<xyz<"],+ Just [">abc>(1(2)3)<xyz<"]]++-}++ ,+ testRegex "^(?>a*)\\d" []+ ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876",+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]+ [Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9"],+ Nothing]++++++ ,+ testRegex "(?<=abc|xy)123" []+ ["abc12345",+ "wxy123z",+ "*** Failers",+ "123abc"]+ [Just ["123"],+ Just ["123"],+ Nothing,+ Nothing]+++ ,+ testRegex "(?<!abc|xy)123" []+ ["123abc",+ "mno123456 ",+ "*** Failers",+ "abc12345",+ "wxy123z"]+ [Just ["123"],+ Just ["123"],+ Nothing,+ Nothing,+ Nothing]++ ,+ testRegex "abc(?C1)xyz" []+ ["abcxyz",+ "123abcxyz999 "]+ [ Just ["abcxyz"],+ Just ["abcxyz"]]++++++{-+ ,+ testRegex "\\Gabc" []+ ["abcdef",+ "defabcxyz\\>3 ",+ "defabcxyz"]+ [Just ["abc"],+ Just ["abc"],+ Nothing]+ -}++ ,++ testRegex "[\\xFF]" []+ [">\xff<"]+ [Just ["\xff"]]++ ,+ testRegex "[^\\xFF]" []+ ["XYZ"]+ [Just ["X"]]+++ ,+ testRegex "^\\pN{2,3}X" []+ ["12X",+ "123X",+ "*** Failers",+ "X",+ "1X",+ "1234X "]+ [Just ["12X"],+ Just ["123X"],+ Nothing,+ Nothing,+ Nothing,+ Nothing]++ -- named capture group tests+ , -- Handles cases with no capture groups+ testCaptures 0 "no capture groups" []++ , -- Properly labels capture groups+ testCaptures 1 "(?<first>first capture group)" [("first", 0)]++ , -- Doesn't return labels for unnamed groups+ testCaptures 1 "(doesn't return unnamed groups)" []++ , -- Counts but doesn't return unnamed groups+ testCaptures 3 "(?<one>abc) (def) (?<three>ghi)" [("one", 0), ("three", 2)]++ , -- Doesn't count non-capturing groups+ testCaptures 1 "(?:abc) (?<named>def)" [("named", 0)]++ , -- Doesn't count named back-references+ testCaptures 2 "(?<first>abc) (?P=first) (?<second>def)" [("first", 0), ("second", 1)]++ , -- Test alternate group naming syntaxes+ testCaptures 3 "(?'first'abc) (?P<second>def) (?<third>ghi)" [("first", 0), ("second", 1), ("third", 2)]++ , -- Groups are returned in numeric order+ testCaptures 3 "(?'c'0) (?P<b>1) (?<a>2)" [("c", 0), ("b", 1), ("a", 2)]++ , -- Handles alternation between groups+ testCaptures 2 "(?<optionA>abc)|(?<optionB>def)" [("optionA", 0), ("optionB", 1)]++ , -- Labels optional groups+ testCaptures 2 "(?<named>abc)(?<optional>def)?" [("named", 0), ("optional", 1)]++ , -- Handles nested named groups+ testCaptures 3 "(?<named>a(?<nested>b)c) (?<unnested>d)" [("named", 0), ("nested", 1), ("unnested", 2)]++ , testLabel "compile failure on duplicate named groups" $+ TestCase $ (assertEqual' "compile failure on duplicate named groups"+ (Left ("two named subpatterns have the same name"))+ (compileM "(?<dup>abc) (?<dup>def)" []))++ ]