@@ -65,14 +65,14 @@ module Data.Attoparsec.Text.Internal
68−import Control.Applicative ((<|>), (<$>), pure, (*>))
68+import Control.Applicative ((<|>), (<$>))
69import Control.Monad (when)
69import Control.Monad (when)
70import Data.Attoparsec.Combinator ((<?>))
70import Data.Attoparsec.Combinator ((<?>))
71import Data.Attoparsec.Internal
71import Data.Attoparsec.Internal
72import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
72import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
73import qualified Data.Attoparsec.Text.Buffer as Buf
73import qualified Data.Attoparsec.Text.Buffer as Buf
74import Data.Attoparsec.Text.Buffer (Buffer, buffer)
74import Data.Attoparsec.Text.Buffer (Buffer, buffer)
75−import Data.Char (isAsciiUpper, isAsciiLower, toUpper, toLower)
75+import Data.Char (chr, ord)
76import Data.List (intercalate)
76import Data.List (intercalate)
77import Data.String (IsString(..))
77import Data.String (IsString(..))
78import Data.Text.Internal (Text(..))
78import Data.Text.Internal (Text(..))
@@ -222,16 +222,15 @@ stringCI s = go 0
223-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
223-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
224asciiCI :: Text -> Parser Text
224asciiCI :: Text -> Parser Text
225−asciiCI s = fmap fst $ match $ T.foldr ((*>) . asciiCharCI) (pure ()) s
225+asciiCI s = string_ (stringSuspended asciiToLower) asciiToLower s
227+ asciiToLower = T.map f
229+ offset = ord 'a' - ord 'A'
230+ f c | 'A' <= c && c <= 'Z' = chr (ord c + offset)
226{-# INLINE asciiCI #-}
232{-# INLINE asciiCI #-}
228−asciiCharCI :: Char -> Parser Char
230− | isAsciiUpper c = char c <|> char (toLower c)
231− | isAsciiLower c = char c <|> char (toUpper c)
232− | otherwise = char c
233−{-# INLINE asciiCharCI #-}
235-- | Skip past input for as long as the predicate returns 'True'.
234-- | Skip past input for as long as the predicate returns 'True'.
236skipWhile :: (Char -> Bool) -> Parser ()
235skipWhile :: (Char -> Bool) -> Parser ()
237skipWhile p = go
236skipWhile p = go
@@ -267,25 +266,14 @@ takeTill p = takeWhile (not . p)
267-- parsers loop until a failure occurs. Careless use will thus result
266-- parsers loop until a failure occurs. Careless use will thus result
268-- in an infinite loop.
267-- in an infinite loop.
269takeWhile :: (Char -> Bool) -> Parser Text
268takeWhile :: (Char -> Bool) -> Parser Text
270−takeWhile p = do
269+takeWhile p = (T.concat . reverse) `fmap` go []
271− h <- T.takeWhile p <$> get
272− continue <- inputSpansChunks (size h)
273− -- only use slow concat path if necessary
275− then takeWhileAcc p [h]
277−{-# INLINE takeWhile #-}
279−takeWhileAcc :: (Char -> Bool) -> [Text] -> Parser Text
282 go acc = do
271 go acc = do
283 h <- T.takeWhile p <$> get
272 h <- T.takeWhile p <$> get
284 continue <- inputSpansChunks (size h)
273 continue <- inputSpansChunks (size h)
285 if continue
274 if continue
286 then go (h:acc)
275 then go (h:acc)
287− else return $ concatReverse (h:acc)
276+ else return (h:acc)
288−{-# INLINE takeWhileAcc #-}
290takeRest :: Parser [Text]
278takeRest :: Parser [Text]
291takeRest = go []
279takeRest = go []
@@ -308,7 +296,7 @@ takeLazyText :: Parser L.Text
308takeLazyText = L.fromChunks `fmap` takeRest
296takeLazyText = L.fromChunks `fmap` takeRest
310data Scan s = Continue s
298data Scan s = Continue s
311− | Finished s {-# UNPACK #-} !Int Text
299+ | Finished {-# UNPACK #-} !Int Text
313scan_ :: (s -> [Text] -> Parser r) -> s -> (s -> Char -> Maybe s) -> Parser r
301scan_ :: (s -> [Text] -> Parser r) -> s -> (s -> Char -> Maybe s) -> Parser r
314scan_ f s0 p = go [] s0
302scan_ f s0 p = go [] s0
@@ -317,7 +305,7 @@ scan_ f s0 p = go [] s0
317 case T.uncons t of
305 case T.uncons t of
318 Just (c,t') -> case p s c of
306 Just (c,t') -> case p s c of
319 Just s' -> scanner s' (n+1) t'
307 Just s' -> scanner s' (n+1) t'
320− Nothing -> Finished s n t
308+ Nothing -> Finished n t
321 Nothing -> Continue s
309 Nothing -> Continue s
322 go acc s = do
310 go acc s = do
323 input <- get
311 input <- get
@@ -326,8 +314,8 @@ scan_ f s0 p = go [] s0
326 if continue
314 if continue
327 then go (input : acc) s'
315 then go (input : acc) s'
328 else f s' (input : acc)
316 else f s' (input : acc)
329− Finished s' n t -> do advance (size input - size t)
317+ Finished n t -> do advance (size input - size t)
330− f s' (T.take n input : acc)
318+ f s (T.take n input : acc)
331{-# INLINE scan_ #-}
319{-# INLINE scan_ #-}
333-- | A stateful scanner. The predicate consumes and transforms a
321-- | A stateful scanner. The predicate consumes and transforms a
@@ -343,13 +331,16 @@ scan_ f s0 p = go [] s0
343-- parsers loop until a failure occurs. Careless use will thus result
331-- parsers loop until a failure occurs. Careless use will thus result
344-- in an infinite loop.
332-- in an infinite loop.
345scan :: s -> (s -> Char -> Maybe s) -> Parser Text
333scan :: s -> (s -> Char -> Maybe s) -> Parser Text
346−scan = scan_ $ \_ chunks -> return $! concatReverse chunks
334+scan = scan_ $ \_ chunks ->
337+ xs -> return . T.concat . reverse $ xs
347{-# INLINE scan #-}
338{-# INLINE scan #-}
349-- | Like 'scan', but generalized to return the final state of the
340-- | Like 'scan', but generalized to return the final state of the
350-- scanner.
341-- scanner.
351runScanner :: s -> (s -> Char -> Maybe s) -> Parser (Text, s)
342runScanner :: s -> (s -> Char -> Maybe s) -> Parser (Text, s)
352−runScanner = scan_ $ \s xs -> let !sx = concatReverse xs in return (sx, s)
343+runScanner = scan_ $ \s xs -> return (T.concat (reverse xs), s)
353{-# INLINE runScanner #-}
344{-# INLINE runScanner #-}
355-- | Consume input as long as the predicate returns 'True', and return
346-- | Consume input as long as the predicate returns 'True', and return
@@ -367,9 +358,8 @@ takeWhile1 p = do
367 advance size'
358 advance size'
368 eoc <- endOfChunk
359 eoc <- endOfChunk
370− then takeWhileAcc p [h]
361+ then (h<>) `fmap` takeWhile p
371 else return h
362 else return h
372−{-# INLINE takeWhile1 #-}
374-- | Match any character in a set.
364-- | Match any character in a set.