attoparsec 0.13.2.5 → 0.14.1
raw patch · 10 files changed
+172/−34 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Attoparsec.ByteString: getChunk :: Parser (Maybe ByteString)
+ Data.Attoparsec.ByteString: takeWhileIncluding :: (Word8 -> Bool) -> Parser ByteString
+ Data.Attoparsec.ByteString.Lazy: getChunk :: Parser (Maybe ByteString)
+ Data.Attoparsec.ByteString.Lazy: takeWhileIncluding :: (Word8 -> Bool) -> Parser ByteString
Files
- Data/Attoparsec/ByteString.hs +2/−0
- Data/Attoparsec/ByteString/Char8.hs +22/−13
- Data/Attoparsec/ByteString/Internal.hs +53/−0
- Data/Attoparsec/ByteString/Lazy.hs +15/−1
- Data/Attoparsec/Combinator.hs +4/−3
- Data/Attoparsec/Text.hs +22/−13
- Data/Attoparsec/Text/Lazy.hs +15/−1
- attoparsec.cabal +3/−3
- changelog.md +9/−0
- tests/QC/ByteString.hs +27/−0
Data/Attoparsec/ByteString.hs view
@@ -66,7 +66,9 @@ , I.runScanner , I.takeWhile , I.takeWhile1+ , I.takeWhileIncluding , I.takeTill+ , I.getChunk -- ** Consume all remaining input , I.takeByteString
Data/Attoparsec/ByteString/Char8.hs view
@@ -489,30 +489,39 @@ {-# SPECIALIZE rational :: Parser Scientific #-} rational = scientifically realToFrac --- | Parse a rational number.+-- | Parse a 'Double'. -- -- This parser accepts an optional leading sign character, followed by--- at least one decimal digit. The syntax similar to that accepted by--- the 'read' function, with the exception that a trailing @\'.\'@ or--- @\'e\'@ /not/ followed by a number is not consumed.+-- at most one decimal digit. The syntax is similar to that accepted by+-- the 'read' function, with the exception that a trailing @\'.\'@ is+-- consumed. --+-- === Examples+--+-- These examples use this helper:+--+-- @+-- r :: 'Parser' a -> 'Data.ByteString.ByteString' -> 'Data.Attoparsec.ByteString.Result' a+-- r p s = 'feed' ('Data.Attoparsec.parse' p s) 'mempty'+-- @+-- -- Examples with behaviour identical to 'read', if you feed an empty -- continuation to the first result: ----- >rational "3" == Done 3.0 ""--- >rational "3.1" == Done 3.1 ""--- >rational "3e4" == Done 30000.0 ""--- >rational "3.1e4" == Done 31000.0, ""+-- > double "3" == Done "" 3.0+-- > double "3.1" == Done "" 3.1+-- > double "3e4" == Done "" 30000.0+-- > double "3.1e4" == Done "" 31000.0+-- > double "3e" == Done "e" 3.0 -- -- Examples with behaviour identical to 'read': ----- >rational ".3" == Fail "input does not start with a digit"--- >rational "e3" == Fail "input does not start with a digit"+-- > double ".3" == Fail ".3" _ _+-- > double "e3" == Fail "e3" _ _ ----- Examples of differences from 'read':+-- Example of difference from 'read': ----- >rational "3.foo" == Done 3.0 ".foo"--- >rational "3e" == Done 3.0 "e"+-- > double "3.foo" == Done "foo" 3.0 -- -- This function does not accept string representations of \"NaN\" or -- \"Infinity\".
Data/Attoparsec/ByteString/Internal.hs view
@@ -53,7 +53,9 @@ , runScanner , takeWhile , takeWhile1+ , takeWhileIncluding , takeTill+ , getChunk -- ** Consume all remaining input , takeByteString@@ -277,6 +279,46 @@ else return $ concatReverse (s:acc) {-# INLINE takeWhileAcc #-} +-- | Consume input until immediately after the predicate returns 'True', and return+-- the consumed input.+--+-- This parser will consume at least one 'Word8' or fail.+takeWhileIncluding :: (Word8 -> Bool) -> Parser B.ByteString+takeWhileIncluding p = do+ (s', t) <- B8.span p <$> get+ case B8.uncons t of+ -- Since we reached a break point and managed to get the next byte,+ -- input can not have been exhausted thus we succed and advance unconditionally.+ Just (h, _) -> do+ let s = s' `B8.snoc` h+ advance (B8.length s)+ return s+ -- The above isn't true so either we ran out of input or we need to process the next chunk.+ Nothing -> do+ continue <- inputSpansChunks (B8.length s')+ if continue+ then takeWhileIncAcc p [s']+ -- Our spec says that if we run out of input we fail.+ else fail "takeWhileIncluding reached end of input"+{-# INLINE takeWhileIncluding #-}++takeWhileIncAcc :: (Word8 -> Bool) -> [B.ByteString] -> Parser B.ByteString+takeWhileIncAcc p = go+ where+ go acc = do+ (s', t) <- B8.span p <$> get+ case B8.uncons t of+ Just (h, _) -> do+ let s = s' `B8.snoc` h+ advance (B8.length s)+ return (concatReverse $ s:acc)+ Nothing -> do+ continue <- inputSpansChunks (B8.length s')+ if continue+ then go (s':acc)+ else fail "takeWhileIncAcc reached end of input"+{-# INLINE takeWhileIncAcc #-}+ takeRest :: Parser [ByteString] takeRest = go [] where@@ -296,6 +338,17 @@ -- | Consume all remaining input and return it as a single string. takeLazyByteString :: Parser L.ByteString takeLazyByteString = L.fromChunks `fmap` takeRest++-- | Return the rest of the current chunk without consuming anything.+--+-- If the current chunk is empty, then ask for more input.+-- If there is no more input, then return 'Nothing'+getChunk :: Parser (Maybe ByteString)+getChunk = do+ input <- wantInput+ if input+ then Just <$> get+ else return Nothing data T s = T {-# UNPACK #-} !Int s
Data/Attoparsec/ByteString/Lazy.hs view
@@ -33,6 +33,7 @@ , module Data.Attoparsec.ByteString -- * Running parsers , parse+ , parseOnly , parseTest -- ** Result conversion , maybeResult@@ -47,7 +48,7 @@ import qualified Data.Attoparsec.Internal.Types as T import Data.Attoparsec.ByteString hiding (IResult(..), Result, eitherResult, maybeResult,- parse, parseWith, parseTest)+ parse, parseOnly, parseWith, parseTest) -- | The result of a parse. data Result r = Fail ByteString [String] String@@ -108,3 +109,16 @@ eitherResult (Done _ r) = Right r eitherResult (Fail _ [] msg) = Left msg eitherResult (Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)++-- | Run a parser that cannot be resupplied via a 'T.Partial' result.+--+-- This function does not force a parser to consume all of its input.+-- Instead, any residual input will be discarded. To force a parser+-- to consume all of its input, use something like this:+--+-- @+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')+-- @+parseOnly :: A.Parser a -> ByteString -> Either String a+parseOnly p = eitherResult . parse p+{-# INLINE parseOnly #-}
Data/Attoparsec/Combinator.hs view
@@ -43,11 +43,12 @@ import Control.Applicative (Applicative(..), (<$>)) import Data.Monoid (Monoid(mappend)) #endif-import Control.Applicative (Alternative(..), empty, liftA2, many, (<|>))+import Control.Applicative (Alternative(..), liftA2, many, (<|>)) import Control.Monad (MonadPlus(..)) import Data.Attoparsec.Internal.Types (Parser(..), IResult(..)) import Data.Attoparsec.Internal (endOfInput, atEnd, satisfyElem) import Data.ByteString (ByteString)+import Data.Foldable (asum) import Data.Text (Text) import qualified Data.Attoparsec.Zepto as Z import Prelude hiding (succ)@@ -58,7 +59,7 @@ -- This combinator is provided for compatibility with Parsec. -- attoparsec parsers always backtrack on failure. try :: Parser i a -> Parser i a-try p = p+try = id {-# INLINE try #-} -- | Name the parser, in case failure occurs.@@ -75,7 +76,7 @@ -- until one of them succeeds. Returns the value of the succeeding -- action. choice :: Alternative f => [f a] -> f a-choice = foldr (<|>) empty+choice = asum {-# SPECIALIZE choice :: [Parser ByteString a] -> Parser ByteString a #-} {-# SPECIALIZE choice :: [Parser Text a] -> Parser Text a #-}
Data/Attoparsec/Text.hs view
@@ -360,30 +360,39 @@ {-# SPECIALIZE rational :: Parser Scientific #-} rational = scientifically realToFrac --- | Parse a rational number.+-- | Parse a 'Double'. -- -- This parser accepts an optional leading sign character, followed by--- at least one decimal digit. The syntax similar to that accepted by--- the 'read' function, with the exception that a trailing @\'.\'@ or--- @\'e\'@ /not/ followed by a number is not consumed.+-- at most one decimal digit. The syntax is similar to that accepted by+-- the 'read' function, with the exception that a trailing @\'.\'@ is+-- consumed. --+-- === Examples+--+-- These examples use this helper:+--+-- @+-- r :: 'Parser' a -> 'Data.Text.Text' -> 'Data.Attoparsec.Text.Result' a+-- r p s = 'feed' ('Data.Attoparsec.parse' p s) 'mempty'+-- @+-- -- Examples with behaviour identical to 'read', if you feed an empty -- continuation to the first result: ----- >rational "3" == Done 3.0 ""--- >rational "3.1" == Done 3.1 ""--- >rational "3e4" == Done 30000.0 ""--- >rational "3.1e4" == Done 31000.0, ""+-- > r double "3" == Done "" 3.0+-- > r double "3.1" == Done "" 3.1+-- > r double "3e4" == Done "" 30000.0+-- > r double "3.1e4" == Done "" 31000.0+-- > r double "3e" == Done "e" 3.0 -- -- Examples with behaviour identical to 'read': ----- >rational ".3" == Fail "input does not start with a digit"--- >rational "e3" == Fail "input does not start with a digit"+-- > r double ".3" == Fail ".3" _ _+-- > r double "e3" == Fail "e3" _ _ ----- Examples of differences from 'read':+-- Example of difference from 'read': ----- >rational "3.foo" == Done 3.0 ".foo"--- >rational "3e" == Done 3.0 "e"+-- > r double "3.foo" == Done "foo" 3.0 -- -- This function does not accept string representations of \"NaN\" or -- \"Infinity\".
Data/Attoparsec/Text/Lazy.hs view
@@ -34,6 +34,7 @@ , module Data.Attoparsec.Text -- * Running parsers , parse+ , parseOnly , parseTest -- ** Result conversion , maybeResult@@ -47,7 +48,7 @@ import qualified Data.Attoparsec.Text as A import qualified Data.Text as T import Data.Attoparsec.Text hiding (IResult(..), Result, eitherResult,- maybeResult, parse, parseWith, parseTest)+ maybeResult, parse, parseOnly, parseWith, parseTest) -- | The result of a parse. data Result r = Fail Text [String] String@@ -99,3 +100,16 @@ eitherResult (Done _ r) = Right r eitherResult (Fail _ [] msg) = Left msg eitherResult (Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)++-- | Run a parser that cannot be resupplied via a 'T.Partial' result.+--+-- This function does not force a parser to consume all of its input.+-- Instead, any residual input will be discarded. To force a parser+-- to consume all of its input, use something like this:+--+-- @+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')+-- @+parseOnly :: A.Parser a -> Text -> Either String a+parseOnly p = eitherResult . parse p+{-# INLINE parseOnly #-}
attoparsec.cabal view
@@ -1,12 +1,12 @@ name: attoparsec-version: 0.13.2.5+version: 0.14.1 license: BSD3 license-file: LICENSE category: Text, Parsing author: Bryan O'Sullivan <bos@serpentine.com> maintainer: Bryan O'Sullivan <bos@serpentine.com>, Ben Gamari <ben@smart-cactus.org> stability: experimental-tested-with: GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.1, GHC==8.10.1+tested-with: GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.4, GHC == 9.0.1 synopsis: Fast combinator parsing for bytestrings and text cabal-version: 2.0 homepage: https://github.com/bgamari/attoparsec@@ -46,7 +46,7 @@ scientific >= 0.3.1 && < 0.4, transformers >= 0.2 && (< 0.4 || >= 0.4.1.0) && < 0.6, text >= 1.1.1.3,- ghc-prim <0.7+ ghc-prim <0.8 if impl(ghc < 7.4) build-depends: bytestring < 0.10.4.0
changelog.md view
@@ -1,3 +1,12 @@+0.14.1++* Added `Data.Attoparsec.ByteString.getChunk`.++0.14.0++* Added `Data.Attoparsec.ByteString.takeWhileIncluding`.+* Make `Data.Attoparsec.{Text,ByteString}.Lazy.parseOnly` accept lazy input.+ 0.13.2.1 * Improved performance of `Data.Attoparsec.Text.asciiCI`
tests/QC/ByteString.hs view
@@ -121,6 +121,18 @@ PL.Done t' h' -> t === t' .&&. toStrictBS h === h' _ -> property False +takeWhileIncluding :: Word8 -> L.ByteString -> Property+takeWhileIncluding w s =+ let s' = L.cons w $ L.snoc s (w+1)+ (h_,t_) = L.span (<=w) s'+ (h,t) =+ case L.uncons t_ of+ Nothing -> (h_, t_)+ Just (n, nt) -> (h_ `L.snoc` n, nt)+ in w < 255 ==> case PL.parse (P.takeWhileIncluding (<=w)) s' of+ PL.Done t' h' -> t === t' .&&. toStrictBS h === h'+ _ -> property False+ takeTill :: Word8 -> L.ByteString -> Property takeTill w s = let (h,t) = L.break (==w) s@@ -131,6 +143,19 @@ takeWhile1_empty :: Property takeWhile1_empty = parseBS (P.takeWhile1 undefined) L.empty === Nothing +getChunk :: L.ByteString -> Property+getChunk s =+ maybe (property False) (=== L.toChunks s) $+ parseBS getChunks s+ where getChunks = go []+ go res = do+ mchunk <- P.getChunk+ case mchunk of+ Nothing -> return (reverse res)+ Just chunk -> do+ _ <- P.take (B.length chunk)+ go (chunk:res)+ endOfInput :: L.ByteString -> Property endOfInput s = parseBS P.endOfInput s === if L.null s then Just ()@@ -181,6 +206,8 @@ , testProperty "takeWhile" takeWhile , testProperty "takeWhile1" takeWhile1 , testProperty "takeWhile1_empty" takeWhile1_empty+ , testProperty "takeWhileIncluding" takeWhileIncluding+ , testProperty "getChunk" getChunk , testProperty "word8" word8 , testProperty "members" members , testProperty "nonmembers" nonmembers