module Text.Regex.DFA.ByteString.EngineFPS(findRegex,countRegex,matchesHere,matchesRegex,accept) where
import Text.Regex.DFA.Engine(peek, accept, lexAccept, lexFailure,
Lexer(..), Cont(..),Boundary(..))
import Data.ByteString.Lazy.Char8(ByteString)
import qualified Data.ByteString.Lazy.Char8 as B(null,tail,length,index)
findRegex :: Lexer
-> ByteString
-> (Int, Maybe (Int,Int))
findRegex lexer input =
let len = fromEnum $ B.length input
loop s i | i == len = (len,Nothing)
| otherwise =
let n=applyHere lexer s len (1) i
in if n==(1) then loop s (succ i)
else (i,Just (ni,n))
in loop input 0
applyHere :: Lexer
-> ByteString
-> Int
-> Int
-> Int
-> Int
applyHere lexerIn input end valueIn hereIn =
let final = fromEnum (B.length input)
loop (Lexer _ action cont) value here | here `seq` value `seq` False = undefined
| otherwise =
let value' = if action == lexAccept then here else value
in case cont of
Done -> value'
_ -> if here == end
then value'
else case peek cont (B.index input (toEnum here)) of
(Lexer _ action' _ ) | action' == lexFailure -> value'
lexer' -> loop lexer' value' (succ here)
loop (Predicate _ p yes no) value here | here `seq` value `seq` False = undefined
| otherwise =
let t = case p of
BeginLine -> (here==0) || ('\n' == B.index input (toEnum $ pred here))
EndLine -> (here==final) || ('\n' == B.index input (toEnum here))
BeginInput -> here==0
EndInput -> here==final
lexer = if t then yes else no
in loop lexer value here
in loop lexerIn valueIn hereIn
countRegex :: Lexer -> ByteString -> Int
countRegex lexer input =
let len = fromEnum $ B.length input
loop i n | n `seq` (i == len) = n
| otherwise =
if (1) == applyHere lexer input len (1) i
then loop (succ i) n
else loop (succ i) (succ n)
in loop 0 0
matchesHere :: Lexer -> ByteString -> Maybe Int
matchesHere lexer input =
let n=applyHere lexer input (fromEnum $ B.length input) (1) 0
in if n == (1) then Nothing else Just n
matchesRegex :: Lexer -> ByteString -> Bool
matchesRegex lexer input | B.null input = False
| otherwise =
case applyHere lexer input (fromEnum $ B.length input) (1) 0 of
(1) -> matchesRegex lexer (B.tail input)
_ -> True