packages feed

regex-pderiv 0.0.9 → 0.1.0

raw patch · 10 files changed

+240/−82 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.Regex.PDeriv.Common: class IsEmpty a
- Text.Regex.PDeriv.Common: isEmpty :: IsEmpty a => a -> Bool
- Text.Regex.PDeriv.RE: instance IsEmpty RE
+ Text.Regex.PDeriv.Common: class IsEpsilon a
+ Text.Regex.PDeriv.Common: class IsPhi a
+ Text.Regex.PDeriv.Common: class PosEpsilon a
+ Text.Regex.PDeriv.Common: class Simplifiable a
+ Text.Regex.PDeriv.Common: isEpsilon :: IsEpsilon a => a -> Bool
+ Text.Regex.PDeriv.Common: isPhi :: IsPhi a => a -> Bool
+ Text.Regex.PDeriv.Common: posEpsilon :: PosEpsilon a => a -> Bool
+ Text.Regex.PDeriv.Common: simplify :: Simplifiable a => a -> a
+ Text.Regex.PDeriv.IntPattern: instance IsEpsilon Pat
+ Text.Regex.PDeriv.IntPattern: instance IsPhi Pat
+ Text.Regex.PDeriv.IntPattern: instance Simplifiable Pat
+ Text.Regex.PDeriv.IntPattern: pdPat0Sim :: Pat -> Letter -> [(Pat, Int -> Binder -> Binder)]
+ Text.Regex.PDeriv.RE: instance IsEpsilon RE
+ Text.Regex.PDeriv.RE: instance IsPhi RE
+ Text.Regex.PDeriv.RE: instance PosEpsilon RE
+ Text.Regex.PDeriv.RE: instance Simplifiable RE

Files

