git.iko.soy/typeable/attoparsec
on master help sign in
Unified 'satisfy' for ByteString and Text.
commite111536f855bf8e74da7152ac30d00089b5426b3 authorMikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com> dateTue 11 Feb 2014, 23:50 (13 years ago) parentb2d9f5f
4 files changed+37−14
Data/Attoparsec/ByteString/Internal.hs+1−6 Data/Attoparsec/Combinator.hs+22−2 Data/Attoparsec/Internal/Types.hs+13 Data/Attoparsec/Text/Internal.hs+1−6
Data/Attoparsec/ByteString/Internal.hs+1−6
@@ -105,12 +105,7 @@ type Success a r = T.Success B.ByteString a r
105105-- >digit = satisfy isDigit
106106-- > where isDigit w = w >= 48 && w <= 57
107107satisfy :: (Word8 -> Bool) -> Parser Word8
108−satisfy p = do
109− s <- ensure 1
110− let !w = B.unsafeHead s
111− if p w
112− then put (B.unsafeTail s) >> return w
113− else fail "satisfy"
108+satisfy = satisfyElem
114109{-# INLINE satisfy #-}
115110
116111-- | The parser @skip p@ succeeds for any byte for which the predicate
Data/Attoparsec/Combinator.hs+22−2
@@ -10,7 +10,9 @@
1010--
1111-- Useful parser combinators, similar to those provided by Parsec.
1212module Data.Attoparsec.Combinator
13− ( try
13+ (
14+ -- * Combinators
15+ try
1416 , (<?>)
1517 , choice
1618 , count
@@ -27,6 +29,8 @@ module Data.Attoparsec.Combinator
2729 , skipMany
2830 , skipMany1
2931 , eitherP
32+ -- * Parsing individual chunk elements
33+ , satisfyElem
3034 ) where
3135
3236import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
@@ -36,7 +40,8 @@ import Control.Monad (MonadPlus(..))
3640import Control.Applicative (many)
3741#endif
3842
39−import Data.Attoparsec.Internal.Types (Parser(..))
43+import Data.Attoparsec.Internal.Types
44+import Data.Attoparsec.Internal
4045#if __GLASGOW_HASKELL__ >= 700
4146import qualified Data.Attoparsec.Zepto as Z
4247import Data.ByteString (ByteString)
@@ -245,3 +250,18 @@ count n p = sequence (replicate n p)
245250eitherP :: (Alternative f) => f a -> f b -> f (Either a b)
246251eitherP a b = (Left <$> a) <|> (Right <$> b)
247252{-# INLINE eitherP #-}
253+
254+-- | The parser @satisfyElem p@ succeeds for any chunk element for which the
255+-- predicate @p@ returns 'True'. Returns the element that is
256+-- actually parsed.
257+--
258+-- >digit = satisfyElem isDigit
259+-- > where isDigit c = c >= '0' && c <= '9'
260+satisfyElem :: Chunk t => (ChunkElem t -> Bool) -> Parser t (ChunkElem t)
261+satisfyElem p = do
262+ c <- ensure 1
263+ let !h = unsafeChunkHead c
264+ if p h
265+ then put (unsafeChunkTail c) >> return h
266+ else fail "satisfyElem"
267+{-# INLINE satisfyElem #-}
Data/Attoparsec/Internal/Types.hs+13
@@ -32,6 +32,7 @@ import Control.Monad (MonadPlus(..))
3232import Data.Word (Word8)
3333import Data.ByteString (ByteString)
3434import qualified Data.ByteString as BS
35+import qualified Data.ByteString.Unsafe as BS
3536import Data.Text (Text)
3637import qualified Data.Text as T
3738import qualified Data.Text.Unsafe as T
@@ -238,6 +239,10 @@ class Monoid c => Chunk c where
238239 type ChunkElem c
239240 -- | Test if the chunk is empty.
240241 nullChunk :: c -> Bool
242+ -- | Get the head element of a non-empty chunk.
243+ unsafeChunkHead :: c -> ChunkElem c
244+ -- | Get the tail of a non-empty chunk.
245+ unsafeChunkTail :: c -> c
241246 -- | Check if the chunk has the length of at least @n@ elements.
242247 chunkLengthAtLeast :: c -> Int -> Bool
243248
@@ -245,6 +250,10 @@ instance Chunk ByteString where
245250 type ChunkElem ByteString = Word8
246251 nullChunk = BS.null
247252 {-# INLINE nullChunk #-}
253+ unsafeChunkHead = BS.unsafeHead
254+ {-# INLINE unsafeChunkHead #-}
255+ unsafeChunkTail = BS.unsafeTail
256+ {-# INLINE unsafeChunkTail #-}
248257 chunkLengthAtLeast bs n = BS.length bs >= n
249258 {-# INLINE chunkLengthAtLeast #-}
250259
@@ -252,5 +261,9 @@ instance Chunk Text where
252261 type ChunkElem Text = Char
253262 nullChunk = T.null
254263 {-# INLINE nullChunk #-}
264+ unsafeChunkHead = T.unsafeHead
265+ {-# INLINE unsafeChunkHead #-}
266+ unsafeChunkTail = T.unsafeTail
267+ {-# INLINE unsafeChunkTail #-}
255268 chunkLengthAtLeast t n = T.lengthWord16 t `quot` 2 >= n || T.length t >= n
256269 {-# INLINE chunkLengthAtLeast #-}
Data/Attoparsec/Text/Internal.hs+1−6
@@ -107,12 +107,7 @@ unsafeDrop = T.drop
107107-- >digit = satisfy isDigit
108108-- > where isDigit c = c >= '0' && c <= '9'
109109satisfy :: (Char -> Bool) -> Parser Char
110−satisfy p = do
111− s <- ensure 1
112− let !w = unsafeHead s
113− if p w
114− then put (unsafeTail s) >> return w
115− else fail "satisfy"
110+satisfy = satisfyElem
116111{-# INLINE satisfy #-}
117112
118113-- | The parser @skip p@ succeeds for any character for which the