git.iko.soy/typeable/attoparsec
on master help sign in
Add DeepSeq support and more specialisations.
8ad6d5fBryan O'Sullivan
Data/Attoparsec/Char8.hs+37−10
@@ -1,4 +1,4 @@
1−{-# LANGUAGE FlexibleInstances #-}
1+{-# LANGUAGE BangPatterns, FlexibleInstances #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3
3
4-- |
4-- |
@@ -99,9 +99,10 @@ import Data.Attoparsec.Internal (Parser, (<?>))
99import Data.Attoparsec.Number (Number(..))
99import Data.Attoparsec.Number (Number(..))
100import Data.Bits (Bits, (.|.), shiftL)
100import Data.Bits (Bits, (.|.), shiftL)
101import Data.ByteString.Internal (c2w, w2c)
101import Data.ByteString.Internal (c2w, w2c)
102+import Data.Int (Int8, Int16, Int32, Int64)
102import Data.Ratio ((%))
103import Data.Ratio ((%))
103import Data.String (IsString(..))
104import Data.String (IsString(..))
104−import Data.Word (Word8)
105+import Data.Word (Word8, Word16, Word32, Word64, Word)
105import Prelude hiding (takeWhile)
106import Prelude hiding (takeWhile)
106import qualified Data.Attoparsec as A
107import qualified Data.Attoparsec as A
107import qualified Data.Attoparsec.Internal as I
108import qualified Data.Attoparsec.Internal as I
@@ -337,7 +338,6 @@ isHorizontalSpace w = w == 32 || w == 9
337--
338--
338-- This parser does not accept a leading @\"0x\"@ string.
339-- This parser does not accept a leading @\"0x\"@ string.
339hexadecimal :: (Integral a, Bits a) => Parser a
340hexadecimal :: (Integral a, Bits a) => Parser a
340−{-# SPECIALISE hexadecimal :: Parser Int #-}
341hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit
341hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit
342 where
342 where
343 isHexDigit w = (w >= 48 && w <= 57) ||
343 isHexDigit w = (w >= 48 && w <= 57) ||
@@ -346,25 +346,48 @@ hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit
346 step a w | w >= 48 && w <= 57 = (a `shiftL` 4) .|. fromIntegral (w - 48)
346 step a w | w >= 48 && w <= 57 = (a `shiftL` 4) .|. fromIntegral (w - 48)
347 | w >= 97 = (a `shiftL` 4) .|. fromIntegral (w - 87)
347 | w >= 97 = (a `shiftL` 4) .|. fromIntegral (w - 87)
348 | otherwise = (a `shiftL` 4) .|. fromIntegral (w - 55)
348 | otherwise = (a `shiftL` 4) .|. fromIntegral (w - 55)
349+{-# SPECIALISE hexadecimal :: Parser Int #-}
350+{-# SPECIALISE hexadecimal :: Parser Int8 #-}
351+{-# SPECIALISE hexadecimal :: Parser Int16 #-}
352+{-# SPECIALISE hexadecimal :: Parser Int32 #-}
353+{-# SPECIALISE hexadecimal :: Parser Int64 #-}
354+{-# SPECIALISE hexadecimal :: Parser Integer #-}
355+{-# SPECIALISE hexadecimal :: Parser Word #-}
356+{-# SPECIALISE hexadecimal :: Parser Word8 #-}
357+{-# SPECIALISE hexadecimal :: Parser Word16 #-}
358+{-# SPECIALISE hexadecimal :: Parser Word32 #-}
359+{-# SPECIALISE hexadecimal :: Parser Word64 #-}
349
360
350-- | Parse and decode an unsigned decimal number.
361-- | Parse and decode an unsigned decimal number.
351decimal :: Integral a => Parser a
362decimal :: Integral a => Parser a
352−{-# SPECIALISE decimal :: Parser Int #-}
353−{-# SPECIALISE decimal :: Parser Integer #-}
354decimal = B8.foldl' step 0 `fmap` I.takeWhile1 isDig
363decimal = B8.foldl' step 0 `fmap` I.takeWhile1 isDig
355 where isDig w = w >= 48 && w <= 57
364 where isDig w = w >= 48 && w <= 57
356 step a w = a * 10 + fromIntegral (w - 48)
365 step a w = a * 10 + fromIntegral (w - 48)
366+{-# SPECIALISE decimal :: Parser Int #-}
367+{-# SPECIALISE decimal :: Parser Int8 #-}
368+{-# SPECIALISE decimal :: Parser Int16 #-}
369+{-# SPECIALISE decimal :: Parser Int32 #-}
370+{-# SPECIALISE decimal :: Parser Int64 #-}
371+{-# SPECIALISE decimal :: Parser Integer #-}
372+{-# SPECIALISE decimal :: Parser Word #-}
373+{-# SPECIALISE decimal :: Parser Word8 #-}
374+{-# SPECIALISE decimal :: Parser Word16 #-}
375+{-# SPECIALISE decimal :: Parser Word32 #-}
376+{-# SPECIALISE decimal :: Parser Word64 #-}
357
377
358-- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
378-- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
359-- character.
379-- character.
360signed :: Num a => Parser a -> Parser a
380signed :: Num a => Parser a -> Parser a
361{-# SPECIALISE signed :: Parser Int -> Parser Int #-}
381{-# SPECIALISE signed :: Parser Int -> Parser Int #-}
382+{-# SPECIALISE signed :: Parser Int8 -> Parser Int8 #-}
383+{-# SPECIALISE signed :: Parser Int16 -> Parser Int16 #-}
384+{-# SPECIALISE signed :: Parser Int32 -> Parser Int32 #-}
385+{-# SPECIALISE signed :: Parser Int64 -> Parser Int64 #-}
386+{-# SPECIALISE signed :: Parser Integer -> Parser Integer #-}
362signed p = (negate <$> (char8 '-' *> p))
387signed p = (negate <$> (char8 '-' *> p))
363 <|> (char8 '+' *> p)
388 <|> (char8 '+' *> p)
364 <|> p
389 <|> p
365
390
366−data T = T !Integer !Int
367−
368-- | Parse a rational number.
391-- | Parse a rational number.
369--
392--
370-- This parser accepts an optional leading sign character, followed by
393-- This parser accepts an optional leading sign character, followed by
@@ -391,6 +414,8 @@ data T = T !Integer !Int
391-- >rational "3e" == Done 3.0 "e"
414-- >rational "3e" == Done 3.0 "e"
392rational :: Fractional a => Parser a
415rational :: Fractional a => Parser a
393{-# SPECIALIZE rational :: Parser Double #-}
416{-# SPECIALIZE rational :: Parser Double #-}
417+{-# SPECIALIZE rational :: Parser Float #-}
418+{-# SPECIALIZE rational :: Parser Rational #-}
394rational = floaty $ \real frac fracDenom -> fromRational $
419rational = floaty $ \real frac fracDenom -> fromRational $
395 real % 1 + frac % fracDenom
420 real % 1 + frac % fracDenom
396
421
@@ -429,12 +454,15 @@ number = floaty $ \real frac fracDenom ->
429 else D (asDouble real frac fracDenom)
454 else D (asDouble real frac fracDenom)
430{-# INLINE number #-}
455{-# INLINE number #-}
431
456
457+data T = T !Integer !Int
458+
432floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a
459floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a
433{-# INLINE floaty #-}
460{-# INLINE floaty #-}
434floaty f = do
461floaty f = do
435 let minus = 45
462 let minus = 45
436 plus = 43
463 plus = 43
437− sign <- I.satisfy (\c -> c == minus || c == plus) <|> return plus
464+ !positive <- ((== plus) <$> I.satisfy (\c -> c == minus || c == plus)) <|>
465+ return True
438 real <- decimal
466 real <- decimal
439 let tryFraction = do
467 let tryFraction = do
440 let dot = 46
468 let dot = 46
@@ -455,7 +483,6 @@ floaty f = do
455 else if power == 0
483 else if power == 0
456 then f real fraction (10 ^ fracDigits)
484 then f real fraction (10 ^ fracDigits)
457 else f real fraction (10 ^ fracDigits) * (10 ^^ power)
485 else f real fraction (10 ^ fracDigits) * (10 ^^ power)
458− return $ if sign == plus
486+ return $ if positive
459 then n
487 then n
460 else -n
488 else -n
461−
Data/Attoparsec/Internal.hs+9−1
@@ -65,6 +65,7 @@ module Data.Attoparsec.Internal
65 ) where
65 ) where
66
66
67import Control.Applicative (Alternative(..), Applicative(..), (<$>))
67import Control.Applicative (Alternative(..), Applicative(..), (<$>))
68+import Control.DeepSeq (NFData(rnf))
68import Control.Monad (MonadPlus(..), when)
69import Control.Monad (MonadPlus(..), when)
69import Data.Attoparsec.Combinator
70import Data.Attoparsec.Combinator
70import Data.Attoparsec.FastSet (charClass, memberWord8)
71import Data.Attoparsec.FastSet (charClass, memberWord8)
@@ -103,6 +104,12 @@ instance Show r => Show (Result r) where
103 show (Partial _) = "Partial _"
104 show (Partial _) = "Partial _"
104 show (Done bs r) = "Done " ++ show bs ++ " " ++ show r
105 show (Done bs r) = "Done " ++ show bs ++ " " ++ show r
105
106
107+instance (NFData r) => NFData (Result r) where
108+ rnf (Fail _ _ _) = ()
109+ rnf (Partial _) = ()
110+ rnf (Done _ r) = rnf r
111+ {-# INLINE rnf #-}
112+
106fmapR :: (a -> b) -> Result a -> Result b
113fmapR :: (a -> b) -> Result a -> Result b
107fmapR _ (Fail st stk msg) = Fail st stk msg
114fmapR _ (Fail st stk msg) = Fail st stk msg
108fmapR f (Partial k) = Partial (fmapR f . k)
115fmapR f (Partial k) = Partial (fmapR f . k)
@@ -330,7 +337,8 @@ storable = hack undefined
330takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString
337takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString
331takeWith n p = do
338takeWith n p = do
332 s <- ensure n
339 s <- ensure n
333− let (h,t) = B.splitAt n s
340+ let h = B.unsafeTake n s
341+ t = B.unsafeDrop n s
334 if p h
342 if p h
335 then put t >> return h
343 then put t >> return h
336 else failDesc "takeWith"
344 else failDesc "takeWith"
Data/Attoparsec/Number.hs+6
@@ -15,6 +15,7 @@ module Data.Attoparsec.Number
15 Number(..)
15 Number(..)
16 ) where
16 ) where
17
17
18+import Control.DeepSeq (NFData(rnf))
18import Data.Data (Data)
19import Data.Data (Data)
19import Data.Function (on)
20import Data.Function (on)
20import Data.Typeable (Typeable)
21import Data.Typeable (Typeable)
@@ -29,6 +30,11 @@ instance Show Number where
29 show (I a) = show a
30 show (I a) = show a
30 show (D a) = show a
31 show (D a) = show a
31
32
33+instance NFData Number where
34+ rnf (I _) = ()
35+ rnf (D _) = ()
36+ {-# INLINE rnf #-}
37+
32binop :: (Integer -> Integer -> a) -> (Double -> Double -> a)
38binop :: (Integer -> Integer -> a) -> (Double -> Double -> a)
33 -> Number -> Number -> a
39 -> Number -> Number -> a
34binop _ d (D a) (D b) = d a b
40binop _ d (D a) (D b) = d a b
attoparsec.cabal+2
@@ -52,6 +52,8 @@ library
52 else
52 else
53 build-depends: base < 2.0
53 build-depends: base < 2.0
54
54
55+ build-depends: deepseq
56+
55 extensions: CPP
57 extensions: CPP
56 exposed-modules: Data.Attoparsec
58 exposed-modules: Data.Attoparsec
57 Data.Attoparsec.Char8
59 Data.Attoparsec.Char8