pcre-less 0.2.0 → 0.2.1
raw patch · 5 files changed
+177/−43 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Text.Regex.Less: matchN :: Match -> Int -> Match
+ Text.Regex.Less: subg :: Match -> String -> String
+ Text.Regex.Less.Quackers: class QLR a
+ Text.Regex.Less.Quackers: compile :: QLR a => a -> Regex
+ Text.Regex.Less.Quackers: execute :: QLR a => a -> String -> [MatchArray]
+ Text.Regex.Less.Quackers: instance QLR ((String, [RECtOpts]), [RERtOpts])
+ Text.Regex.Less.Quackers: instance QLR ((String, [RERtOpts]), [RECtOpts])
+ Text.Regex.Less.Quackers: instance QLR (String, ([RECtOpts], [RERtOpts]))
+ Text.Regex.Less.Quackers: instance QLR (String, ([RERtOpts], [RECtOpts]))
+ Text.Regex.Less.Quackers: instance QLR (String, [RECtOpts])
+ Text.Regex.Less.Quackers: instance QLR (String, [RERtOpts])
+ Text.Regex.Less.Quackers: instance QLR String
- Text.Regex.Less: (=~) :: (QLR a) => String -> a -> Result
+ Text.Regex.Less: (=~) :: QLR a => String -> a -> Match
- Text.Regex.Less: bref :: Result -> Int -> String
+ Text.Regex.Less: bref :: Match -> Int -> String
- Text.Regex.Less: derefs :: Result -> String -> String
+ Text.Regex.Less: derefs :: (Int -> String) -> String -> String
- Text.Regex.Less: subs :: Result -> String -> String
+ Text.Regex.Less: subs :: Match -> String -> String
- Text.Regex.Less: truth :: Result -> Bool
+ Text.Regex.Less: truth :: Match -> Bool
Files
- Text/Regex/Less.hs +55/−19
- Text/Regex/Less/Quackers.hs +15/−18
- pcre-less.cabal +8/−6
- test/HU.hs +86/−0
- test/QC.hs +13/−0
Text/Regex/Less.hs view
@@ -1,46 +1,82 @@ {- copyright (c) sreservoir. license bsd three-clause. -} -module Text.Regex.Less ((=~),(<<),truth,subs,derefs,bref) where+module Text.Regex.Less+ ( (=~),(<<),+ truth,subs,subg,derefs,bref,matchN)+ where import qualified Text.Regex.PCRE as R-import qualified Data.Array as A+import qualified Data.Array.IArray as A import Text.Regex.Less.Quackers -type Result = (String,[R.MatchArray])+type Match = (String,[R.MatchArray]) -- standard usage:- -- "" =~ ""- -- "" =~ "" << RECtOpts- -- "" =~ "" << RERtOpts- -- "" =~ "" << RECtOpts << RERtOpts--- value suitable for use below.+-- "" =~ ""+-- "" =~ "" << [RECtOpts]+-- "" =~ "" << [RERtOpts]+-- "" =~ "" << [RECtOpts] << RERtOpts+-- value is suitable for use below. infixl 4 =~-(=~) :: QLR a => String -> a -> Result-a =~ b = a << R.matchAll (compile b) a+(=~) :: QLR a => String -> a -> Match+a =~ b = a << execute b a +-- (a << b) = (a,b) infixl 5 << (<<) :: a -> b -> (a,b) a << b = (a,b) -truth :: Result -> Bool+-- whether the match succeeded.+truth :: Match -> Bool truth (_,a) = not (null a) -subs :: Result -> String -> String-subs a b = s ++ derefs a b ++ f+-- replaces matched substring with supplied string.+-- supplied string is passed through derefs first.+subs :: Match -> String -> String+subs a b = s ++ derefs (bref a) b ++ f where o = fst a (i,c) = head (snd a) A.! 0 (s,r) = splitAt i o f = drop c r -derefs :: Result -> String -> String-derefs a ('^':'^':bs) = '^' : derefs a bs-derefs a ('^':bs) =+-- as subs, to every match.+subg :: Match -> String -> String+subg a b = subg' o (decay (map A.elems m)) b+ where (o,m) = a++-- for each match part, does just what it needs.+-- if there are more, repeat with the rest.+subg' :: String -> [[(Int,Int)]] -> String -> String+subg' ors (cur@((ini,chs):_):ms) sub =+ take ini ors ++ derefs bref' sub+ ++ subg' (drop (ini + chs) ors) ms sub+ where bref' a = R.extract (cur !! a) ors+subg' _ _ _ = []++-- reduces offset by number used by the previous.+decay :: [[(Int,Int)]] -> [[(Int,Int)]]+decay (x:xs) = x : decay rest+ where rest = map (map proc) xs+ proc (a,b) = a - uncurry (+) (head x) << b+decay [] = []+ +-- does backreferences with ` .+derefs :: (Int -> String) -> String -> String+derefs f ('`':'`':bs) = '`' : derefs f bs+derefs f ('`':'.':bs) = derefs f bs+derefs f ('`':bs) = case reads bs of- [(c,d)] -> bref a c ++ derefs a d+ [(c,d)] -> f c ++ derefs f d _ -> undefined-derefs a (b:bs) = b : derefs a bs+derefs f (b:bs) = b : derefs f bs derefs _ [] = [] -bref :: Result -> Int -> String+-- returns the indexed substring.+-- backref 0 is the entire match.+bref :: Match -> Int -> String bref a i = R.extract (head (snd a) A.! i) (fst a)++-- takes one of the matches.+matchN :: Match -> Int -> Match+matchN (a,b) i = (a,[b !! i])
Text/Regex/Less/Quackers.hs view
@@ -8,38 +8,35 @@ import qualified Text.Regex.PCRE as R import Text.Regex.Less.REOpts --- the QLR (QuacksLikeRegex) class:- -- compile--- instances of QLR:- -- String- -- (String,[RECtOpts])- -- (String,[RERtOpts])- -- (String,([RECtOpts],[RERtOpts]))- -- (String,([RERtOpts],[RECtOpts]))- -- ((String,[RECtOpts]),[RERtOpts])- -- ((String,[RERtOpts]),[RECtOpts])+bsR :: String -> String+bsR ('`':'`':cs) = '`' : bsR cs+bsR ('`':cs) = '\\' : bsR cs+bsR ('\\':cs) = "\\\\" ++ bsR cs+bsR (c:cs) = c : bsR cs+bsR [] = [] --- QuacksLikeRegex: can =~ . class QLR a where compile :: a -> R.Regex+ execute :: a -> String -> [R.MatchArray]+ execute a b = R.matchAll (compile a) b instance QLR String where- compile a = R.makeRegexOpts (reCtOpts []) (reRtOpts []) a+ compile a = R.makeRegexOpts (reCtOpts []) (reRtOpts []) (bsR a) instance QLR (String,[RECtOpts]) where- compile (a,b) = R.makeRegexOpts (reCtOpts b) (reRtOpts []) a+ compile (a,b) = R.makeRegexOpts (reCtOpts b) (reRtOpts []) (bsR a) instance QLR (String,[RERtOpts]) where- compile (a,b) = R.makeRegexOpts (reCtOpts []) (reRtOpts b) a+ compile (a,b) = R.makeRegexOpts (reCtOpts []) (reRtOpts b) (bsR a) instance QLR ((String,[RECtOpts]),[RERtOpts]) where- compile ((a,b),c) = R.makeRegexOpts (reCtOpts b) (reRtOpts c) a+ compile ((a,b),c) = R.makeRegexOpts (reCtOpts b) (reRtOpts c) (bsR a) instance QLR ((String,[RERtOpts]),[RECtOpts]) where- compile ((a,b),c) = R.makeRegexOpts (reCtOpts c) (reRtOpts b) a+ compile ((a,b),c) = R.makeRegexOpts (reCtOpts c) (reRtOpts b) (bsR a) instance QLR (String,([RECtOpts],[RERtOpts])) where- compile (a,(b,c)) = R.makeRegexOpts (reCtOpts b) (reRtOpts c) a+ compile (a,(b,c)) = R.makeRegexOpts (reCtOpts b) (reRtOpts c) (bsR a) instance QLR (String,([RERtOpts],[RECtOpts])) where- compile (a,(b,c)) = R.makeRegexOpts (reCtOpts c) (reRtOpts b) a+ compile (a,(b,c)) = R.makeRegexOpts (reCtOpts c) (reRtOpts b) (bsR a)
pcre-less.cabal view
@@ -1,26 +1,28 @@ name: pcre-less-version: 0.2.0-synopsis: Nicer interface to regex-pcre+version: 0.2.1+synopsis: Nicer interface to regex-pcre. description:- Unfortunately, docs don't exist yet.-homepage: ~+ Uses regex-pcre to provide substitution, backrefs.+ Uses '`' over '\\' just to be idiosyncratic. (It's prettier.)+ See the tests for more information.+-- homepage: ~ license: BSD3--- The file containing the license text. license-file: LICENSE author: sreservoir maintainer: sreservoir@gmail.com category: Text build-type: Simple cabal-version: >= 1.2+extra-source-files: test/QC.hs, test/HU.hs library exposed-modules: Text.Regex.Less Text.Regex.Less.REOpts+ Text.Regex.Less.Quackers other-modules: Text.Regex.Less.RECtOpts Text.Regex.Less.RERtOpts- Text.Regex.Less.Quackers build-depends: base >= 4 && < 5,regex-pcre >= 0.94,array >= 0.3 extensions: FlexibleInstances,TypeSynonymInstances ghc-options: -Wall
+ test/HU.hs view
@@ -0,0 +1,86 @@+{- copyright (c) sreservoir.+ licensed under mit (x11). -}++module Main where++import Text.Regex.Less+import Data.List+import Test.HUnit++main :: IO ()+main = mapM_ runTestTT tests++tests :: [Test]+tests = map TestList+ [ tests0, tests1, tests2, tests3,+ tests4, tests5, tests6, tests7 ]++tests0 :: [Test]+tests0 =+ [ TestLabel "sanity" $+ TestCase (assertEqual "" (a+a) (2*a))+ | a <- [ 1,19 .. 963 ] :: [Int] ]++alnums :: [Char]+alnums = '_' : ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9']++tests1 :: [Test]+tests1 =+ [ TestLabel "alnum `w" $+ TestCase (assertBool (show a ++ " not `w?")+ (truth ([a] =~ "`w")))+ | a <- alnums ]++tests2 :: [Test]+tests2 =+ [ TestLabel "alnum not `W" $+ TestCase (assertBool (show a ++ " is `W?") + (not (truth ([a] =~ "`W"))))+ | a <- alnums ]++tests3 :: [Test]+tests3 =+ [ TestLabel "other `W" $+ TestCase (assertBool (show a ++ " not `W?") + (truth ([a] =~ "`W")))+ | a <- ['\0'..'\DEL'] \\ alnums ]++tests4 :: [Test]+tests4 =+ [ TestLabel "other not `w" $+ TestCase (assertBool (show a ++ " is `w?") + (not (truth ([a] =~ "`w"))))+ | a <- ['\0'..'\DEL'] \\ alnums ]++prints :: [Char]+prints = [' '..'~']++tests5 :: [Test]+tests5 =+ [ TestLabel "simple once-substitution" $+ TestCase (assertEqual "doubling"+ (subs (a =~ ".*") "`0`0")+ (a ++ a))+ | b <- prints, c <- prints, a <- [[b,c]] ]++tests6 :: [Test]+tests6 =+ [ TestLabel "extracting numbers" $+ TestCase (assertEqual "numbers"+ (read (bref (fst a =~ "`d*") 0))+ (snd a))+ | b <- [ 1,1000 .. 100000 ] :: [Integer], a <- [(show b,b)] ]++tests7 :: [Test]+tests7 =+ [ TestLabel "testing primes :P" $+ TestCase (assertEqual "primes"+ (snd a)+ (truth (replicate (fst a) '1' =~ "^1?$|^(11+?)`1+$")))+ | a <- [( 2,False),( 3,False),( 4, True),( 5,False),+ ( 6, True),( 7,False),( 8, True),( 9, True),+ (10, True),(11,False),(12, True),(13,False),+ (14, True),(15, True),(16, True),(17,False),+ (18, True),(19,False),(20, True),(21, True),+ (22, True),(23,False),(24, True),(25, True),+ (26, True),(27, True),(28, True),(29,False)] ]
+ test/QC.hs view
@@ -0,0 +1,13 @@+{- copyright (c) sreservoir.+ licensed under mit (x11). -}++module Main where++import Text.Regex.Less+import Test.QuickCheck++main :: IO ()+main = do+ putStr "all strings match null: " >> quickCheck matchEmpty++matchEmpty a = truth (a =~ "")