packages feed

attoparsec 0.10.1.1 → 0.10.2.0

raw patch · 12 files changed

+279/−26 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Attoparsec.ByteString: peekWord8 :: Parser (Maybe Word8)
+ Data.Attoparsec.ByteString.Char8: (.*>) :: ByteString -> Parser a -> Parser a
+ Data.Attoparsec.ByteString.Char8: (<*.) :: Parser a -> ByteString -> Parser a
+ Data.Attoparsec.ByteString.Char8: peekChar :: Parser (Maybe Char)
+ Data.Attoparsec.ByteString.Lazy: instance NFData r => NFData (Result r)
+ Data.Attoparsec.Text: (.*>) :: Text -> Parser a -> Parser a
+ Data.Attoparsec.Text: (<*.) :: Parser a -> Text -> Parser a
+ Data.Attoparsec.Text: peekChar :: Parser (Maybe Char)
+ Data.Attoparsec.Text.Lazy: instance NFData r => NFData (Result r)

Files

Data/Attoparsec/ByteString.hs view
@@ -46,6 +46,7 @@     , I.word8     , I.anyWord8     , I.notWord8+    , I.peekWord8     , I.satisfy     , I.satisfyWith     , I.skip
Data/Attoparsec/ByteString/Char8.hs view
@@ -44,6 +44,7 @@     , char8     , anyChar     , notChar+    , peekChar     , satisfy      -- ** Special character parsers@@ -75,6 +76,11 @@     , takeWhile1     , takeTill +    -- ** String combinators+    -- $specalt+    , (.*>)+    , (<*.)+     -- ** Consume all remaining input     , I.takeByteString     , I.takeLazyByteString@@ -98,7 +104,7 @@     , I.atEnd     ) where -import Control.Applicative ((*>), (<$>), (<|>))+import Control.Applicative ((*>), (<*), (<$>), (<|>)) import Data.Attoparsec.ByteString.FastSet (charClass, memberChar) import Data.Attoparsec.ByteString.Internal (Parser, (<?>)) import Data.Attoparsec.Combinator@@ -214,6 +220,16 @@ anyChar = satisfy $ const True {-# INLINE anyChar #-} +-- | Match any character. Returns 'Nothing' if end of input has been+-- reached. Does not consume any input.+--+-- /Note/: Because this parser does not fail, do not use it with+-- combinators such as 'many', because such parsers loop until a+-- failure occurs.  Careless use will thus result in an infinite loop.+peekChar :: Parser (Maybe Char)+peekChar = (fmap w2c) `fmap` I.peekWord8+{-# INLINE peekChar #-}+ -- | Fast predicate for matching ASCII space characters. -- -- /Note/: This predicate only gives correct answers for the ASCII@@ -327,6 +343,33 @@ skipSpace = I.skipWhile isSpace_w8 {-# INLINE skipSpace #-} +-- $specalt+--+-- The '.*>' and '<*.' combinators are intended for use with the+-- @OverloadedStrings@ language extension.  They simplify the common+-- task of matching a statically known string, then immediately+-- parsing something else.+--+-- An example makes this easier to understand:+--+-- @{-\# LANGUAGE OverloadedStrings #-}+--+-- shoeSize = \"Shoe size: \" '.*>' 'decimal'+-- @+--+-- If we were to try to use '*>' above instead, the type checker would+-- not be able to tell which 'IsString' instance to use for the text+-- in quotes.  We would have to be explicit, using either a type+-- signature or the 'I.string' parser.++-- | Type-specialized version of '*>' for 'B.ByteString'.+(.*>) :: B.ByteString -> Parser a -> Parser a+s .*> f = I.string s *> f++-- | Type-specialized version of '<*' for 'B.ByteString'.+(<*.) :: Parser a -> B.ByteString -> Parser a+f <*. s = f <* I.string s+ -- | A predicate that matches either a carriage return @\'\\r\'@ or -- newline @\'\\n\'@ character. isEndOfLine :: Word8 -> Bool@@ -408,7 +451,7 @@ -- >rational "3.1"   == Done 3.1 "" -- >rational "3e4"   == Done 30000.0 "" -- >rational "3.1e4" == Done 31000.0, ""-+-- -- Examples with behaviour identical to 'read': -- -- >rational ".3"    == Fail "input does not start with a digit"
Data/Attoparsec/ByteString/Internal.hs view
@@ -33,6 +33,7 @@     , skip     , word8     , notWord8+    , peekWord8      -- ** Byte classes     , inClass@@ -58,7 +59,6 @@     -- * State observation and manipulation functions     , endOfInput     , atEnd-    , ensure      -- * Utilities     , endOfLine@@ -399,6 +399,22 @@ notWord8 :: Word8 -> Parser Word8 notWord8 c = satisfy (/= c) <?> "not " ++ show c {-# INLINE notWord8 #-}++-- | Match any byte. Returns 'Nothing' if end of input has been+-- reached. Does not consume any input.+--+-- /Note/: Because this parser does not fail, do not use it with+-- combinators such as 'many', because such parsers loop until a+-- failure occurs.  Careless use will thus result in an infinite loop.+peekWord8 :: Parser (Maybe Word8)+peekWord8 = T.Parser $ \i0 a0 m0 _kf ks ->+            let ks' i a m = let w = B.unsafeHead (unI i)+                            in w `seq` ks i a m (Just w)+                kf' i a m = ks i a m Nothing+            in if B.null (unI i0)+               then prompt i0 a0 m0 kf' ks'+               else ks' i0 a0 m0+{-# INLINE peekWord8 #-}  -- | Match only if all input has been consumed. endOfInput :: Parser ()
Data/Attoparsec/ByteString/Lazy.hs view
@@ -33,6 +33,7 @@     , eitherResult     ) where +import Control.DeepSeq (NFData(rnf)) import Data.ByteString.Lazy.Internal (ByteString(..), chunk) import qualified Data.ByteString as B import qualified Data.Attoparsec.ByteString as A@@ -52,6 +53,16 @@               -- ^ The parse succeeded.  The 'ByteString' is the               -- input that had not yet been consumed (if any) when               -- the parse succeeded.++instance NFData r => NFData (Result r) where+    rnf (Fail bs ctxs msg) = rnfBS bs `seq` rnf ctxs `seq` rnf msg+    rnf (Done bs r)        = rnfBS bs `seq` rnf r+    {-# INLINE rnf #-}++rnfBS :: ByteString -> ()+rnfBS (Chunk _ xs) = rnfBS xs+rnfBS Empty        = ()+{-# INLINE rnfBS #-}  instance Show r => Show (Result r) where     show (Fail bs stk msg) =
Data/Attoparsec/Text.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BangPatterns, FlexibleInstances, TypeSynonymInstances #-}+ -- | -- Module      :  Data.Attoparsec.Text -- Copyright   :  Bryan O'Sullivan 2011@@ -50,6 +51,7 @@     , I.satisfy     , I.satisfyWith     , I.skip+    , I.peekChar      -- ** Special character parsers     , digit@@ -62,7 +64,7 @@      -- * Efficient string handling     , I.string-    , stringCI+    , I.stringCI     , skipSpace     , I.skipWhile     , I.scan@@ -71,6 +73,11 @@     , I.takeWhile1     , I.takeTill +    -- ** String combinators+    -- $specalt+    , (.*>)+    , (<*.)+     -- ** Consume all remaining input     , I.takeText     , I.takeLazyText@@ -94,7 +101,7 @@     , I.atEnd     ) where -import Control.Applicative ((<$>), (*>), (<|>))+import Control.Applicative ((<$>), (*>), (<*), (<|>)) import Data.Attoparsec.Combinator import Data.Attoparsec.Number (Number(..)) import Data.Attoparsec.Text.Internal ((<?>), Parser, Result, parse, takeWhile1)@@ -316,7 +323,7 @@ -- >rational "3.1"   == Done 3.1 "" -- >rational "3e4"   == Done 30000.0 "" -- >rational "3.1e4" == Done 31000.0, ""-+-- -- Examples with behaviour identical to 'read': -- -- >rational ".3"    == Fail "input does not start with a digit"@@ -392,15 +399,37 @@ space = I.satisfy isSpace <?> "space" {-# INLINE space #-} --- | Satisfy a literal string, ignoring case.-stringCI :: Text -> Parser Text-stringCI = I.stringTransform T.toCaseFold-{-# INLINE stringCI #-}- -- | Skip over white space. skipSpace :: Parser () skipSpace = I.skipWhile isSpace {-# INLINE skipSpace #-}++-- $specalt+--+-- The '.*>' and '<*.' combinators are intended for use with the+-- @OverloadedStrings@ language extension.  They simplify the common+-- task of matching a statically known string, then immediately+-- parsing something else.+--+-- An example makes this easier to understand:+--+-- @{-\# LANGUAGE OverloadedStrings #-}+--+-- shoeSize = \"Shoe size: \" '.*>' 'decimal'+-- @+--+-- If we were to try to use '*>' above instead, the type checker would+-- not be able to tell which 'IsString' instance to use for the text+-- in quotes.  We would have to be explicit, using either a type+-- signature or the 'I.string' parser.++-- | Type-specialized version of '*>' for 'Text'.+(.*>) :: Text -> Parser a -> Parser a+s .*> f = I.string s *> f++-- | Type-specialized version of '<*' for 'Text'.+(<*.) :: Parser a -> Text -> Parser a+f <*. s = f <* I.string s  data T = T !Integer !Int 
Data/Attoparsec/Text/Internal.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE BangPatterns, Rank2Types, OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE BangPatterns, FlexibleInstances, OverloadedStrings, Rank2Types,+    RecordWildCards, TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      :  Data.Attoparsec.Text.Internal -- Copyright   :  Bryan O'Sullivan 2011@@ -33,6 +35,7 @@     , skip     , char     , notChar+    , peekChar      -- ** Character classes     , inClass@@ -41,7 +44,7 @@     -- * Efficient string handling     , skipWhile     , string-    , stringTransform+    , stringCI     , take     , scan     , takeWhile@@ -55,7 +58,6 @@     -- * State observation and manipulation functions     , endOfInput     , atEnd-    , ensure      -- * Utilities     , endOfLine@@ -65,6 +67,7 @@ import Control.Monad (when) import Data.Attoparsec.Combinator import Data.Attoparsec.Internal.Types hiding (Parser, Input, Added, Failure, Success)+import Data.String (IsString(..)) import Data.Text (Text) import Prelude hiding (getChar, take, takeWhile) import qualified Data.Attoparsec.Internal.Types as T@@ -79,6 +82,9 @@ type Failure r = T.Failure Text r type Success a r = T.Success Text a r +instance IsString (Parser Text) where+    fromString = string . T.pack+ -- | If at least @n@ characters of input are available, return the -- current input, otherwise fail. ensure :: Int -> Parser Text@@ -219,10 +225,25 @@ string s = takeWith (T.length s) (==s) {-# INLINE string #-} -stringTransform :: (Text -> Text) -> Text-                -> Parser Text-stringTransform f s = takeWith (T.length s) ((==f s) . f)-{-# INLINE stringTransform #-}+-- | Satisfy a literal string, ignoring case.+--+-- Note: this function is currently quite inefficient. Unicode case+-- folding can change the length of a string (\"&#223;\" becomes+-- "ss"), which makes a simple, efficient implementation tricky.  We+-- have (for now) chosen simplicity over efficiency.+stringCI :: Text -> Parser Text+stringCI s = go 0+  where+    go !n+      | n > T.length fs = fail "stringCI"+      | otherwise = do+      t <- ensure n+      let h = unsafeTake n t+      if T.toCaseFold h == fs+        then put (unsafeDrop n t) >> return h+        else go (n+1)+    fs = T.toCaseFold s+{-# INLINE stringCI #-}  -- | Skip past input for as long as the predicate returns 'True'. skipWhile :: (Char -> Bool) -> Parser ()@@ -381,6 +402,22 @@ notChar :: Char -> Parser Char notChar c = satisfy (/= c) <?> "not " ++ show c {-# INLINE notChar #-}++-- | Match any character. Returns 'Nothing' if end of input has been+-- reached. Does not consume any input.+--+-- /Note/: Because this parser does not fail, do not use it with+-- combinators such as 'many', because such parsers loop until a+-- failure occurs.  Careless use will thus result in an infinite loop.+peekChar :: Parser (Maybe Char)+peekChar = T.Parser $ \i0 a0 m0 _kf ks ->+       let ks' i a m = let w = unsafeHead (unI i)+                       in w `seq` ks i a m (Just w)+           kf' i a m = ks i a m Nothing+       in if T.null (unI i0)+          then prompt i0 a0 m0 kf' ks'+          else ks' i0 a0 m0+{-# INLINE peekChar #-}  -- | Match only if all input has been consumed. endOfInput :: Parser ()
Data/Attoparsec/Text/Lazy.hs view
@@ -33,6 +33,7 @@     , eitherResult     ) where +import Control.DeepSeq (NFData(rnf)) import Data.Text.Lazy.Internal (Text(..), chunk) import qualified Data.Attoparsec.Internal.Types as T import qualified Data.Attoparsec.Text as A@@ -56,6 +57,11 @@     show (Fail bs stk msg) =         "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg     show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r++instance NFData r => NFData (Result r) where+    rnf (Fail bs ctxs msg) = rnf bs `seq` rnf ctxs `seq` rnf msg+    rnf (Done bs r)        = rnf bs `seq` rnf r+    {-# INLINE rnf #-}  fmapR :: (a -> b) -> Result a -> Result b fmapR _ (Fail st stk msg) = Fail st stk msg
attoparsec.cabal view
@@ -1,5 +1,5 @@ name:            attoparsec-version:         0.10.1.1+version:         0.10.2.0 license:         BSD3 license-file:    LICENSE category:        Text, Parsing@@ -17,15 +17,17 @@     efficiently with network protocols and complicated text/binary     file formats. extra-source-files:+    README.markdown+    benchmarks/Benchmarks.hs     benchmarks/Makefile-    benchmarks/med.txt.bz2     benchmarks/Tiny.hs+    benchmarks/attoparsec-benchmarks.cabal+    benchmarks/med.txt.bz2     examples/Makefile     examples/Parsec_RFC2616.hs-    examples/rfc2616.c     examples/RFC2616.hs     examples/TestRFC2616.hs-    README.markdown+    examples/rfc2616.c     tests/Makefile     tests/QC.hs     tests/QC/*.hs@@ -61,7 +63,7 @@                    Data.Attoparsec.Internal.Types                    Data.Attoparsec.Text.FastSet                    Data.Attoparsec.Text.Internal-  ghc-options:     -Wall+  ghc-options: -O2 -Wall    if flag(developer)     ghc-prof-options: -auto-all
+ benchmarks/Benchmarks.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE BangPatterns #-}++import Control.Applicative+import Control.DeepSeq (NFData(rnf))+import Criterion.Main (bench, bgroup, defaultMain, nf, whnf)+import Data.ByteString.Internal (ByteString(..))+import Data.Char+import Text.Parsec.Text ()+import Text.Parsec.Text.Lazy ()+import qualified Data.Attoparsec.ByteString as AB+import qualified Data.Attoparsec.ByteString.Char8 as AC+import qualified Data.Attoparsec.ByteString.Lazy as ABL+import qualified Data.Attoparsec.Text as AT+import qualified Data.Attoparsec.Text.Lazy as ATL+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Lazy as BL+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Text.Parsec as P++instance NFData ByteString where+    rnf (PS _ _ _) = ()++instance NFData P.ParseError where+    rnf = rnf . show++chunksOf :: Int -> [a] -> [[a]]+chunksOf k = go+  where go xs = case splitAt k xs of+                  ([],_)  -> []+                  (y, ys) -> y : go ys++fromLazy :: BL.ByteString -> B.ByteString+fromLazy = B.concat . BL.toChunks++main = do+  let s  = take 1024 . cycle $ ['a'..'z'] ++ ['A'..'Z']+      !b = BC.pack s+      !bl = BL.fromChunks . map BC.pack . chunksOf 4 $ s+      !t = T.pack s+      !tl = TL.fromChunks . map T.pack . chunksOf 4 $ s+  defaultMain [+     bgroup "many" [+       bgroup "attoparsec" [+         bench "B" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b+       , bench "BL" $ nf (ABL.parse (many (AC.satisfy AC.isAlpha_ascii))) bl+       , bench "T" $ nf (AT.parse (many (AT.satisfy AC.isAlpha_ascii))) t+       , bench "TL" $ nf (ATL.parse (many (AT.satisfy AC.isAlpha_ascii))) tl+       ]+     , bgroup "parsec" [+         bench "S" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") s+       , bench "B" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") b+       , bench "BL" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") bl+       , bench "T" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") t+       , bench "TL" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") tl+       ]+     ]+   , bgroup "comparison" [+       bgroup "many-vs-takeWhile" [+         bench "many" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b+       , bench "takeWhile" $ nf (AB.parse (AC.takeWhile AC.isAlpha_ascii)) b+       ]+     , bgroup "letter-vs-isAlpha" [+         bench "letter" $ nf (AB.parse (many AC.letter_ascii)) b+       , bench "isAlpha" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b+       ]+     ]+   , bgroup "takeWhile" [+       bench "isAlpha" $ nf (ABL.parse (AC.takeWhile isAlpha)) bl+     , bench "isAlpha_ascii" $ nf (ABL.parse (AC.takeWhile AC.isAlpha_ascii)) bl+     , bench "isAlpha_iso8859_15" $ nf (ABL.parse (AC.takeWhile AC.isAlpha_iso8859_15)) bl+     ]+   ]
+ benchmarks/attoparsec-benchmarks.cabal view
@@ -0,0 +1,18 @@+-- These benchmarks are not intended to be installed.+-- So don't install 'em.++name: attoparsec-benchmarks+version: 0+cabal-version: >=1.2+build-type: Simple++executable attoparsec-benchmarks+  main-is: Benchmarks.hs+  build-depends:+    attoparsec,+    base,+    bytestring,+    criterion >= 0.5,+    deepseq == 1.1.*,+    parsec >= 3.1.2,+    text
tests/QC/ByteString.hs view
@@ -2,7 +2,7 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module QC.ByteString (tests) where -import Control.Applicative ((<$>))+import Control.Applicative ((<$>), (<*>)) import Prelude hiding (takeWhile) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck@@ -48,6 +48,11 @@     where v = L.head bs           bs = L.pack s +peekWord8 s+    | L.null s  = p == Just (Nothing, s)+    | otherwise = p == Just (Just (L.head s), s)+  where p = maybeP ((,) <$> P.peekWord8 <*> P.takeLazyByteString) s+ string s t = maybeP (P.string s') (s `L.append` t) == Just s'   where s' = toStrict s @@ -94,6 +99,7 @@     testProperty "word8" word8,     testProperty "notWord8" notWord8,     testProperty "anyWord8" anyWord8,+    testProperty "peekWord8" peekWord8,     testProperty "string" string,     testProperty "skipWhile" skipWhile,     testProperty "takeCount" takeCount,
tests/QC/Text.hs view
@@ -2,7 +2,7 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module QC.Text (tests) where -import Control.Applicative ((<$>))+import Control.Applicative ((<$>), (<*>)) import Prelude hiding (takeWhile) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck@@ -48,9 +48,17 @@     where v = L.head bs           bs = L.pack s +peekChar s+    | L.null s  = p == Just (Nothing, s)+    | otherwise = p == Just (Just (L.head s), s)+  where p = maybeP ((,) <$> P.peekChar <*> P.takeLazyText) s+ string s t = maybeP (P.string s') (s `L.append` t) == Just s'   where s' = toStrict s +stringCI s = P.parseOnly (P.stringCI fs) s == Right s+  where fs = T.toCaseFold s+ toStrict = T.concat . L.toChunks  skipWhile w s =@@ -94,7 +102,9 @@     testProperty "char" char,     testProperty "notChar" notChar,     testProperty "anyChar" anyChar,+    testProperty "peekChar" peekChar,     testProperty "string" string,+    testProperty "stringCI" stringCI,     testProperty "skipWhile" skipWhile,     testProperty "takeCount" takeCount,     testProperty "takeWhile" takeWhile,