packages feed

attoparsec 0.10.4.0 → 0.11.1.0

raw patch · 14 files changed

+202/−119 lines, 14 filesdep +scientificdep ~basedep ~deepseq

Dependencies added: scientific

Dependency ranges changed: base, deepseq

Files

Data/Attoparsec/ByteString.hs view
@@ -47,10 +47,13 @@     , I.word8     , I.anyWord8     , I.notWord8-    , I.peekWord8     , I.satisfy     , I.satisfyWith     , I.skip++    -- ** Lookahead+    , I.peekWord8+    , I.peekWord8'      -- ** Byte classes     , I.inClass
Data/Attoparsec/ByteString/Char8.hs view
@@ -46,9 +46,12 @@     , char8     , anyChar     , notChar-    , peekChar     , satisfy +    -- ** Lookahead+    , peekChar+    , peekChar'+     -- ** Special character parsers     , digit     , letter_iso8859_15@@ -106,7 +109,7 @@     , I.atEnd     ) where -import Control.Applicative ((*>), (<*), (<$>), (<|>))+import Control.Applicative (pure, (*>), (<*), (<$>), (<|>)) import Data.Attoparsec.ByteString.FastSet (charClass, memberChar) import Data.Attoparsec.ByteString.Internal (Parser, (<?>)) import Data.Attoparsec.Combinator@@ -114,8 +117,8 @@ import Data.Bits (Bits, (.|.), shiftL) import Data.ByteString.Internal (c2w, w2c) import Data.Int (Int8, Int16, Int32, Int64)-import Data.Ratio ((%)) import Data.String (IsString(..))+import Data.Scientific (Scientific, scientific, coefficient, base10Exponent) import Data.Word (Word8, Word16, Word32, Word64, Word) import Prelude hiding (takeWhile) import qualified Data.Attoparsec.ByteString as A@@ -223,8 +226,8 @@ anyChar = satisfy $ const True {-# INLINE anyChar #-} --- | Match any character. Returns 'Nothing' if end of input has been--- reached. Does not consume any input.+-- | Match any character, to perform lookahead. 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@@ -233,6 +236,12 @@ peekChar = (fmap w2c) `fmap` I.peekWord8 {-# INLINE peekChar #-} +-- | Match any character, to perform lookahead.  Does not consume any+-- input, but will fail if end of input has been reached.+peekChar' :: Parser Char+peekChar' = w2c `fmap` I.peekWord8'+{-# INLINE peekChar' #-}+ -- | Fast predicate for matching ASCII space characters. -- -- /Note/: This predicate only gives correct answers for the ASCII@@ -471,8 +480,8 @@ {-# SPECIALIZE rational :: Parser Double #-} {-# SPECIALIZE rational :: Parser Float #-} {-# SPECIALIZE rational :: Parser Rational #-}-rational = floaty $ \real frac fracDenom -> fromRational $-                     real % 1 + frac % fracDenom+{-# SPECIALIZE rational :: Parser Scientific #-}+rational = scientifically realToFrac  -- | Parse a rational number. --@@ -490,12 +499,7 @@ -- This function does not accept string representations of \"NaN\" or -- \"Infinity\". double :: Parser Double-double = floaty asDouble--asDouble :: Integer -> Integer -> Integer -> Double-asDouble real frac fracDenom =-    fromIntegral real + fromIntegral frac / fromIntegral fracDenom-{-# INLINE asDouble #-}+double = rational  -- | Parse a number, attempting to preserve both speed and precision. --@@ -507,43 +511,38 @@ -- 'rational'. -- -- This function does not accept string representations of \"NaN\" or--- \"Infinity\".+-- \" number :: Parser Number-number = floaty $ \real frac fracDenom ->-         if frac == 0 && fracDenom == 0-         then I real-         else D (asDouble real frac fracDenom)-{-# INLINE number #-}--data T = T !Integer !Int+number = scientifically $ \s ->+            let e = base10Exponent s+                c = coefficient s+            in if e >= 0+               then I (c * 10 ^ e)+               else D (fromInteger c / 10 ^ negate e) -floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a-{-# INLINE floaty #-}-floaty f = do+{-# INLINE scientifically #-}+scientifically :: (Scientific -> a) -> Parser a+scientifically h = do   let minus = 45       plus  = 43   !positive <- ((== plus) <$> I.satisfy (\c -> c == minus || c == plus)) <|>-               return True-  real <- decimal-  let tryFraction = do-        let dot = 46-        _ <- I.satisfy (==dot)-        ds <- I.takeWhile isDigit_w8-        case I.parseOnly decimal ds of-                Right n -> return $ T n (B.length ds)-                _       -> fail "no digits after decimal"-  T fraction fracDigits <- tryFraction <|> return (T 0 0)+               pure True++  n <- decimal++  let f fracDigits = scientific (B8.foldl' step n fracDigits)+                                (negate $ B8.length fracDigits)+      step a w = a * 10 + fromIntegral (w - 48)++  s <- let dot = 46 in+       (I.satisfy (==dot) *> (f <$> I.takeWhile isDigit_w8)) <|>+         pure (scientific n 0)++  let !signedCoeff | positive  =          coefficient s+                   | otherwise = negate $ coefficient s+   let littleE = 101       bigE    = 69-      e w = w == littleE || w == bigE-  power <- (I.satisfy e *> signed decimal) <|> return (0::Int)-  let n = if fracDigits == 0-          then if power == 0-               then fromIntegral real-               else fromIntegral real * (10 ^^ power)-          else if power == 0-               then f real fraction (10 ^ fracDigits)-               else f real fraction (10 ^ fracDigits) * (10 ^^ power)-  return $ if positive-           then n-           else -n+  (I.satisfy (\c -> c == littleE || c == bigE) *>+      fmap (h . scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>+    return (h $ scientific signedCoeff   (base10Exponent s))
Data/Attoparsec/ByteString/FastSet.hs view
@@ -83,7 +83,7 @@     where search lo hi               | hi < lo = False               | otherwise =-                  let mid = (lo + hi) `div` 2+                  let mid = (lo + hi) `quot` 2                   in case compare w (U.unsafeIndex s mid) of                        GT -> search (mid + 1) hi                        LT -> search lo (mid - 1)
Data/Attoparsec/ByteString/Internal.hs view
@@ -34,7 +34,10 @@     , skip     , word8     , notWord8++    -- ** Lookahead     , peekWord8+    , peekWord8'      -- ** Byte classes     , inClass@@ -426,8 +429,8 @@ 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.+-- | Match any byte, to perform lookahead. 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@@ -444,6 +447,14 @@             else let !w = B.unsafeHead (unI i0)                  in ks i0 a0 m0 (Just w) {-# INLINE peekWord8 #-}++-- | Match any byte, to perform lookahead.  Does not consume any+-- input, but will fail if end of input has been reached.+peekWord8' :: Parser Word8+peekWord8' = do+  s <- ensure 1+  return $! B.unsafeHead s+{-# INLINE peekWord8' #-}  -- | Match only if all input has been consumed. endOfInput :: Parser ()
Data/Attoparsec/ByteString/Lazy.hs view
@@ -7,8 +7,8 @@ -- Stability   :  experimental -- Portability :  unknown ----- Simple, efficient combinator parsing for lazy 'ByteString'--- strings, loosely based on the Parsec library.+-- Simple, efficient combinator parsing that can consume lazy+-- 'ByteString' strings, loosely based on the Parsec library. -- -- This is essentially the same code as in the 'Data.Attoparsec' -- module, only with a 'parse' function that can consume a lazy@@ -16,10 +16,11 @@ -- more input to be fed in.  Think of this as suitable for use with a -- lazily read file, e.g. via 'L.readFile' or 'L.hGetContents'. ----- Behind the scenes, strict 'B.ByteString' values are still used--- internally to store parser input and manipulate it efficiently.--- High-performance parsers such as 'string' still expect strict--- 'B.ByteString' parameters.+-- /Note:/ The various parser functions and combinators such as+-- 'string' still expect /strict/ 'B.ByteString' parameters, and+-- return strict 'B.ByteString' results.  Behind the scenes, strict+-- 'B.ByteString' values are still used internally to store parser+-- input and manipulate it efficiently.  module Data.Attoparsec.ByteString.Lazy     (
Data/Attoparsec/Number.hs view
@@ -10,10 +10,7 @@ -- -- A simple number type, useful for parsing both exact and inexact -- quantities without losing much precision.-module Data.Attoparsec.Number-    (-      Number(..)-    ) where+module Data.Attoparsec.Number ( Number(..) ) where  import Control.DeepSeq (NFData(rnf)) import Data.Data (Data)
Data/Attoparsec/Text.hs view
@@ -52,7 +52,10 @@     , I.satisfy     , I.satisfyWith     , I.skip++    -- ** Lookahead     , I.peekChar+    , I.peekChar'      -- ** Special character parsers     , digit@@ -103,14 +106,14 @@     , I.atEnd     ) where -import Control.Applicative ((<$>), (*>), (<*), (<|>))+import Control.Applicative (pure, (<$>), (*>), (<*), (<|>)) import Data.Attoparsec.Combinator import Data.Attoparsec.Number (Number(..))+import Data.Scientific (Scientific, scientific, coefficient, base10Exponent) import Data.Attoparsec.Text.Internal ((<?>), Parser, Result, parse, takeWhile1) import Data.Bits (Bits, (.|.), shiftL) import Data.Char (isAlpha, isDigit, isSpace, ord) import Data.Int (Int8, Int16, Int32, Int64)-import Data.Ratio ((%)) import Data.Text (Text) import Data.Word (Word8, Word16, Word32, Word64, Word) import qualified Data.Attoparsec.Internal as I@@ -343,8 +346,8 @@ {-# SPECIALIZE rational :: Parser Double #-} {-# SPECIALIZE rational :: Parser Float #-} {-# SPECIALIZE rational :: Parser Rational #-}-rational = floaty $ \real frac fracDenom -> fromRational $-                     real % 1 + frac % fracDenom+{-# SPECIALIZE rational :: Parser Scientific #-}+rational = scientifically realToFrac  -- | Parse a rational number. --@@ -362,12 +365,7 @@ -- This function does not accept string representations of \"NaN\" or -- \"Infinity\". double :: Parser Double-double = floaty asDouble--asDouble :: Integer -> Integer -> Integer -> Double-asDouble real frac fracDenom =-    fromIntegral real + fromIntegral frac / fromIntegral fracDenom-{-# INLINE asDouble #-}+double = rational  -- | Parse a number, attempting to preserve both speed and precision. --@@ -381,12 +379,35 @@ -- This function does not accept string representations of \"NaN\" or -- \"Infinity\". number :: Parser Number-number = floaty $ \real frac fracDenom ->-         if frac == 0 && fracDenom == 0-         then I real-         else D (asDouble real frac fracDenom)-{-# INLINE number #-}+number = scientifically $ \s ->+            let e = base10Exponent s+                c = coefficient s+            in if e >= 0+               then I (c * 10 ^ e)+               else D (fromInteger c / 10 ^ negate e) +{-# INLINE scientifically #-}+scientifically :: (Scientific -> a) -> Parser a+scientifically h = do+  !positive <- ((== '+') <$> I.satisfy (\c -> c == '-' || c == '+')) <|>+               pure True++  n <- decimal++  let f fracDigits = scientific (T.foldl' step n fracDigits)+                                (negate $ T.length fracDigits)+      step a c = a * 10 + fromIntegral (ord c - 48)++  s <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>+         pure (scientific n 0)++  let !signedCoeff | positive  =          coefficient s+                   | otherwise = negate $ coefficient s++  (I.satisfy (\c -> c == 'e' || c == 'E') *>+      fmap (h . scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>+    return (h $ scientific signedCoeff   (base10Exponent s))+ -- | Parse a single digit, as recognised by 'isDigit'. digit :: Parser Char digit = I.satisfy isDigit <?> "digit"@@ -433,31 +454,3 @@ -- | Type-specialized version of '<*' for 'Text'. (<*.) :: Parser a -> Text -> Parser a f <*. s = f <* I.string s--data T = T !Integer !Int--floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a-{-# INLINE floaty #-}-floaty f = do-  !positive <- ((== '+') <$> I.satisfy (\c -> c == '-' || c == '+')) <|>-               return True-  real <- decimal-  let tryFraction = do-        _ <- I.satisfy (=='.')-        ds <- I.takeWhile isDigit-        case I.parseOnly decimal ds of-                Right n -> return $ T n (T.length ds)-                _       -> fail "no digits after decimal"-  T fraction fracDigits <- tryFraction <|> return (T 0 0)-  let e c = c == 'e' || c == 'E'-  power <- (I.satisfy e *> signed decimal) <|> return (0::Int)-  let n = if fracDigits == 0-          then if power == 0-               then fromIntegral real-               else fromIntegral real * (10 ^^ power)-          else if power == 0-               then f real fraction (10 ^ fracDigits)-               else f real fraction (10 ^ fracDigits) * (10 ^^ power)-  return $ if positive-           then n-           else -n
Data/Attoparsec/Text/FastSet.hs view
@@ -50,7 +50,7 @@     where search lo hi               | hi < lo = False               | otherwise =-                  let mid = (lo + hi) `div` 2+                  let mid = (lo + hi) `quot` 2                   in case compare c (AB.unsafeAt a mid) of                        GT -> search (mid + 1) hi                        LT -> search lo (mid - 1)
Data/Attoparsec/Text/Internal.hs view
@@ -35,7 +35,10 @@     , skip     , char     , notChar++    -- ** Lookahead     , peekChar+    , peekChar'      -- ** Character classes     , inClass@@ -90,7 +93,7 @@     fromString = string . T.pack  lengthAtLeast :: T.Text -> Int -> Bool-lengthAtLeast t@(T.Text _ _ len) n = (len `div` 2) >= n || T.length t >= n+lengthAtLeast t@(T.Text _ _ len) n = (len `quot` 2) >= n || T.length t >= n {-# INLINE lengthAtLeast #-}  -- | If at least @n@ characters of input are available, return the@@ -440,8 +443,8 @@ 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.+-- | Match any character, to perform lookahead. 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@@ -458,6 +461,14 @@            else let !c = unsafeHead (unI i0)                 in ks i0 a0 m0 (Just c) {-# INLINE peekChar #-}++-- | Match any character, to perform lookahead.  Does not consume any+-- input, but will fail if end of input has been reached.+peekChar' :: Parser Char+peekChar' = do+  s <- ensure 1+  return $! unsafeHead s+{-# INLINE peekChar' #-}  -- | Match only if all input has been consumed. endOfInput :: Parser ()
Data/Attoparsec/Text/Lazy.hs view
@@ -7,7 +7,7 @@ -- Stability   :  experimental -- Portability :  unknown ----- Simple, efficient combinator parsing for lazy 'Text'+-- Simple, efficient combinator parsing that can consume lazy 'Text' -- strings, loosely based on the Parsec library. -- -- This is essentially the same code as in the 'Data.Attoparsec.Text'@@ -16,10 +16,11 @@ -- more input to be fed in.  Think of this as suitable for use with a -- lazily read file, e.g. via 'L.readFile' or 'L.hGetContents'. ----- Behind the scenes, strict 'T.Text' values are still used--- internally to store parser input and manipulate it efficiently.--- High-performance parsers such as 'string' still expect strict--- 'T.Text' parameters.+-- /Note:/ The various parser functions and combinators such as+-- 'string' still expect /strict/ 'T.Text' parameters, and return+-- strict 'T.Text' results.  Behind the scenes, strict 'T.Text' values+-- are still used internally to store parser input and manipulate it+-- efficiently.  module Data.Attoparsec.Text.Lazy     (
attoparsec.cabal view
@@ -1,12 +1,12 @@ name:            attoparsec-version:         0.10.4.0+version:         0.11.1.0 license:         BSD3 license-file:    LICENSE category:        Text, Parsing author:          Bryan O'Sullivan <bos@serpentine.com> maintainer:      Bryan O'Sullivan <bos@serpentine.com> stability:       experimental-tested-with:     GHC == 6.12.3, GHC == 7.0.3, GHC == 7.2.1, GHC == 7.4.2, GHC == 7.6.1+tested-with:     GHC == 7.0, GHC == 7.2, GHC == 7.4, GHC == 7.6, GHC == 7.8 synopsis:        Fast combinator parsing for bytestrings and text cabal-version:   >= 1.8 homepage:        https://github.com/bos/attoparsec@@ -23,6 +23,7 @@     benchmarks/Tiny.hs     benchmarks/attoparsec-benchmarks.cabal     benchmarks/med.txt.bz2+    changelog     examples/Makefile     examples/Parsec_RFC2616.hs     examples/RFC2616.hs@@ -43,7 +44,8 @@                  bytestring,                  containers,                  deepseq,-                 text >= 0.11.1.5+                 text >= 0.11.1.5,+                 scientific >= 0.2    exposed-modules: Data.Attoparsec                    Data.Attoparsec.ByteString
benchmarks/Benchmarks.hs view
@@ -6,6 +6,7 @@ import Data.Bits (unsafeShiftL) import Data.ByteString.Internal (ByteString(..)) import Data.Char+import Data.Scientific (Scientific(..)) import Data.Word (Word32) import Text.Parsec.Text () import Text.Parsec.Text.Lazy ()@@ -80,6 +81,60 @@    , bgroup "scan" [        bench "short" $ nf (AB.parse quotedString) (BC.pack "abcdefghijk\"")      , bench "long" $ nf (AB.parse quotedString) b+     ]++   , let strN     = "1234.56789"+         strNePos = "1234.56789e3"+         strNeNeg = "1234.56789e-3"+     in+     bgroup "numbers"+     [ let !tN     = T.pack strN+           !tNePos = T.pack strNePos+           !tNeNeg = T.pack strNeNeg+       in bgroup "Text"+       [+         bgroup "no power"+         [ bench "double"     $ nf (AT.parseOnly AT.double)                            tN+         , bench "number"     $ nf (AT.parseOnly AT.number)                            tN+         , bench "rational"   $ nf (AT.parseOnly (AT.rational :: AT.Parser Rational))  tN+         , bench "scientific" $ nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tN+         ]+       , bgroup "positive power"+         [ bench "double"     $ nf (AT.parseOnly AT.double)                            tNePos+         , bench "number"     $ nf (AT.parseOnly AT.number)                            tNePos+         , bench "rational"   $ nf (AT.parseOnly (AT.rational :: AT.Parser Rational))  tNePos+         , bench "scientific" $ nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tNePos+         ]+       , bgroup "negative power"+         [ bench "double"     $ nf (AT.parseOnly AT.double)                            tNeNeg+         , bench "number"     $ nf (AT.parseOnly AT.number)                            tNeNeg+         , bench "rational"   $ nf (AT.parseOnly (AT.rational :: AT.Parser Rational))  tNeNeg+         , bench "scientific" $ nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tNeNeg+         ]+       ]+     , let !bN     = BC.pack strN+           !bNePos = BC.pack strNePos+           !bNeNeg = BC.pack strNeNeg+       in bgroup "ByteString"+       [ bgroup "no power"+         [ bench "double"     $ nf (AC.parseOnly AC.double)                             bN+         , bench "number"     $ nf (AC.parseOnly AC.number)                             bN+         , bench "rational"   $ nf (AC.parseOnly (AC.rational :: AC.Parser Rational))   bN+         , bench "scientific" $ nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bN+         ]+       , bgroup "positive power"+         [ bench "double"     $ nf (AC.parseOnly AC.double)                             bNePos+         , bench "number"     $ nf (AC.parseOnly AC.number)                             bNePos+         , bench "rational"   $ nf (AC.parseOnly (AC.rational :: AC.Parser Rational))   bNePos+         , bench "scientific" $ nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bNePos+         ]+       , bgroup "negative power"+         [ bench "double"     $ nf (AC.parseOnly AC.double)                             bNeNeg+         , bench "number"     $ nf (AC.parseOnly AC.number)                             bNeNeg+         , bench "rational"   $ nf (AC.parseOnly (AC.rational :: AC.Parser Rational))   bNeNeg+         , bench "scientific" $ nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bNeNeg+         ]+       ]      ]    ] 
benchmarks/attoparsec-benchmarks.cabal view
@@ -3,16 +3,19 @@  name: attoparsec-benchmarks version: 0-cabal-version: >=1.2+cabal-version: >=1.6 build-type: Simple  executable attoparsec-benchmarks   main-is: Benchmarks.hs+  hs-source-dirs: .. .+  ghc-options: -O2   build-depends:-    attoparsec,-    base,+    array,+    base == 4.*,     bytestring,     criterion >= 0.5,-    deepseq == 1.1.*,+    deepseq >= 1.1,     parsec >= 3.1.2,+    scientific,     text
+ changelog view
@@ -0,0 +1,7 @@+0.11.1.0++	* New dependency: the scientific package.  This allows us to parse+	  numbers much more efficiently.++	* peekWord8', peekChar': new primitive parsers that allow+	  single-character lookahead.