@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, FlexibleInstances, GADTs, OverloadedStrings,
1+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, GADTs, OverloadedStrings,
2 Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
2 Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -65,14 +65,17 @@ module Data.Attoparsec.Text.Internal
68+#if !MIN_VERSION_base(4,8,0)
68−import Control.Applicative ((<|>), (<$>), pure, (*>))
69+import Control.Applicative ((<$>))
71+import Control.Applicative ((<|>))
69import Control.Monad (when)
72import Control.Monad (when)
70import Data.Attoparsec.Combinator ((<?>))
73import Data.Attoparsec.Combinator ((<?>))
71import Data.Attoparsec.Internal
74import Data.Attoparsec.Internal
72import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
75import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
73import qualified Data.Attoparsec.Text.Buffer as Buf
76import qualified Data.Attoparsec.Text.Buffer as Buf
74import Data.Attoparsec.Text.Buffer (Buffer, buffer)
77import Data.Attoparsec.Text.Buffer (Buffer, buffer)
75−import Data.Char (isAsciiUpper, isAsciiLower, toUpper, toLower)
78+import Data.Char (chr, ord)
76import Data.List (intercalate)
79import Data.List (intercalate)
77import Data.String (IsString(..))
80import Data.String (IsString(..))
78import Data.Text.Internal (Text(..))
81import Data.Text.Internal (Text(..))
@@ -222,16 +225,15 @@ stringCI s = go 0
223-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
226-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
224asciiCI :: Text -> Parser Text
227asciiCI :: Text -> Parser Text
225−asciiCI s = fmap fst $ match $ T.foldr ((*>) . asciiCharCI) (pure ()) s
228+asciiCI s = string_ (stringSuspended asciiToLower) asciiToLower s
230+ asciiToLower = T.map f
232+ offset = ord 'a' - ord 'A'
233+ f c | 'A' <= c && c <= 'Z' = chr (ord c + offset)
226{-# INLINE asciiCI #-}
235{-# 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'.
237-- | Skip past input for as long as the predicate returns 'True'.
236skipWhile :: (Char -> Bool) -> Parser ()
238skipWhile :: (Char -> Bool) -> Parser ()
237skipWhile p = go
239skipWhile p = go
@@ -267,25 +269,14 @@ takeTill p = takeWhile (not . p)
267-- parsers loop until a failure occurs. Careless use will thus result
269-- parsers loop until a failure occurs. Careless use will thus result
268-- in an infinite loop.
270-- in an infinite loop.
269takeWhile :: (Char -> Bool) -> Parser Text
271takeWhile :: (Char -> Bool) -> Parser Text
270−takeWhile p = do
272+takeWhile p = concatReverse `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
274 go acc = do
283 h <- T.takeWhile p <$> get
275 h <- T.takeWhile p <$> get
284 continue <- inputSpansChunks (size h)
276 continue <- inputSpansChunks (size h)
285 if continue
277 if continue
286 then go (h:acc)
278 then go (h:acc)
287− else return $ concatReverse (h:acc)
279+ else return (h:acc)
288−{-# INLINE takeWhileAcc #-}
290takeRest :: Parser [Text]
281takeRest :: Parser [Text]
291takeRest = go []
282takeRest = go []
@@ -308,7 +299,7 @@ takeLazyText :: Parser L.Text
308takeLazyText = L.fromChunks `fmap` takeRest
299takeLazyText = L.fromChunks `fmap` takeRest
310data Scan s = Continue s
301data Scan s = Continue s
311− | Finished s {-# UNPACK #-} !Int Text
302+ | Finished {-# UNPACK #-} !Int Text
313scan_ :: (s -> [Text] -> Parser r) -> s -> (s -> Char -> Maybe s) -> Parser r
304scan_ :: (s -> [Text] -> Parser r) -> s -> (s -> Char -> Maybe s) -> Parser r
314scan_ f s0 p = go [] s0
305scan_ f s0 p = go [] s0
@@ -317,7 +308,7 @@ scan_ f s0 p = go [] s0
317 case T.uncons t of
308 case T.uncons t of
318 Just (c,t') -> case p s c of
309 Just (c,t') -> case p s c of
319 Just s' -> scanner s' (n+1) t'
310 Just s' -> scanner s' (n+1) t'
320− Nothing -> Finished s n t
311+ Nothing -> Finished n t
321 Nothing -> Continue s
312 Nothing -> Continue s
322 go acc s = do
313 go acc s = do
323 input <- get
314 input <- get
@@ -326,8 +317,8 @@ scan_ f s0 p = go [] s0
326 if continue
317 if continue
327 then go (input : acc) s'
318 then go (input : acc) s'
328 else f s' (input : acc)
319 else f s' (input : acc)
329− Finished s' n t -> do advance (size input - size t)
320+ Finished n t -> do advance (size input - size t)
330− f s' (T.take n input : acc)
321+ f s (T.take n input : acc)
331{-# INLINE scan_ #-}
322{-# INLINE scan_ #-}
333-- | A stateful scanner. The predicate consumes and transforms a
324-- | A stateful scanner. The predicate consumes and transforms a
@@ -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.