packages feed

attoparsec 0.8.4.0 → 0.8.5.0

raw patch · 6 files changed

+542/−185 lines, 6 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.Attoparsec: ensure :: Int -> Parser ()
- Data.Attoparsec: instance Functor Result
- Data.Attoparsec: instance Show r => Show (Result r)
- Data.Attoparsec.Char8: ensure :: Int -> Parser ()
+ Data.Attoparsec: atEnd :: Parser Bool
+ Data.Attoparsec: parseOnly :: Parser a -> ByteString -> Either String a
+ Data.Attoparsec: takeByteString :: Parser ByteString
+ Data.Attoparsec: takeLazyByteString :: Parser ByteString
+ Data.Attoparsec.Char8: D :: {-# UNPACK #-} !Double -> Number
+ Data.Attoparsec.Char8: I :: !Integer -> Number
+ Data.Attoparsec.Char8: atEnd :: Parser Bool
+ Data.Attoparsec.Char8: data Number
+ Data.Attoparsec.Char8: number :: Parser Number
+ Data.Attoparsec.Char8: takeByteString :: Parser ByteString
+ Data.Attoparsec.Char8: takeLazyByteString :: Parser ByteString
+ Data.Attoparsec.Number: D :: {-# UNPACK #-} !Double -> Number
+ Data.Attoparsec.Number: I :: !Integer -> Number
+ Data.Attoparsec.Number: data Number
+ Data.Attoparsec.Number: instance Data Number
+ Data.Attoparsec.Number: instance Eq Number
+ Data.Attoparsec.Number: instance Fractional Number
+ Data.Attoparsec.Number: instance Num Number
+ Data.Attoparsec.Number: instance Ord Number
+ Data.Attoparsec.Number: instance Real Number
+ Data.Attoparsec.Number: instance RealFrac Number
+ Data.Attoparsec.Number: instance Show Number
+ Data.Attoparsec.Number: instance Typeable Number
+ Data.Attoparsec.Zepto: atEnd :: Parser Bool
+ Data.Attoparsec.Zepto: data Parser a
+ Data.Attoparsec.Zepto: instance Alternative Parser
+ Data.Attoparsec.Zepto: instance Applicative Parser
+ Data.Attoparsec.Zepto: instance Functor Parser
+ Data.Attoparsec.Zepto: instance Monad Parser
+ Data.Attoparsec.Zepto: instance MonadPlus Parser
+ Data.Attoparsec.Zepto: instance Monoid (Parser a)
+ Data.Attoparsec.Zepto: parse :: Parser a -> ByteString -> Either String a
+ Data.Attoparsec.Zepto: string :: ByteString -> Parser ()
+ Data.Attoparsec.Zepto: take :: Int -> Parser ByteString
+ Data.Attoparsec.Zepto: takeWhile :: (Word8 -> Bool) -> Parser ByteString
- Data.Attoparsec: Done :: !ByteString -> r -> Result r
+ Data.Attoparsec: Done :: ByteString -> r -> Result r
- Data.Attoparsec: Fail :: !ByteString -> [String] -> String -> Result r
+ Data.Attoparsec: Fail :: ByteString -> [String] -> String -> Result r
- Data.Attoparsec.Char8: Done :: !ByteString -> r -> Result r
+ Data.Attoparsec.Char8: Done :: ByteString -> r -> Result r
- Data.Attoparsec.Char8: Fail :: !ByteString -> [String] -> String -> Result r
+ Data.Attoparsec.Char8: Fail :: ByteString -> [String] -> String -> Result r
- Data.Attoparsec.Char8: hexadecimal :: Integral a => Parser a
+ Data.Attoparsec.Char8: hexadecimal :: (Integral a, Bits a) => Parser a
- Data.Attoparsec.Char8: rational :: RealFloat a => Parser a
+ Data.Attoparsec.Char8: rational :: Fractional a => Parser a

Files

Data/Attoparsec.hs view
@@ -15,6 +15,9 @@     -- * Differences from Parsec     -- $parsec +    -- * Incremental input+    -- $incremental+     -- * Performance considerations     -- $performance @@ -28,6 +31,7 @@     -- * Running parsers     , parse     , feed+    , I.parseOnly     , parseWith     , parseTest @@ -61,14 +65,19 @@     , I.takeWhile1     , I.takeTill +    -- ** Consume all remaining input+    , I.takeByteString+    , I.takeLazyByteString+     -- * State observation and manipulation functions     , I.endOfInput-    , I.ensure+    , I.atEnd     ) where  import Data.Attoparsec.Combinator import qualified Data.Attoparsec.Internal as I import qualified Data.ByteString as B+import Data.Attoparsec.Internal (Result(..), parse)  -- $parsec --@@ -84,12 +93,11 @@ -- * Much of the performance advantage of Attoparsec is gained via --   high-performance parsers such as 'I.takeWhile' and 'I.string'. --   If you use complicated combinators that return lists of bytes or---   characters, there really isn't much performance difference the---   two libraries.+--   characters, there is less performance difference between the two+--   libraries. -- -- * Unlike Parsec 3, Attoparsec does not support being used as a---   monad transformer.  This is mostly a matter of the implementor---   not having needed that functionality.+--   monad transformer. -- -- * Attoparsec is specialised to deal only with strict 'B.ByteString' --   input.  Efficiency concernts rule out both lists and lazy@@ -97,12 +105,37 @@ --   allow consumption of very large input without a large footprint. --   For this need, Attoparsec's incremental input provides an --   excellent substitute, with much more control over when input---   takes place.+--   takes place.  If you must use lazy bytestrings, see the 'Lazy'+--   module, which feeds lazy chunks to a regular parser. -- -- * Parsec parsers can produce more helpful error messages than --   Attoparsec parsers.  This is a matter of focus: Attoparsec avoids --   the extra book-keeping in favour of higher performance. +-- $incremental+--+-- Attoparsec supports incremental input, meaning that you can feed it+-- a bytestring that represents only part of the expected total amount+-- of data to parse. If your parser reaches the end of a fragment of+-- input and could consume more input, it will suspend parsing and+-- return a 'Partial' continuation.+--+-- Supplying the 'Partial' continuation with another bytestring will+-- resume parsing at the point where it was suspended. You must be+-- prepared for the result of the resumed parse to be another+-- 'Partial' continuation.+--+-- To indicate that you have no more input, supply the 'Partial'+-- continuation with an empty bytestring.+--+-- Remember that some parsing combinators will not return a result+-- until they reach the end of input.  They may thus cause 'Partial'+-- results to be returned.+--+-- If you do not need support for incremental input, consider using+-- the 'I.parseOnly' function to run your parser.  It will never+-- prompt for more input.+ -- $performance -- -- If you write an Attoparsec-based parser carefully, it can be@@ -146,57 +179,18 @@ -- The 'Result' type is an instance of 'Functor', where 'fmap' -- transforms the value in a 'Done' result. --- | The result of a parse.-data Result r = Fail !B.ByteString [String] String-              -- ^ The parse failed.  The 'B.ByteString' is the input-              -- that had not yet been consumed when the failure-              -- occurred.  The @[@'String'@]@ is a list of contexts-              -- in which the error occurred.  The 'String' is the-              -- message describing the error, if any.-              | Partial (B.ByteString -> Result r)-              -- ^ Supply this continuation with more input so that-              -- the parser can resume.  To indicate that no more-              -- input is available, use an 'B.empty' string.-              | Done !B.ByteString r-              -- ^ The parse succeeded.  The 'B.ByteString' is the-              -- input that had not yet been consumed (if any) when-              -- the parse succeeded.--instance Show r => Show (Result r) where-    show (Fail bs stk msg) =-        "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg-    show (Partial _)       = "Partial _"-    show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r- -- | If a parser has returned a 'Partial' result, supply it with more -- input. feed :: Result r -> B.ByteString -> Result r feed f@(Fail _ _ _) _ = f feed (Partial k) d    = k d feed (Done bs r) d    = Done (B.append bs d) r--fmapR :: (a -> b) -> Result a -> Result b-fmapR _ (Fail st stk msg) = Fail st stk msg-fmapR f (Partial k)       = Partial (fmapR f . k)-fmapR f (Done bs r)       = Done bs (f r)--instance Functor Result where-    fmap = fmapR+{-# INLINE feed #-}  -- | Run a parser and print its result to standard output. parseTest :: (Show a) => I.Parser a -> B.ByteString -> IO () parseTest p s = print (parse p s) -translate :: I.Result a -> Result a-translate (I.Fail st stk msg) = Fail (I.input st) stk msg-translate (I.Partial k)       = Partial (translate . k)-translate (I.Done st r)       = Done (I.input st) r---- | Run a parser and return its result.-parse :: I.Parser a -> B.ByteString -> Result a-parse m s = translate (I.parse m s)-{-# INLINE parse #-}- -- | Run a parser with an initial input string, and a monadic action -- that can supply more input if needed. parseWith :: Monad m =>@@ -208,10 +202,10 @@           -> B.ByteString           -- ^ Initial input for the parser.           -> m (Result a)-parseWith refill p s = step $ I.parse p s-  where step (I.Fail st stk msg) = return $! Fail (I.input st) stk msg-        step (I.Partial k)       = (step . k) =<< refill-        step (I.Done st r)       = return $! Done (I.input st) r+parseWith refill p s = step $ parse p s+  where step (Partial k) = (step . k) =<< refill+        step r           = return r+{-# INLINE parseWith #-}  -- | Convert a 'Result' value to a 'Maybe' value. A 'Partial' result -- is treated as failure.
Data/Attoparsec/Char8.hs view
@@ -69,6 +69,10 @@     , takeWhile1     , takeTill +    -- ** Consume all remaining input+    , I.takeByteString+    , I.takeLazyByteString+     -- * Text parsing     , I.endOfLine     , isEndOfLine@@ -79,17 +83,21 @@     , hexadecimal     , signed     , double+    , Number(..)+    , number     , rational      -- * State observation and manipulation functions     , I.endOfInput-    , I.ensure+    , I.atEnd     ) where  import Control.Applicative ((*>), (<$>), (<|>)) import Data.Attoparsec.Combinator import Data.Attoparsec.FastSet (charClass, memberChar) import Data.Attoparsec.Internal (Parser, (<?>))+import Data.Attoparsec.Number (Number(..))+import Data.Bits (Bits, (.|.), shiftL) import Data.ByteString.Internal (c2w, w2c) import Data.Ratio ((%)) import Data.String (IsString(..))@@ -328,14 +336,16 @@ -- @\'a\'@ through @\'f\'@ may be upper or lower case. -- -- This parser does not accept a leading @\"0x\"@ string.-hexadecimal :: Integral a => Parser a+hexadecimal :: (Integral a, Bits a) => Parser a {-# SPECIALISE hexadecimal :: Parser Int #-} hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit-  where isHexDigit w = (w >= 48 && w <= 57) || (x >= 97 && x <= 102)-            where x = toLower w-        step a w | w >= 48 && w <= 57  = a * 16 + fromIntegral (w - 48)-                 | otherwise           = a * 16 + fromIntegral (x - 87)-            where x = toLower w+  where+    isHexDigit w = (w >= 48 && w <= 57) ||+                   (w >= 97 && w <= 102) ||+                   (w >= 65 && w <= 90)+    step a w | w >= 48 && w <= 57  = (a `shiftL` 4) .|. fromIntegral (w - 48)+             | w >= 97             = (a `shiftL` 4) .|. fromIntegral (w - 87)+             | otherwise           = (a `shiftL` 4) .|. fromIntegral (w - 55)  -- | Parse and decode an unsigned decimal number. decimal :: Integral a => Parser a@@ -379,7 +389,7 @@ -- -- >rational "3.foo" == Done 3.0 ".foo" -- >rational "3e"    == Done 3.0 "e"-rational :: RealFloat a => Parser a+rational :: Fractional a => Parser a {-# SPECIALIZE rational :: Parser Double #-} rational = floaty $ \real frac fracDenom -> fromRational $                      real % 1 + frac % fracDenom@@ -397,11 +407,29 @@ -- around the 15th decimal place.  For 0.001% of numbers, this -- function will lose precision at the 13th or 14th decimal place. double :: Parser Double-double = floaty $ \real frac fracDenom ->-                   fromIntegral real +-                   fromIntegral frac / fromIntegral fracDenom+double = floaty asDouble -floaty :: RealFloat a => (Integer -> Integer -> Integer -> a) -> Parser a+asDouble :: Integer -> Integer -> Integer -> Double+asDouble real frac fracDenom =+    fromIntegral real + fromIntegral frac / fromIntegral fracDenom+{-# INLINE asDouble #-}++-- | Parse a number, attempting to preserve both speed and precision.+--+-- The syntax accepted by this parser is the same as for 'rational'.+--+-- /Note/: This function is almost ten times faster than 'rational'.+-- On integral inputs, it gives perfectly accurate answers, and on+-- floating point inputs, it is slightly less accurate than+-- 'rational'.+number :: Parser Number+number = floaty $ \real frac fracDenom ->+         if frac == 0 && fracDenom == 0+         then I real+         else D (asDouble real frac fracDenom)+{-# INLINE number #-}++floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a {-# INLINE floaty #-} floaty f = do   let minus = 45@@ -429,7 +457,7 @@           else if power == 0                then f real fraction (10 ^ fracDigits)                else f real fraction (10 ^ fracDigits) * (10 ^^ power)-  return $! if sign == plus-            then n-            else -n+  return $ if sign == plus+           then n+           else -n   
Data/Attoparsec/Internal.hs view
@@ -3,7 +3,7 @@ -- Module      :  Data.Attoparsec.Internal -- Copyright   :  Bryan O'Sullivan 2007-2010 -- License     :  BSD3--- +-- -- Maintainer  :  bos@serpentine.com -- Stability   :  experimental -- Portability :  unknown@@ -16,10 +16,10 @@     -- * Parser types       Parser     , Result(..)-    , S(input)      -- * Running parsers     , parse+    , parseOnly      -- * Combinators     , (<?>)@@ -51,8 +51,13 @@     , takeWhile1     , takeTill +    -- ** Consume all remaining input+    , takeByteString+    , takeLazyByteString+     -- * State observation and manipulation functions     , endOfInput+    , atEnd     , ensure      -- * Utilities@@ -74,62 +79,78 @@ import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Internal as B import qualified Data.ByteString.Unsafe as B+import qualified Data.ByteString.Lazy as L -data Result r = Fail S [String] String+-- | The result of a parse.+data Result r = Fail B.ByteString [String] String+              -- ^ The parse failed.  The 'B.ByteString' is the input+              -- that had not yet been consumed when the failure+              -- occurred.  The @[@'String'@]@ is a list of contexts+              -- in which the error occurred.  The 'String' is the+              -- message describing the error, if any.               | Partial (B.ByteString -> Result r)-              | Done S r+              -- ^ Supply this continuation with more input so that+              -- the parser can resume.  To indicate that no more+              -- input is available, use an 'B.empty' string.+              | Done B.ByteString r+              -- ^ The parse succeeded.  The 'B.ByteString' is the+              -- input that had not yet been consumed (if any) when+              -- the parse succeeded. +instance Show r => Show (Result r) where+    show (Fail bs stk msg) =+        "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg+    show (Partial _)       = "Partial _"+    show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r++fmapR :: (a -> b) -> Result a -> Result b+fmapR _ (Fail st stk msg) = Fail st stk msg+fmapR f (Partial k)       = Partial (fmapR f . k)+fmapR f (Done bs r)       = Done bs (f r)++instance Functor Result where+    fmap = fmapR++newtype Input = I {unI :: B.ByteString}+newtype Added = A {unA :: B.ByteString}+ -- | The 'Parser' type is a monad. newtype Parser a = Parser {-      runParser :: forall r. S+      runParser :: forall r. Input -> Added -> More                 -> Failure   r                 -> Success a r                 -> Result r     } -type Failure   r = S -> [String] -> String -> Result r-type Success a r = S -> a -> Result r+type Failure   r = Input -> Added -> More -> [String] -> String -> Result r+type Success a r = Input -> Added -> More -> a -> Result r  -- | Have we read all available input? data More = Complete | Incomplete             deriving (Eq, Show) -plusMore :: More -> More -> More-plusMore Complete _ = Complete-plusMore _ Complete = Complete-plusMore _ _        = Incomplete-{-# INLINE plusMore #-}--instance Monoid More where-    mempty  = Incomplete-    mappend = plusMore--data S = S {-      input  :: !B.ByteString-    , _added :: B.ByteString-    , more  :: !More-    } deriving (Show)--instance Show r => Show (Result r) where-    show (Fail _ stack msg) = "Fail " ++ show stack ++ " " ++ show msg-    show (Partial _) = "Partial _"-    show (Done bs r) = "Done " ++ show bs ++ " " ++ show r--addS :: S -> S -> S-addS (S s0 a0 c0) (S _s1 a1 c1) = S (s0 +++ a1) (a0 +++ a1) (mappend c0 c1)+addS :: Input -> Added -> More+     -> Input -> Added -> More+     -> (Input -> Added -> More -> r) -> r+addS i0 a0 m0 _i1 a1 m1 f =+    let !i = I (unI i0 +++ unA a1)+        a  = A (unA a0 +++ unA a1)+        m  = m0 <> m1+    in f i a m+  where+    Complete <> _ = Complete+    _ <> Complete = Complete+    _ <> _        = Incomplete {-# INLINE addS #-} -instance Monoid S where-    mempty  = S B.empty B.empty Incomplete-    mappend = addS- bindP :: Parser a -> (a -> Parser b) -> Parser b bindP m g =-    Parser (\st0 kf ks -> runParser m st0 kf (\s a -> runParser (g a) s kf ks))+    Parser $ \i0 a0 m0 kf ks -> runParser m i0 a0 m0 kf $+                                \i1 a1 m1 a -> runParser (g a) i1 a1 m1 kf ks {-# INLINE bindP #-}  returnP :: a -> Parser a-returnP a = Parser (\st0 _kf ks -> ks st0 a)+returnP a = Parser (\i0 a0 m0 _kf ks -> ks i0 a0 m0 a) {-# INLINE returnP #-}  instance Monad Parser where@@ -137,15 +158,16 @@     (>>=)  = bindP     fail   = failDesc -noAdds :: S -> S-noAdds (S s0 _a0 c0) = S s0 B.empty c0+noAdds :: Input -> Added -> More+       -> (Input -> Added -> More -> r) -> r+noAdds i0 _a0 m0 f = f i0 (A B.empty) m0 {-# INLINE noAdds #-}  plus :: Parser a -> Parser a -> Parser a-plus a b = Parser $ \st0 kf ks ->-           let kf' st1 _ _ = runParser b (mappend st0 st1) kf ks-               !st2 = noAdds st0-           in  runParser a st2 kf' ks+plus a b = Parser $ \i0 a0 m0 kf ks ->+           let kf' i1 a1 m1 _ _ = addS i0 a0 m0 i1 a1 m1 $+                                  \ i2 a2 m2 -> runParser b i2 a2 m2 kf ks+           in  noAdds i0 a0 m0 $ \i2 a2 m2 -> runParser a i2 a2 m2 kf' ks {-# INLINE plus #-}  instance MonadPlus Parser where@@ -154,7 +176,8 @@     mplus = plus  fmapP :: (a -> b) -> Parser a -> Parser b-fmapP p m = Parser (\st0 f k -> runParser m st0 f (\s a -> k s (p a)))+fmapP p m = Parser $ \i0 a0 m0 f k ->+            runParser m i0 a0 m0 f $ \i1 a1 s1 a -> k i1 a1 s1 (p a) {-# INLINE fmapP #-}  instance Functor Parser where@@ -170,7 +193,7 @@ instance Applicative Parser where     pure   = returnP     (<*>)  = apP-    +     -- These definitions are equal to the defaults, but this     -- way the optimizer doesn't have to work so hard to figure     -- that out.@@ -188,48 +211,56 @@     (<|>) = plus  failDesc :: String -> Parser a-failDesc err = Parser (\st0 kf _ks -> kf st0 [] msg)+failDesc err = Parser (\i0 a0 m0 kf _ks -> kf i0 a0 m0 [] msg)     where msg = "Failed reading: " ++ err {-# INLINE failDesc #-} --- | Succeed only if at least @n@ bytes of input are available.-ensure :: Int -> Parser ()-ensure n = Parser $ \st0@(S s0 _a0 _c0) kf ks ->-    if B.length s0 >= n-    then ks st0 ()-    else runParser (demandInput >> ensure n) st0 kf ks+-- | If at least @n@ bytes of input are available, return the current+-- input, otherwise fail.+ensure :: Int -> Parser B.ByteString+ensure !n = Parser $ \i0 a0 m0 kf ks ->+    if B.length (unI i0) >= n+    then ks i0 a0 m0 (unI i0)+    else runParser (demandInput >> ensure n) i0 a0 m0 kf ks  -- | Ask for input.  If we receive any, pass it to a success -- continuation, otherwise to a failure continuation.-prompt :: S -> (S -> Result r) -> (S -> Result r) -> Result r-prompt (S s0 a0 _c0) kf ks = Partial $ \s ->+prompt :: Input -> Added -> More+       -> (Input -> Added -> More -> Result r)+       -> (Input -> Added -> More -> Result r)+       -> Result r+prompt i0 a0 _m0 kf ks = Partial $ \s ->     if B.null s-    then kf $! S s0 a0 Complete-    else ks $! S (s0 +++ s) (a0 +++ s) Incomplete+    then kf i0 a0 Complete+    else ks (I (unI i0 +++ s)) (A (unA a0 +++ s)) Incomplete  -- | Immediately demand more input via a 'Partial' continuation -- result. demandInput :: Parser ()-demandInput = Parser $ \st0 kf ks ->-    if more st0 == Complete-    then kf st0 ["demandInput"] "not enough bytes"-    else prompt st0 (\st -> kf st ["demandInput"] "not enough bytes") (`ks` ())+demandInput = Parser $ \i0 a0 m0 kf ks ->+    if m0 == Complete+    then kf i0 a0 m0 ["demandInput"] "not enough bytes"+    else let kf' i a m = kf i a m ["demandInput"] "not enough bytes"+             ks' i a m = ks i a m ()+         in prompt i0 a0 m0 kf' ks'  -- | This parser always succeeds.  It returns 'True' if any input is -- available either immediately or on demand, and 'False' if the end -- of all input has been reached. wantInput :: Parser Bool-wantInput = Parser $ \st0@(S s0 _a0 c0) _kf ks ->+wantInput = Parser $ \i0 a0 m0 _kf ks ->   case () of-    _ | not (B.null s0) -> ks st0 True-      | c0 == Complete  -> ks st0 False-      | otherwise       -> prompt st0 (`ks` False) (`ks` True)+    _ | not (B.null (unI i0)) -> ks i0 a0 m0 True+      | m0 == Complete  -> ks i0 a0 m0 False+      | otherwise       -> let kf' i a m = ks i a m False+                               ks' i a m = ks i a m True+                           in prompt i0 a0 m0 kf' ks'  get :: Parser B.ByteString-get  = Parser (\st0 _kf ks -> ks st0 (input st0))+get  = Parser $ \i0 a0 m0 _kf ks -> ks i0 a0 m0 (unI i0)  put :: B.ByteString -> Parser ()-put s = Parser (\(S _s0 a0 c0) _kf ks -> ks (S s a0 c0) ())+put s = Parser $ \_i0 a0 m0 _kf ks -> ks (I s) a0 m0 ()  (+++) :: B.ByteString -> B.ByteString -> B.ByteString (+++) = B.append@@ -243,8 +274,10 @@ -- lookahead.  The downside to using this combinator is that it can -- retain input for longer than is desirable. try :: Parser a -> Parser a-try p = Parser $ \st0 kf ks ->-        runParser p (noAdds st0) (kf . mappend st0) ks+try p = Parser $ \i0 a0 m0 kf ks ->+        noAdds i0 a0 m0 $ \i1 a1 m1 ->+            let kf' i2 a2 m2 = addS i0 a0 m0 i2 a2 m2 kf+            in runParser p i1 a1 m1 kf' ks  -- | The parser @satisfy p@ succeeds for any byte for which the -- predicate @p@ returns 'True'. Returns the byte that is actually@@ -254,8 +287,7 @@ -- >    where isDigit w = w >= 48 && w <= 57 satisfy :: (Word8 -> Bool) -> Parser Word8 satisfy p = do-  ensure 1-  s <- get+  s <- ensure 1   let w = B.unsafeHead s   if p w     then put (B.unsafeTail s) >> return w@@ -268,8 +300,7 @@ -- >    where isDigit w = w >= 48 && w <= 57 skip :: (Word8 -> Bool) -> Parser () skip p = do-  ensure 1-  s <- get+  s <- ensure 1   if p (B.unsafeHead s)     then put (B.unsafeTail s)     else fail "skip"@@ -279,8 +310,7 @@ -- parser returns the transformed byte that was parsed. satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a satisfyWith f p = do-  ensure 1-  s <- get+  s <- ensure 1   let c = f (B.unsafeHead s)   if p c     then put (B.unsafeTail s) >> return c@@ -292,14 +322,14 @@   hack :: Storable b => b -> Parser b   hack dummy = do     (fp,o,_) <- B.toForeignPtr `fmapP` take (sizeOf dummy)-    return . B.inlinePerformIO . withForeignPtr fp $ \p -> peek (castPtr $ p `plusPtr` o)+    return . B.inlinePerformIO . withForeignPtr fp $ \p ->+        peek (castPtr $ p `plusPtr` o)  -- | Consume @n@ bytes of input, but succeed only if the predicate -- returns 'True'. takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString takeWith n p = do-  ensure n-  s <- get+  s <- ensure n   let (h,t) = B.splitAt n s   if p h     then put t >> return h@@ -339,11 +369,11 @@ skipWhile p = go  where   go = do-    input <- wantInput-    when input $ do-      t <- B8.dropWhile p <$> get-      put t-      when (B.null t) go+    t <- B8.dropWhile p <$> get+    put t+    when (B.null t) $ do+      input <- wantInput+      when input go {-# INLINE skipWhile #-}  -- | Consume input as long as the predicate returns 'False'@@ -372,16 +402,36 @@ takeWhile p = (B.concat . reverse) `fmap` go []  where   go acc = do-    input <- wantInput-    if input+    (h,t) <- B8.span p <$> get+    put t+    if B.null t       then do-        (h,t) <- B8.span p <$> get-        put t-        if B.null t+        input <- wantInput+        if input           then go (h:acc)           else return (h:acc)-      else return acc+      else return (h:acc) +takeRest :: Parser [B.ByteString]+takeRest = go []+ where+  go acc = do+    input <- wantInput+    if input+      then do+        s <- get+        put B.empty+        go (s:acc)+      else return (reverse acc)++-- | Consume all remaining input and return it as a single string.+takeByteString :: Parser B.ByteString+takeByteString = B.concat `fmap` takeRest++-- | Consume all remaining input and return it as a single string.+takeLazyByteString :: Parser L.ByteString+takeLazyByteString = L.fromChunks `fmap` takeRest+ -- | A stateful scanner.  The predicate consumes and transforms a -- state argument, and each transformed state is passed to successive -- invocations of the predicate on each byte of the input until one@@ -394,29 +444,33 @@ -- combinators such as 'many', because such parsers loop until a -- failure occurs.  Careless use will thus result in an infinite loop. scan :: s -> (s -> Word8 -> Maybe s) -> Parser B.ByteString-scan s0 p = (B.concat . reverse) `fmap` go [] s0+scan s0 p = do+  chunks <- go [] s0+  case chunks of+    [x] -> return x+    xs  -> return . B.concat . reverse $ xs  where   go acc s1 = do-    input <- wantInput-    if input+    let scanner (B.PS fp off len) =+          withForeignPtr fp $ \ptr -> do+            let inner !i !s | i == off+len = done (i-off) s+                            | otherwise = do+                                        w <- peekByteOff ptr i+                                        case p s w of+                                          Just s' -> inner (i+1) s'+                                          Nothing -> done (i-off) s+                done !i !s = return (B.PS fp off i, B.PS fp (off+i) (len-i),s)+            inner off s1+    (h,t,s') <- (unsafePerformIO . scanner) <$> get+    put t+    if B.null t       then do-        let scanner (B.PS fp off len) =-              withForeignPtr fp $ \ptr -> do-                let inner !i !s | i == off+len = return (i-off,s)-                                | otherwise = do-                                            w <- peekByteOff ptr i-                                            case p s w of-                                              Just s' -> inner (i+1) s'-                                              Nothing -> return (i-off,s)-                (i,s') <- inner off s1-                return (B.PS fp off i, B.PS fp (off+i) (len-i),s')-        (h,t,s') <- (unsafePerformIO . scanner) <$> get-        put t-        if B.null t+        input <- wantInput+        if input           then go (h:acc) s'           else return (h:acc)-      else return acc-{-# INLINE scan #-}    +      else return (h:acc)+{-# INLINE scan #-}  -- | Consume input as long as the predicate returns 'True', and return -- the consumed input.@@ -471,15 +525,24 @@  -- | Match only if all input has been consumed. endOfInput :: Parser ()-endOfInput = Parser $ \st0@S{..} kf ks ->-             if B.null input-             then if more == Complete-                  then ks st0 ()-                  else let kf' st1 _ _ = ks (mappend st0 st1) ()-                           ks' st1 _   = kf (mappend st0 st1) [] "endOfInput"-                       in  runParser demandInput st0 kf' ks'-             else kf st0 [] "endOfInput"-                                               +endOfInput = Parser $ \i0 a0 m0 kf ks ->+             if B.null (unI i0)+             then if m0 == Complete+                  then ks i0 a0 m0 ()+                  else let kf' i1 a1 m1 _ _ = addS i0 a0 m0 i1 a1 m1 $+                                              \ i2 a2 m2 -> ks i2 a2 m2 ()+                           ks' i1 a1 m1 _   = addS i0 a0 m0 i1 a1 m1 $+                                              \ i2 a2 m2 -> kf i2 a2 m2 []+                                                            "endOfInput"+                       in  runParser demandInput i0 a0 m0 kf' ks'+             else kf i0 a0 m0 [] "endOfInput"++-- | Return an indication of whether the end of input has been+-- reached.+atEnd :: Parser Bool+atEnd = not <$> wantInput+{-# INLINE atEnd #-}+ -- | Match either a single newline character @\'\\n\'@, or a carriage -- return followed by a newline character @\"\\r\\n\"@. endOfLine :: Parser ()@@ -489,19 +552,31 @@ (<?>) :: Parser a       -> String                 -- ^ the name to use if parsing fails       -> Parser a-p <?> msg = Parser $ \s kf ks -> runParser p s (\s' strs m -> kf s' (msg:strs) m) ks+p <?> msg0 = Parser $ \i0 a0 m0 kf ks ->+             let kf' i a m strs msg = kf i a m (msg0:strs) msg+             in runParser p i0 a0 m0 kf' ks {-# INLINE (<?>) #-} infix 0 <?>  -- | Terminal failure continuation. failK :: Failure a-failK st0 stack msg = Fail st0 stack msg+failK i0 _a0 _m0 stack msg = Fail (unI i0) stack msg+{-# INLINE failK #-}  -- | Terminal success continuation. successK :: Success a a-successK state a = Done state a+successK i0 _a0 _m0 a = Done (unI i0) a+{-# INLINE successK #-}  -- | Run a parser. parse :: Parser a -> B.ByteString -> Result a-parse m s = runParser m (S s B.empty Incomplete) failK successK+parse m s = runParser m (I s) (A B.empty) Incomplete failK successK {-# INLINE parse #-}++-- | Run a parser that cannot be resupplied via a 'Partial' result.+parseOnly :: Parser a -> B.ByteString -> Either String a+parseOnly m s = case runParser m (I s) (A B.empty) Complete failK successK of+                  Fail _ _ err -> Left err+                  Done _ a     -> Right a+                  _            -> error "parseOnly: impossible error!"+{-# INLINE parseOnly #-}
+ Data/Attoparsec/Number.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE DeriveDataTypeable #-}+-- |+-- Module      :  Data.Attoparsec.Number+-- Copyright   :  Bryan O'Sullivan 2011+-- License     :  BSD3+--+-- Maintainer  :  bos@serpentine.com+-- Stability   :  experimental+-- Portability :  unknown+--+-- A simple number type, useful for parsing both exact and inexact+-- quantities without losing much precision.+module Data.Attoparsec.Number+    (+      Number(..)+    ) where++import Data.Data (Data)+import Data.Function (on)+import Data.Typeable (Typeable)++-- | A numeric type that can represent integers accurately, and+-- floating point numbers to the precision of a 'Double'.+data Number = I !Integer+            | D {-# UNPACK #-} !Double+              deriving (Typeable, Data)++instance Show Number where+    show (I a) = show a+    show (D a) = show a++binop :: (Integer -> Integer -> a) -> (Double -> Double -> a)+      -> Number -> Number -> a+binop _ d (D a) (D b) = d a b+binop i _ (I a) (I b) = i a b+binop _ d (D a) (I b) = d a (fromIntegral b)+binop _ d (I a) (D b) = d (fromIntegral a) b+{-# INLINE binop #-}++instance Eq Number where+    (==) = binop (==) (==)+    {-# INLINE (==) #-}++    (/=) = binop (/=) (/=)+    {-# INLINE (/=) #-}++instance Ord Number where+    (<) = binop (<) (<)+    {-# INLINE (<) #-}++    (>) = binop (>) (>)+    {-# INLINE (>) #-}++instance Num Number where+    (+) = binop (((I$!).) . (+)) (((D$!).) . (+))+    {-# INLINE (+) #-}++    (-) = binop (((I$!).) . (-)) (((D$!).) . (-))+    {-# INLINE (-) #-}++    (*) = binop (((I$!).) . (+)) (((D$!).) . (+))+    {-# INLINE (*) #-}++    abs (I a) = I $! abs a+    abs (D a) = D $! abs a+    {-# INLINE abs #-}++    negate (I a) = I $! negate a+    negate (D a) = D $! negate a+    {-# INLINE negate #-}++    signum (I a) = I $! signum a+    signum (D a) = D $! signum a+    {-# INLINE signum #-}++    fromInteger = (I$!) . fromInteger+    {-# INLINE fromInteger #-}++instance Real Number where+    toRational (I a) = fromIntegral a+    toRational (D a) = toRational a+    {-# INLINE toRational #-}++instance Fractional Number where+    fromRational = (D$!) . fromRational+    {-# INLINE fromRational #-}++    (/) = binop (((D$!).) . (/) `on` fromIntegral)+                (((D$!).) . (/))+    {-# INLINE (/) #-}++    recip (I a) = D $! recip (fromIntegral a)+    recip (D a) = D $! recip a+    {-# INLINE recip #-}++instance RealFrac Number where+    properFraction (I a) = (fromIntegral a,0)+    properFraction (D a) = case properFraction a of+                             (i,d) -> (i,D d)+    {-# INLINE properFraction #-}+    truncate (I a) = fromIntegral a+    truncate (D a) = truncate a+    {-# INLINE truncate #-}+    round (I a) = fromIntegral a+    round (D a) = round a+    {-# INLINE round #-}+    ceiling (I a) = fromIntegral a+    ceiling (D a) = ceiling a+    {-# INLINE ceiling #-}+    floor (I a) = fromIntegral a+    floor (D a) = floor a+    {-# INLINE floor #-}
+ Data/Attoparsec/Zepto.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples #-}++-- |+-- Module      :  Data.Attoparsec.Zepto+-- Copyright   :  Bryan O'Sullivan 2011+-- License     :  BSD3+-- +-- Maintainer  :  bos@serpentine.com+-- Stability   :  experimental+-- Portability :  unknown+--+-- A tiny, highly specialized combinator parser for 'B.ByteString'+-- strings.+--+-- While the main Attoparsec module generally performs well, this+-- module is particularly fast for simple non-recursive loops that+-- should not normally result in failed parses.+--+-- /Warning/: on more complex inputs involving recursion or failure,+-- parsers based on this module may be as much as /ten times slower/+-- than regular Attoparsec! You should /only/ use this module when you+-- have benchmarks that prove that its use speeds your code up.+module Data.Attoparsec.Zepto+    (+      Parser+    , parse+    , atEnd+    , string+    , take+    , takeWhile+    ) where++import Data.Word (Word8)+import Control.Applicative+import Control.Monad+import Data.Monoid+import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as B+import Data.ByteString (ByteString)+import Prelude hiding (take, takeWhile)++newtype S = S {+      input :: ByteString+    }++data Result a = Fail String+              | OK !a++-- | A simple parser.+--+-- This monad is strict in its state, and the monadic bind operator+-- ('>>=') evaluates each result to weak head normal form before+-- passing it along.+newtype Parser a = Parser {+      runParser :: S -> (# Result a, S #)+    }++instance Functor Parser where+    fmap f m = Parser $ \s -> case runParser m s of+                                (# OK a, s' #)     -> (# OK (f a), s' #)+                                (# Fail err, s' #) -> (# Fail err, s' #)+    {-# INLINE fmap #-}++instance Monad Parser where+    return a = Parser $ \s -> (# OK a, s #)+    {-# INLINE return #-}++    m >>= k   = Parser $ \s -> case runParser m s of+                                 (# OK a, s' #) -> runParser (k a) s'+                                 (# Fail err, s' #) -> (# Fail err, s' #)+    {-# INLINE (>>=) #-}++    fail msg = Parser $ \s -> (# Fail msg, s #)++instance MonadPlus Parser where+    mzero = fail "mzero"+    {-# INLINE mzero #-}++    mplus a b = Parser $ \s ->+                case runParser a s of+                  (# ok@(OK _), s' #) -> (# ok, s' #)+                  (# _, _ #) -> case runParser b s of+                                   (# ok@(OK _), s'' #) -> (# ok, s'' #)+                                   (# err, s'' #) -> (# err, s'' #)+    {-# INLINE mplus #-}++instance Applicative Parser where+    pure   = return+    (<*>)  = ap++gets :: (S -> a) -> Parser a+gets f = Parser $ \s -> (# OK (f s), s #)+{-# INLINE gets #-}++put :: S -> Parser ()+put s = Parser $ \_ -> (# OK (), s #)+{-# INLINE put #-}++-- | Run a parser.+parse :: Parser a -> ByteString -> Either String a+parse p bs = case runParser p (S bs) of+               (# OK a, _ #) -> Right a+               (# Fail err, _ #) -> Left err++instance Monoid (Parser a) where+    mempty  = fail "mempty"+    {-# INLINE mempty #-}+    mappend = mplus++instance Alternative Parser where+    empty = fail "empty"+    {-# INLINE empty #-}+    (<|>) = mplus++-- | Consume input while the predicate returns 'True'.+takeWhile :: (Word8 -> Bool) -> Parser ByteString+takeWhile p = do+  (h,t) <- gets (B.span p . input)+  put (S t)+  return h+{-# INLINE takeWhile #-}++-- | Consume @n@ bytes of input.+take :: Int -> Parser ByteString+take !n = do+  s <- gets input+  if B.length s >= n+    then put (S (B.unsafeDrop n s)) >> return (B.unsafeTake n s)+    else fail "insufficient input"+{-# INLINE take #-}++-- | Match a string exactly.+string :: ByteString -> Parser ()+string s = do+  i <- gets input+  if s `B.isPrefixOf` i+    then put (S (B.unsafeDrop (B.length s) i)) >> return ()+    else fail "string"+{-# INLINE string #-}++-- | Indicate whether the end of the input has been reached.+atEnd :: Parser Bool+atEnd = do+  i <- gets input+  return $! B.null i+{-# INLINE atEnd #-}
attoparsec.cabal view
@@ -1,12 +1,12 @@ name:            attoparsec-version:         0.8.4.0+version:         0.8.5.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.10.4, GHC == 6.12.1+tested-with:     GHC == 6.10.4, GHC == 6.12.3, GHC == 7.0.1 synopsis:        Fast combinator parsing for bytestrings cabal-version:   >= 1.6 homepage:        http://bitbucket.org/bos/attoparsec@@ -58,6 +58,8 @@                    Data.Attoparsec.Combinator                    Data.Attoparsec.FastSet                    Data.Attoparsec.Lazy+                   Data.Attoparsec.Number+                   Data.Attoparsec.Zepto   other-modules:   Data.Attoparsec.Internal   ghc-options:     -Wall