Text/Regex/PDeriv/ByteString/LeftToRight.lhs view
@@ -34,8 +34,8 @@  > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Pretty (Pretty(..))-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), my_hash, my_lookup, GFlag(..), IsEmpty(..), nub2, preBinder, mainBinder, subBinder)-> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, toBinder, Binder(..), strip, listifyBinder)+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), Simplifiable(..), my_hash, my_lookup, GFlag(..), nub2, preBinder, mainBinder, subBinder)+> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, pdPat0Sim, toBinder, Binder(..), strip, listifyBinder) > import Text.Regex.PDeriv.Parse > import qualified Text.Regex.PDeriv.Dictionary as D (Dictionary(..), Key(..), insertNotOverwrite, lookupAll, empty, isIn, nub) @@ -71,7 +71,7 @@ >     let sig = map (\x -> (x,0)) (sigmaRE (strip init))         -- the sigma >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty         -- add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   -- all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                   -- the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                   -- the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         lists = [ (i,l,jfs) |  >                   (p,l, qfs) <- delta, @@ -312,7 +312,7 @@ >     Left err -> Left ("parseRegex for Text.Regex.PDeriv.ByteString failed:"++show err) >     Right pat -> Right (patToRegex pat compOpt execOpt) >     where ->       patToRegex p _ _ = Regex (compilePat p)+>       patToRegex p _ _ = Regex (compilePat $ simplify p)   
Text/Regex/PDeriv/ByteString/LeftToRightD.lhs view
@@ -27,6 +27,10 @@ > import qualified Data.ByteString.Char8 as S > import Control.DeepSeq +> -- import Control.Parallel +> -- import Control.Parallel.Strategies hiding (Seq)++ > import System.IO.Unsafe (unsafePerformIO)  > import Text.Regex.Base(RegexOptions(..))@@ -34,8 +38,8 @@  > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Pretty (Pretty(..))-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), my_hash, my_lookup, GFlag(..), IsEmpty(..), nub2, preBinder, mainBinder, subBinder)-> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, toBinder, Binder(..), strip, listifyBinder)+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), Simplifiable(..), my_hash, my_lookup, GFlag(..), nub2, preBinder, mainBinder, subBinder)+> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, pdPat0Sim, toBinder, Binder(..), strip, listifyBinder) > import Text.Regex.PDeriv.Parse > import qualified Text.Regex.PDeriv.Dictionary as D (Dictionary(..), Key(..), insert, insertNotOverwrite, lookupAll, empty, isIn, nub) @@ -71,7 +75,7 @@ >     let sig = map (\x -> (x,0)) (sigmaRE (strip init))                              -- the sigma >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty             -- add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   -- all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                       -- the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                       -- the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         lists = [ (i,l,jfs) |  >                   (p,l, qfs) <- delta, @@ -112,7 +116,7 @@ >     | otherwise =  >         let  >             all_sofar_states = acc_states ++ curr_states->             new_delta = [ (s, l, sfs) | s <- curr_states, l <- sig, let sfs = pdPat0 s l]+>             new_delta = [ (s, l, sfs) | s <- curr_states, l <- sig, let sfs = pdPat0Sim s l] >             new_states = all_sofar_states `seq` D.nub [ s' | (_,_,sfs) <- new_delta, (s',f) <- sfs >                                                       , not (s' `D.isIn` dict) ] >             acc_delta_next  = (acc_delta ++ new_delta)@@ -142,7 +146,7 @@ >         -- building the NFA >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty             -- add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   -- all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                       -- the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                       -- the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         lists = dictionary `seq`  >                 [ (i,l,jfs) | @@ -282,20 +286,20 @@ > patMatchesIntStatePdPat1 cnt dStateTable  w' [] = [] > patMatchesIntStatePdPat1 cnt dStateTable  w' currNfaStateBinders = >     case {-# SCC "uncons" #-} S.uncons w' of ->       Nothing -> currNfaStateBinders+>       Nothing -> currNfaStateBinders -- we are done with the matching >       Just (l,w) -> ->           let ((i,_,_):_) = currNfaStateBinders+>           let ((i,_,_):_) = currNfaStateBinders  -- i is the current DFA state >               k           = {-# SCC "k" #-} l `seq` i `seq` my_hash i l >           in >           case k `seq` IM.lookup k dStateTable of->             { Nothing -> [] -- key miss means some letter exists in w but not in r.    +>             { Nothing -> [] -- "key missing" which means some letter exists in w but not in r.     >             ; Just (j,next_nfaStates,fDict) ->  >                 let --  >                     binders = {-# SCC "binders" #-} -- io `seq` >                               currNfaStateBinders `seq` fDict `seq`   >                               concatMap' ( \ (_,m,b) -> case IM.lookup m fDict of  >                                                        Nothing -> []->                                                        Just fs -> b `seq` map (\f -> f cnt b) fs ) currNfaStateBinders +>                                                        Just fs -> b `seq` fs `seq` map (\f -> f cnt b) fs ) currNfaStateBinders  >                     nextNfaStateBinders = {-# SCC "nextNfaStateBinders" #-} -- io `seq`  >                                           binders `seq` next_nfaStates `seq` j `seq` >                                           map (\(x,y) -> (j,x,y)) (zip next_nfaStates binders)@@ -303,9 +307,17 @@ >                 in nextNfaStateBinders `seq` cnt' `seq` w `seq` >                        patMatchesIntStatePdPat1 cnt' dStateTable w  nextNfaStateBinders }  +> {- > concatMap' :: (a -> [b]) -> [a] -> [b]+> concatMap' f x = reverse $ foldr ( \ b a -> (++) (f b) $! a) [] x                                +> -}++> +> concatMap' :: (a -> [b]) -> [a] -> [b] > concatMap' f x = foldr' ( \ b a -> (++) a $! (f b) ) [] x+>  + > foldr' :: (a -> b -> b) -> b -> [a] -> b > foldr' f b [] = b > foldr' f b (a:as) = let b' = f a b @@ -386,7 +398,7 @@ >     Left err -> Left ("parseRegex for Text.Regex.PDeriv.ByteString failed:"++show err) >     Right pat -> Right (patToRegex pat compOpt execOpt) >     where ->       patToRegex p _ _ = Regex (compilePat p)+>       patToRegex p _ _ = Regex (compilePat $ simplify p)   @@ -398,7 +410,7 @@ > regexec :: Regex      -- ^ Compiled regular expression >        -> S.ByteString -- ^ ByteString to match against >        -> Either String (Maybe (S.ByteString, S.ByteString, S.ByteString, [S.ByteString]))-> regexec (Regex r) bs =+> regexec (Regex r) bs = -- r `seq` Right Nothing >  case greedyPatMatchCompiled r bs of >    Nothing -> Right (Nothing) >    Just env ->@@ -413,7 +425,6 @@ >          main = case lookup mainBinder env of { Just w -> w ; Nothing -> S.empty } >          matched = map snd (filter (\(v,w) -> v > 0) env) >      in Right (Just (pre,main,post,matched))-  > -- | Control whether the pattern is multiline or case-sensitive like Text.Regex and whether to > -- capture the subgroups (\1, \2, etc).  Controls enabling extra anchor syntax.
Text/Regex/PDeriv/ByteString/Posix.lhs view
@@ -43,7 +43,7 @@  > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Pretty (Pretty(..))-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), my_hash, my_lookup, GFlag(..), IsEmpty(..), IsGreedy(..), preBinder, subBinder, mainBinder)+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), my_hash, my_lookup, GFlag(..), IsGreedy(..), preBinder, subBinder, mainBinder) > import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, toBinder, Binder(..), strip, listifyBinder) > import Text.Regex.PDeriv.Parse > import qualified Text.Regex.PDeriv.Dictionary as D (Dictionary(..), Key(..), insertNotOverwrite, lookupAll, empty, isIn, nub)@@ -82,7 +82,7 @@ >     let sig = map (\x -> (x,0)) (sigmaRE (strip init))         --  the sigma >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty         --  add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   --  all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                   --  the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                   --  the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         lists = delta `seq` dictionary `seq` [ (j, l, (i,f,flag,gf)) | (p,l,f,q,flag,gf) <- delta,  >                                                let i = mapping dictionary p  @@ -154,7 +154,7 @@ > lookupPdPat0' :: PdPat0TableRev -> (Int,Binder) -> Letter -> [(Int,Binder,Int,Bool)] > lookupPdPat0' hash_table (i,b) (l,x) =  >     case IM.lookup (my_hash i l) hash_table of->     Just quatripples -> [ (j, op x b, p, gf) | (j, op, p, gf) <- quatripples ]+>     Just quatripples -> [ b' `seq` (j, b', p, gf) | (j, op, p, gf) <- quatripples, let b' =  op x b ] >     Nothing -> []   > {- | map pattern variable to greedy flag@@ -314,12 +314,13 @@  a function that updates the binder given an index (that is the pattern var) ASSUMPTION: the  var index in the pattern is linear. e.g. no ( 0 :: R1, (1 :: R2, 2 :: R3))+The update start from the last pos of the input string, ending with the first pos of the input.  > updateBinderByIndex :: Int  >                     -> Int  >                     -> Binder  >                     -> Binder-> updateBinderByIndex i pos binder = +> updateBinderByIndex i pos binder = -- binder {- >     case IM.lookup i binder of >       { Nothing -> IM.insert i [(pos,pos+1)] binder >       ; Just ranges -> @@ -331,7 +332,7 @@ >           | pos < (b - 1) -> IM.update (\_ -> Just ((pos,pos+1):(b,e):rs)) i binder >           | otherwise     -> error ("impossible, the current letter position is greater than the last recorded letter" ++ show i ++ show pos ++ show (b,e)) >         }->       }+>       } -- -}  > {- > updateBinderByIndex :: Int    -- ^ pattern variable index@@ -421,11 +422,11 @@ >                      -- in [ (PPlus p' (PStar p), f) | (p', f) <- pfs ] > {- > pdPat0 (PPlus p1 p2@(PStar _)) l  -- we drop this case since it make difference with the PPair->        | isEmpty (strip p1) = [ (PPlus p3 p2, f) | (p3,f) <- pdPat0 p1 l ] ++ (pdPat0 p2 l) -- simply drop p1 since it is empty+>        | posEpsilon (strip p1) = [ (PPlus p3 p2, f) | (p3,f) <- pdPat0 p1 l ] ++ (pdPat0 p2 l) -- simply drop p1 since it is empty >        | otherwise = [ (PPlus p3 p2, f) | (p3,f) <- pdPat0 p1 l ]  > -} > pdPat0 (PPair p1 p2) l = ->     if (isEmpty (strip p1))+>     if (posEpsilon (strip p1)) >     then if isGreedy p1 >          then nub3 ([ (PPair p1' p2, f, True) | (p1' , f, _ ) <- pdPat0 p1 l ] ++ (pdPat0 p2 l)) >          else nub3 ((pdPat0 p2 l) ++ [ (PPair p1' p2, f, False) | (p1' , f, _) <- pdPat0 p1 l ])
Text/Regex/PDeriv/ByteString/RightToLeft.lhs view
@@ -31,8 +31,8 @@  > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Pretty (Pretty(..))-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), my_hash, my_lookup, GFlag(..), IsGreedy(..), nub3, preBinder, mainBinder, subBinder) -> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, toBinder, Binder(..), strip, listifyBinder)+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), Simplifiable(..), my_hash, my_lookup, GFlag(..), IsGreedy(..), nub3, preBinder, mainBinder, subBinder) +> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, pdPat0Sim, toBinder, Binder(..), strip, listifyBinder) > import Text.Regex.PDeriv.Parse > import qualified Text.Regex.PDeriv.Dictionary as D (Dictionary(..), Key(..), insertNotOverwrite, lookupAll, empty, isIn, nub) @@ -69,7 +69,7 @@ >     let sig = map (\x -> (x,0)) (sigmaRE (strip init))         -- the sigma >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty         -- add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   -- all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                   -- the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                   -- the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         lists = delta `seq` dictionary `seq` [ (j, l, (i,f,flag)) | (p,l,f,q,flag) <- delta,  >                                                let i = mapping dictionary p  @@ -119,7 +119,7 @@ >             (dict',max_id') = new_states `seq` foldl (\(d,id) p -> (D.insertNotOverwrite (D.hash p) (p,id) d, id + 1) ) (dict,max_id) new_states >         in {- dict' `seq` max_id' `seq` -} builder sig all_sofar_states acc_delta_next new_states dict' max_id'  -> pdPat0Flag p l = let qfs = pdPat0 p l+> pdPat0Flag p l = let qfs = pdPat0Sim p l >                  in case qfs of  >                       []        -> [] >                       [ (q,f) ] -> [ ((q,f),0) ] @@ -157,6 +157,18 @@   +> patMatchesIntStatePdPat0Rev'  :: Int -> PdPat0TableRev -> Word -> [(Int, [Binder -> Binder], Int)] -> [(Int, [Binder -> Binder], Int )]+> patMatchesIntStatePdPat0Rev'  cnt pdStateTableRev w fs =+>     case {-# SCC "myuncons" #-} S.uncons w of +>       Nothing -> fs+>       Just (l,w') -> +>           let +>               fs' = nub3 [ g `seq` (j, g, pri) | (i, f, _) <- fs, (j, f', pri) <- lookupPdPat0' pdStateTableRev i (l,cnt), let g = (f' cnt):f ]+>               cnt' = {-# SCC "cnt_minus_one" #-} cnt - 1+>           in fs' `seq` cnt' `seq` patMatchesIntStatePdPat0Rev' cnt' pdStateTableRev w' fs'+++ > patMatchIntStatePdPat0Rev :: Pat -> Word -> [Env] > patMatchIntStatePdPat0Rev p w =  >     let@@ -164,10 +176,12 @@ >         b = toBinder p >         l = S.length w >         w' = S.reverse w->         fs = [ (i, id, 0) | i <- fins ]->         fs' =  w' `seq` fins `seq` l `seq` pdStateTableRev `seq` (patMatchesIntStatePdPat0Rev (l-1) pdStateTableRev w' fs)->         -- fs'' = my_sort fs'->         allbinders = b `seq` [ (f b) | (s,f,_) <- fs', s == 0 ]+>         -- fs = [ (i, id, 0) | i <- fins ]+>         -- fs' =  w' `seq` fins `seq` l `seq` pdStateTableRev `seq` (patMatchesIntStatePdPat0Rev (l-1) pdStateTableRev w' fs)+>         -- allbinders = b `seq` [ (f b) | (s,f,_) <- fs', s == 0 ]+>         fs = [ (i, [], 0) | i <- fins ]+>         fs' =  w' `seq` fins `seq` l `seq` pdStateTableRev `seq` (patMatchesIntStatePdPat0Rev' (l-1) pdStateTableRev w' fs)+>         allbinders = b `seq` [ (foldl' (\x g -> (g x)) b f) | (s,f,_) <- fs', s == 0 ] >     in map (collectPatMatchFromBinder w) allbinders >                       @@ -196,10 +210,13 @@ >     let >         l = S.length w >         w' = S.reverse w->         fs = [ (i, id, i) | i <- fins ]->         fs' = w' `seq` fs `seq`  l `seq` pdStateTable `seq` (patMatchesIntStatePdPat0Rev (l-1) pdStateTable w' fs)+>         -- fs = [ (i, id, i) | i <- fins ]+>         -- fs' = w' `seq` fs `seq`  l `seq` pdStateTable `seq` (patMatchesIntStatePdPat0Rev (l-1) pdStateTable w' fs) >         -- fs'' = fs' `seq` my_sort fs'->         allbinders = fs' `seq` b `seq` [ (f b) | (s,f,_) <- fs', s == 0 ]+>         -- allbinders = fs' `seq` b `seq` [ (f b) | (s,f,_) <- fs', s == 0 ]+>         fs = [ (i, [], 0) | i <- fins ]+>         fs' =  w' `seq` fins `seq` l `seq` pdStateTable `seq` (patMatchesIntStatePdPat0Rev' (l-1) pdStateTable w' fs)+>         allbinders = b `seq` [ (foldl' (\x g -> (g x)) b f) | (s,f,_) <- fs', s == 0 ] >     in allbinders `seq` map (collectPatMatchFromBinder w) allbinders >        @@ -230,7 +247,7 @@ >     Left err -> Left ("parseRegex for Text.Regex.PDeriv.ByteString failed:"++show err) >     Right pat -> Right (patToRegex pat compOpt execOpt) >     where ->       patToRegex p _ _ = Regex (compilePat p)+>       patToRegex p _ _ = Regex (compilePat $ simplify p)   
Text/Regex/PDeriv/ByteString/TwoPasses.lhs view
@@ -33,8 +33,8 @@  > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Pretty (Pretty(..))-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), my_hash, my_lookup, GFlag(..), IsGreedy(..), nub2, preBinder, mainBinder, subBinder)-> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, toBinder, Binder(..), strip, listifyBinder)+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), Simplifiable(..), my_hash, my_lookup, GFlag(..), IsGreedy(..), nub2, preBinder, mainBinder, subBinder)+> import Text.Regex.PDeriv.IntPattern (Pat(..), pdPat, pdPat0, pdPat0Sim, toBinder, Binder(..), strip, listifyBinder) > import Text.Regex.PDeriv.Parse > import qualified Text.Regex.PDeriv.Dictionary as D (Dictionary(..), Key(..), insertNotOverwrite, lookupAll, empty, isIn, nub) @@ -105,7 +105,7 @@ >     let sig = map (\x -> (x,0)) (sigmaRE (strip init))         --  the sigma >         init_dict = D.insertNotOverwrite (D.hash init) (init,0) D.empty         --  add init into the initial dictionary >         (all, delta, dictionary) = sig `seq` builder sig [] [] [init] init_dict 1   --  all states and delta->         final = all `seq`  [ s | s <- all, isEmpty (strip s)]                   --  the final states+>         final = all `seq`  [ s | s <- all, posEpsilon (strip s)]                   --  the final states >         sfinal = final `seq` dictionary `seq` map (mapping dictionary) final >         sdelta = [ (i,l,jfs) |  >                   (p,l, qfs) <- delta, @@ -156,7 +156,7 @@ >     | otherwise =  >         let  >             all_sofar_states = acc_states ++ curr_states->             new_delta = [ (s, l, sfs) | s <- curr_states, l <- sig, let sfs = pdPat0 s l]+>             new_delta = [ (s, l, sfs) | s <- curr_states, l <- sig, let sfs = pdPat0Sim s l] >             new_states = all_sofar_states `seq` D.nub [ s' | (_,_,sfs) <- new_delta, (s',f) <- sfs >                                                       , not (s' `D.isIn` dict) ] >             acc_delta_next  = (acc_delta ++ new_delta)@@ -259,7 +259,7 @@ >     Left err -> Left ("parseRegex for Text.Regex.PDeriv.ByteString failed:"++show err) >     Right pat -> Right (patToRegex pat compOpt execOpt) >     where ->       patToRegex p _ _ = Regex (compilePat p)+>       patToRegex p _ _ = Regex (compilePat $ simplify p)   
Text/Regex/PDeriv/Common.lhs view
@@ -2,7 +2,10 @@ > module Text.Regex.PDeriv.Common  >     ( Range >     , Letter->     , IsEmpty (..)+>     , PosEpsilon (..)+>     , IsEpsilon (..)+>     , IsPhi (..)+>     , Simplifiable (..) >     , my_hash >     , my_lookup >     , GFlag (..)@@ -25,9 +28,22 @@ > -- | a character and its index (position) > type Letter = (Char,Int)      -> class IsEmpty a where->     isEmpty :: a -> Bool+> -- | test for 'epsilon \in a' epsilon-possession+> class PosEpsilon a where+>     posEpsilon :: a -> Bool +> -- | test for epsilon == a+> class IsEpsilon a where+>     isEpsilon :: a -> Bool++> -- | test for \phi == a+> class IsPhi a where+>     isPhi :: a -> Bool++> class Simplifiable a where+>     simplify :: a -> a++ > my_hash :: Int -> Char -> Int > my_hash i x = (ord x) + 256 * i @@ -101,7 +117,7 @@ > nub3subsimple im [ x ] = [ x ] > nub3subsimple im (x@(k,f,0):xs) = x:(nub3subsimple im xs) > nub3subsimple im (x@(k,f,1):xs) = let im' = IM.insert k () im->                                   in x:(nub3subsimple im' xs)+>                                   in im' `seq` x:(nub3subsimple im' xs) > nub3subsimple im (x@(k,f,n):xs) = case IM.lookup k im of  >                                   Just _ -> nub3subsimple im xs >                                   Nothing -> let im' = IM.insert k () im
Text/Regex/PDeriv/IntPattern.lhs view
@@ -9,13 +9,14 @@ >     , listifyBinder >  --  , updateBinderByIndex >     , pdPat0+>     , pdPat0Sim >     , nub2 >     ) >     where  > import Data.List > import qualified Data.IntMap as IM-> import Text.Regex.PDeriv.Common (Range, Letter, IsEmpty(..), GFlag(..), IsGreedy(..) )+> import Text.Regex.PDeriv.Common (Range, Letter, PosEpsilon(..), IsEpsilon(..), IsPhi(..), GFlag(..), IsGreedy(..), Simplifiable(..) ) > import Text.Regex.PDeriv.RE > import Text.Regex.PDeriv.Dictionary (Key(..), primeL, primeR) > import Text.Regex.PDeriv.Pretty@@ -99,7 +100,7 @@ > mkEmpPat :: Pat -> Pat > mkEmpPat (PVar x w p) = PVar x w (mkEmpPat p) > mkEmpPat (PE r) ->   | isEmpty r = PE Empty+>   | posEpsilon r = PE Empty >   | otherwise = PE Phi > mkEmpPat (PStar p g) = PE Empty -- problematic?! we are losing binding (x,()) from  ( x : a*) ~> PE <> > mkEmpPat (PPlus p1 p2) = mkEmpPat p1 -- since p2 must be pstar we drop it. If we mkEmpPat p2, we need to deal with pdPat (PPlus (x :<>) (PE <>)) l@@ -140,7 +141,7 @@ >     first sub pattern is non-greedy. We simply swap the order of the  >     'choices' in the resulting pds. -}  > pdPat (PPair p1 p2) l = ->   if (isEmpty (strip p1))+>   if (posEpsilon (strip p1)) >   then  if isGreedy p1 >         then nub ([ PPair p1' p2 | p1' <- pdPat p1 l] ++  >                   [ PPair (mkEmpPat p1) p2' | p2' <- pdPat p2 l])@@ -159,7 +160,7 @@ >     Shall we swap the order of the alternatives when p' is non-greedy? >     Why not? This seems harmless since we have already made some progress by pushing l into p*. -} > pdPat (PPlus p1 p2@(PStar _ _)) l -- p2 must be pStar->     | isEmpty (strip p1) = +>     | posEpsilon (strip p1) =  >         if isGreedy p1  >         then [ PPlus p3 p2 | p3  <- pdPat p1 l ] ++ [ PPlus p3 p2' | (PPlus p1' p2') <- pdPat p2 l, let p3 =  p1' `getBindingsFrom` p1 ] >         else [ PPlus p3 p2' | (PPlus p1' p2') <- pdPat p2 l, let p3 =  p1' `getBindingsFrom` p1 ] ++ [ PPlus p3 p2 | p3  <- pdPat p1 l ]@@ -230,14 +231,14 @@ >                     -> Int  >                     -> Binder  >                     -> Binder-> updateBinderByIndex i pos binder = -- binder  +> updateBinderByIndex i pos binder = -- binder  {- >     IM.update (\ r -> case r of  -- we always initialize to [], we don't need to handle the key miss case->                       { [] -> Just [(pos,pos)] ->                       ; ((b,e):rs)+>                       {  ((b,e):rs) >                           | pos == e + 1 -> Just ((b,e+1):rs) >                           | pos > e + 1  -> Just ((pos,pos):(b,e):rs) >                           | otherwise    -> error "impossible, the current letter position is smaller than the last recorded letter"   ->                       } ) i binder +>                       ; [] -> Just [(pos,pos)] +>                       } ) i binder -- -} > {- > updateBinderByIndex i pos binder =  >     case IM.lookup i binder of@@ -302,7 +303,7 @@ > pdPat0 (PStar p g) l = let pfs = pdPat0 p l >                        in pfs `seq` [ (PPair p' (PStar p g), f) | (p', f) <- pfs ] > pdPat0 (PPair p1 p2) l = ->     if (isEmpty (strip p1))+>     if (posEpsilon (strip p1)) >     then if isGreedy p1 >          then nub2 ([ (PPair p1' p2, f) | (p1' , f) <- pdPat0 p1 l ] ++ (pdPat0 p2 l)) >          else nub2 ((pdPat0 p2 l) ++ [ (PPair p1' p2, f) | (p1' , f) <- pdPat0 p1 l ])@@ -313,3 +314,60 @@  > nub2 :: Eq a => [(a,b)] -> [(a,b)] > nub2 = nubBy (\(p1,f1) (p2, f2) -> p1 == p2) +++> {-| Function 'pdPat0Sim' applies simplification to the results of 'pdPat0' -}+> pdPat0Sim :: Pat -- ^ the source pattern +>              -> Letter -- ^ the letter to be "consumed"+>              -> [(Pat, Int -> Binder -> Binder)]+> pdPat0Sim p l = +>      let pfs = pdPat0 p l+>          pfs' = pfs `seq` map (\(p,f) -> (simplify p, f)) pfs+>      in nub2 pfs'++++> -- | mainly interested in simplifying epsilon, p --> p+> -- could be made more optimal, e.g. (epsilon, epsilon) --> epsilon+> instance Simplifiable Pat where+>     -- simplify :: Pat -> Pat+>     simplify (PVar i rs p) = PVar i rs (simplify p)+>     simplify (PPair p1 p2) =+>         let p1' = simplify p1+>             p2' = simplify p2+>         in if isEpsilon p1'+>            then p2'+>            else if isEpsilon p2'+>                 then p1'+>                 else PPair p1' p2'+>     simplify (PChoice p1 p2 g) =+>         let p1' = simplify p1+>             p2' = simplify p2+>         in if isPhi p2'+>            then p1'+>            else if isPhi p1'+>                 then p2'+>                 else PChoice p1' p2' g+>     simplify (PStar p g) = PStar (simplify p) g+>     simplify (PPlus p1 p2) = PPlus (simplify p1) (simplify p2)+>     simplify (PE r) = PE (simplify r)+++> instance IsEpsilon Pat where+>    isEpsilon (PVar _ _ p) = isEpsilon p+>    isEpsilon (PE r) = isEpsilon r                                                        +>    isEpsilon (PPair p1 p2) =  (isEpsilon p1) && (isEpsilon p2)+>    isEpsilon (PChoice p1 p2 _) =  (isEpsilon p1) && (isEpsilon p2)+>    isEpsilon (PStar p _) = isEpsilon p+>    isEpsilon (PPlus p1 p2) = isEpsilon p1 && isEpsilon p2+>    isEpsilon (PEmpty _) = True+                                                        ++> instance IsPhi Pat where+>    isPhi (PVar _ _ p) = isPhi p+>    isPhi (PE r) = isPhi r                                                        +>    isPhi (PPair p1 p2) =  (isPhi p1) || (isPhi p2)+>    isPhi (PChoice p1 p2 _) =  (isPhi p1) && (isPhi p2)+>    isPhi (PStar p _) = False+>    isPhi (PPlus p1 p2) = isPhi p1 || isPhi p2+>    isPhi (PEmpty _) = False
Text/Regex/PDeriv/RE.lhs view
@@ -7,7 +7,7 @@ > import Data.List (nub) > import Data.Char (chr) -> import Text.Regex.PDeriv.Common (IsEmpty(..), IsGreedy(..), GFlag(..))+> import Text.Regex.PDeriv.Common (PosEpsilon(..), IsEpsilon(..), IsPhi(..), Simplifiable(..), IsGreedy(..), GFlag(..)) > import Text.Regex.PDeriv.Dictionary (Key(..), primeL, primeR)  ------------------------@@ -30,7 +30,7 @@ >     (==) (Seq r1 r2) (Seq r3 r4) = (r1 == r3) && (r2 == r4) >     (==) (Star r1 g1) (Star r2 g2) = g1 == g2 && r1 == r2  >     (==) Any Any = True->     (==) (Not cs) (Not cs') = cs == cs'+>     (==) (Not cs) (Not cs') = cs == cs'  >     (==) _ _ = False  @@ -85,18 +85,40 @@ > resToRE (r:res) = foldl (\x y -> Choice x y Greedy) r res > resToRE [] = Phi -> -- | function 'isEmpty' checks whether regular expressions are empty-> instance IsEmpty RE where->   isEmpty Phi = False->   isEmpty Empty = True->   isEmpty (Choice r1 r2 g) = (isEmpty r1) || (isEmpty r2)->   isEmpty (Seq r1 r2) = (isEmpty r1) && (isEmpty r2)->   isEmpty (Star r g) = True->   isEmpty (L _) = False->   isEmpty Any = False->   isEmpty (Not _) = False++> instance PosEpsilon RE where+>   posEpsilon Phi = False+>   posEpsilon Empty = True+>   posEpsilon (Choice r1 r2 g) = (posEpsilon r1) || (posEpsilon r2)+>   posEpsilon (Seq r1 r2) = (posEpsilon r1) && (posEpsilon r2)+>   posEpsilon (Star r g) = True+>   posEpsilon (L _) = False+>   posEpsilon Any = False+>   posEpsilon (Not _) = False          +> -- | function 'isEpsilon' checks whether epsilon = r+> instance IsEpsilon RE where+>   isEpsilon Phi = False+>   isEpsilon Empty = True+>   isEpsilon (Choice r1 r2 g) = (isEpsilon r1) && (isEpsilon r2)+>   isEpsilon (Seq r1 r2) = (isEpsilon r1) && (isEpsilon r2)+>   isEpsilon (Star Phi g) = True+>   isEpsilon (Star r g) = isEpsilon r+>   isEpsilon (L _) = False+>   isEpsilon Any = False+>   isEpsilon (Not _) = False++> instance IsPhi RE where+>   isPhi Phi = True+>   isPhi Empty = False+>   isPhi (Choice r1 r2 g) = (isPhi r1) && (isPhi r2)+>   isPhi (Seq r1 r2) = (isPhi r1) || (isPhi r2)+>   isPhi (Star r g) = False+>   isPhi (L _) = False+>   isPhi Any = False+>   isPhi (Not _) = False+ > -- | function 'partDeriv' implements the partial derivative operations for regular expressions. We don't pay attention to the greediness flag here. > partDeriv :: RE -> Char -> [RE] > partDeriv r l = nub (partDerivSub r l)@@ -115,22 +137,22 @@ >     let  >         s1 = partDerivSub r1 l  >         s2 = partDerivSub r2 l->     in {- s1 `seq` s2 `seq` -} (s1 ++ s2)+>     in s1 `seq` s2 `seq` (s1 ++ s2) > partDerivSub (Seq r1 r2) l ->     | isEmpty r1 = +>     | posEpsilon r1 =  >           let  >               s0 = partDerivSub r1 l >               s1 = s0 `seq` [ (Seq r1' r2) | r1' <- s0 ] >               s2 = partDerivSub r2 l->           in {- s1 `seq` s2 `seq` -} (s1 ++ s2)+>           in s1 `seq` s2 `seq` (s1 ++ s2) >     | otherwise =  >         let  >             s0 = partDerivSub r1 l ->         in {- s0 `seq` -} [ (Seq r1' r2) | r1' <- s0 ]+>         in s0 `seq` [ (Seq r1' r2) | r1' <- s0 ] > partDerivSub (Star r g) l =  >     let >         s0 = partDerivSub r l->     in {- s0 `seq` -} [ (Seq r' (Star r g)) | r' <- s0 ]+>     in s0 `seq` [ (Seq r' (Star r g)) | r' <- s0 ]  > -- | function 'sigmaRE' returns all characters appearing in a reg exp. > sigmaRE :: RE -> [Char]@@ -146,3 +168,26 @@ > sigmaREsub Phi = [] > sigmaREsub Empty = [] +> instance Simplifiable RE where+>     simplify (L l) = L l+>     simplify Any   = Any+>     simplify (Not cs) = Not cs+>     simplify (Seq r1 r2) = +>         let r1' = simplify r1+>             r2' = simplify r2+>         in if isEpsilon r1'+>            then r2'+>            else if isEpsilon r2'+>                 then r1'+>                 else Seq r1' r2'+>     simplify (Choice r1 r2 g) = +>         let r1' = simplify r1+>             r2' = simplify r2+>         in if isPhi r1'+>            then r2'+>            else if isPhi r2'+>                 then r1'+>                 else Choice r1' r2' g+>     simplify (Star r g) = Star (simplify r) g+>     simplify Phi = Phi+>     simplify Empty = Empty
Text/Regex/PDeriv/Translate.lhs view
@@ -134,7 +134,7 @@ > trans :: EPat -> State TState Pat > trans epat =  >     do { is_posix <- isPosix -- if it is posix, we need to aggresively "tag" every sub expression with a binder->        ; if is_posix +>        ; if is_posix && isStructural epat >          then do  >            { gi <- getIncGI >            ; ipat <- trans' epat@@ -143,14 +143,22 @@ >            } >          else trans' epat >        }->     where trans' :: EPat -> State TState Pat->           trans' epat ->               | hasGroup epat = p_trans epat->               | otherwise     = do ->                                 { r <- r_trans epat->                                 ; return (PE r)->                                 }+>     where isStructural :: EPat -> Bool -- ^ indicate whether it is a complex structure which we need to add extra binding for POSIX tracking+>           isStructural (EOr _)     = True+>           isStructural (EConcat _) = True                                                                      +>           isStructural (EOpt _ _)  = True+>           isStructural (EPlus _ _) = True+>           isStructural (EStar _ _) = True+>           isStructural _           = False                                                                       +> trans' :: EPat -> State TState Pat+> trans' epat +>      | hasGroup epat = p_trans epat+>      | otherwise     = do +>                 { r <- r_trans epat+>                 ; return (PE r)+>                 }+ > {- > trans :: EPat -> State TState Pat > trans epat | hasGroup epat = p_trans epat@@ -192,7 +200,8 @@ >       -} >     ; EGroup e -> >       do { i <- getIncGI->          ; p <- trans e+>          ; -- p <- trans e+>          ; p <- trans' e -- no need to go through trans which possible tag p with a posix var >          ; return ( PVar i [] p) >          } >     ; EOr es -> 
regex-pderiv.cabal view
@@ -1,5 +1,5 @@ Name:                   regex-pderiv-Version:                0.0.9+Version:                0.1.0 License:                BSD3 License-File:           LICENSE Copyright:              Copyright (c) 2010, Kenny Zhuo Ming Lu and Martin Sulzmann@@ -18,7 +18,8 @@ flag base4  library -  Build-Depends:        regex-base >= 0.93.1, parsec, mtl, containers, bytestring, deepseq, bitset+  Build-Depends:        regex-base >= 0.93.1, parsec, mtl, containers, bytestring, deepseq+  Build-Depends:	bitset   Build-Depends:         base >= 4.0 && < 5.0, ghc-prim   Exposed-Modules:       Text.Regex.PDeriv.ByteString                          Text.Regex.PDeriv.ByteString.TwoPasses@@ -38,5 +39,5 @@                          Text.Regex.PDeriv.Dictionary   Buildable:              True   Extensions:             GADTs, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, TypeSynonymInstances, FlexibleContexts-  GHC-Options:            +  GHC-Options:            -threaded   GHC-Prof-Options:       -auto-all