git.iko.soy/typeable/attoparsec
on master help sign in
Common implementations for 'wantInput', 'endOfInput', and 'atEnd'.
49a8b2cMikhail Vorozhtsov
Data/Attoparsec/ByteString/Internal.hs−30
@@ -468,30 +468,6 @@ ensure n = T.Parser $ \t pos more lose succ ->
468-- Non-recursive so the bounds check can be inlined:
468-- Non-recursive so the bounds check can be inlined:
469{-# INLINE ensure #-}
469{-# INLINE ensure #-}
470
470
471−-- | This parser always succeeds. It returns 'True' if any input is
472−-- available either immediately or on demand, and 'False' if the end
473−-- of all input has been reached.
474−wantInput :: Parser Bool
475−wantInput = T.Parser $ \t pos more _lose succ ->
476− case () of
477− _ | lengthAtLeast pos 1 t -> succ t pos more True
478− | more == Complete -> succ t pos more False
479− | otherwise -> let lose' t' pos' more' = succ t' pos' more' False
480− succ' t' pos' more' = succ t' pos' more' True
481− in prompt t pos more lose' succ'
482−{-# INLINE wantInput #-}
483−
484−-- | Match only if all input has been consumed.
485−endOfInput :: Parser ()
486−endOfInput = T.Parser $ \t pos more lose succ ->
487− case () of
488− _| lengthAtLeast pos 1 t -> lose t pos more [] "endOfInput"
489− | more == Complete -> succ t pos more ()
490− | otherwise ->
491− let lose' t' pos' more' _ctx _msg = succ t' pos' more' ()
492− succ' t' pos' more' _a = lose t' pos' more' [] "endOfInput"
493− in runParser demandInput t pos more lose' succ'
494−
495-- | Return both the result of a parse and the portion of the input
471-- | Return both the result of a parse and the portion of the input
496-- that was consumed while it was being parsed.
472-- that was consumed while it was being parsed.
497match :: Parser a -> Parser (ByteString, a)
473match :: Parser a -> Parser (ByteString, a)
@@ -500,12 +476,6 @@ match p = T.Parser $ \t pos more lose succ ->
500 succ t' pos' more' (substring pos (pos'-pos) t', a)
476 succ t' pos' more' (substring pos (pos'-pos) t', a)
501 in runParser p t pos more lose succ'
477 in runParser p t pos more lose succ'
502
478
503−-- | Return an indication of whether the end of input has been
504−-- reached.
505−atEnd :: Parser Bool
506−atEnd = not <$> wantInput
507−{-# INLINE atEnd #-}
508−
509lengthAtLeast :: Pos -> Int -> Buffer -> Bool
479lengthAtLeast :: Pos -> Int -> Buffer -> Bool
510lengthAtLeast (Pos pos) n bs = Buf.length bs >= pos + n
480lengthAtLeast (Pos pos) n bs = Buf.length bs >= pos + n
511{-# INLINE lengthAtLeast #-}
481{-# INLINE lengthAtLeast #-}
Data/Attoparsec/Combinator.hs+3
@@ -30,12 +30,15 @@ module Data.Attoparsec.Combinator
30 , skipMany1
30 , skipMany1
31 , eitherP
31 , eitherP
32 , feed
32 , feed
33+ , endOfInput
34+ , atEnd
33 ) where
35 ) where
34
36
35import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
37import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
36 many, (<|>), (*>), (<$>))
38 many, (<|>), (*>), (<$>))
37import Control.Monad (MonadPlus(..))
39import Control.Monad (MonadPlus(..))
38import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
40import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
41+import Data.Attoparsec.Internal (endOfInput, atEnd)
39import Data.ByteString (ByteString)
42import Data.ByteString (ByteString)
40import Data.Monoid (Monoid(mappend))
43import Data.Monoid (Monoid(mappend))
41import Data.Text (Text)
44import Data.Text (Text)
Data/Attoparsec/Internal.hs+39−1
@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP, BangPatterns #-}
1+{-# LANGUAGE CPP, BangPatterns, ScopedTypeVariables #-}
2-- |
2-- |
3-- Module : Data.Attoparsec.Internal
3-- Module : Data.Attoparsec.Internal
4-- Copyright : Bryan O'Sullivan 2007-2014
4-- Copyright : Bryan O'Sullivan 2007-2014
@@ -15,8 +15,12 @@ module Data.Attoparsec.Internal
15 ( compareResults
15 ( compareResults
16 , prompt
16 , prompt
17 , demandInput
17 , demandInput
18+ , wantInput
19+ , endOfInput
20+ , atEnd
18 ) where
21 ) where
19
22
23+import Control.Applicative ((<$>))
20#if __GLASGOW_HASKELL__ >= 700
24#if __GLASGOW_HASKELL__ >= 700
21import Data.ByteString (ByteString)
25import Data.ByteString (ByteString)
22import Data.Text (Text)
26import Data.Text (Text)
@@ -74,3 +78,37 @@ demandInput = Parser $ \t pos more lose succ ->
74{-# SPECIALIZE demandInput :: Parser ByteString () #-}
78{-# SPECIALIZE demandInput :: Parser ByteString () #-}
75{-# SPECIALIZE demandInput :: Parser Text () #-}
79{-# SPECIALIZE demandInput :: Parser Text () #-}
76#endif
80#endif
81+
82+-- | This parser always succeeds. It returns 'True' if any input is
83+-- available either immediately or on demand, and 'False' if the end
84+-- of all input has been reached.
85+wantInput :: forall t . Chunk t => Parser t Bool
86+wantInput = Parser $ \t pos more _lose succ ->
87+ case () of
88+ _ | pos < atBufferEnd (undefined :: t) t -> succ t pos more True
89+ | more == Complete -> succ t pos more False
90+ | otherwise -> let lose' t' pos' more' = succ t' pos' more' False
91+ succ' t' pos' more' = succ t' pos' more' True
92+ in prompt t pos more lose' succ'
93+{-# INLINE wantInput #-}
94+
95+-- | Match only if all input has been consumed.
96+endOfInput :: forall t . Chunk t => Parser t ()
97+endOfInput = Parser $ \t pos more lose succ ->
98+ case () of
99+ _| pos < atBufferEnd (undefined :: t) t -> lose t pos more [] "endOfInput"
100+ | more == Complete -> succ t pos more ()
101+ | otherwise ->
102+ let lose' t' pos' more' _ctx _msg = succ t' pos' more' ()
103+ succ' t' pos' more' _a = lose t' pos' more' [] "endOfInput"
104+ in runParser demandInput t pos more lose' succ'
105+#if __GLASGOW_HASKELL__ >= 700
106+{-# SPECIALIZE endOfInput :: Parser ByteString () #-}
107+{-# SPECIALIZE endOfInput :: Parser Text () #-}
108+#endif
109+
110+-- | Return an indication of whether the end of input has been
111+-- reached.
112+atEnd :: Chunk t => Parser t Bool
113+atEnd = not <$> wantInput
114+{-# INLINE atEnd #-}
Data/Attoparsec/Internal/Types.hs+6
@@ -209,6 +209,8 @@ class Monoid c => Chunk c where
209 nullChunk :: c -> Bool
209 nullChunk :: c -> Bool
210 -- | Append chunk to a buffer.
210 -- | Append chunk to a buffer.
211 pappendChunk :: State c -> c -> State c
211 pappendChunk :: State c -> c -> State c
212+ -- | Position at the end of a buffer. The first argument is ignored.
213+ atBufferEnd :: c -> State c -> Pos
212
214
213instance Chunk ByteString where
215instance Chunk ByteString where
214 type ChunkElem ByteString = Word8
216 type ChunkElem ByteString = Word8
@@ -216,6 +218,8 @@ instance Chunk ByteString where
216 {-# INLINE nullChunk #-}
218 {-# INLINE nullChunk #-}
217 pappendChunk = B.pappend
219 pappendChunk = B.pappend
218 {-# INLINE pappendChunk #-}
220 {-# INLINE pappendChunk #-}
221+ atBufferEnd _ = Pos . B.length
222+ {-# INLINE atBufferEnd #-}
219
223
220instance Chunk Text where
224instance Chunk Text where
221 type ChunkElem Text = Char
225 type ChunkElem Text = Char
@@ -223,3 +227,5 @@ instance Chunk Text where
223 {-# INLINE nullChunk #-}
227 {-# INLINE nullChunk #-}
224 pappendChunk = T.pappend
228 pappendChunk = T.pappend
225 {-# INLINE pappendChunk #-}
229 {-# INLINE pappendChunk #-}
230+ atBufferEnd _ = Pos . T.length
231+ {-# INLINE atBufferEnd #-}
Data/Attoparsec/Text/Internal.hs−29
@@ -479,29 +479,6 @@ ensure n = T.Parser $ \t pos more lose succ ->
479-- Non-recursive so the bounds check can be inlined:
479-- Non-recursive so the bounds check can be inlined:
480{-# INLINE ensure #-}
480{-# INLINE ensure #-}
481
481
482−-- | This parser always succeeds. It returns 'True' if any input is
483−-- available either immediately or on demand, and 'False' if the end
484−-- of all input has been reached.
485−wantInput :: Parser Bool
486−wantInput = T.Parser $ \t pos more _lose succ ->
487− case () of
488− _ | pos < lengthOf t -> succ t pos more True
489− | more == Complete -> succ t pos more False
490− | otherwise -> let lose' t' pos' more' = succ t' pos' more' False
491− succ' t' pos' more' = succ t' pos' more' True
492− in prompt t pos more lose' succ'
493−
494−-- | Match only if all input has been consumed.
495−endOfInput :: Parser ()
496−endOfInput = T.Parser $ \t pos more lose succ ->
497− case () of
498− _| pos < lengthOf t -> lose t pos more [] "endOfInput"
499− | more == Complete -> succ t pos more ()
500− | otherwise ->
501− let lose' t' pos' more' _ctx _msg = succ t' pos' more' ()
502− succ' t' pos' more' _a = lose t' pos' more' [] "endOfInput"
503− in runParser demandInput t pos more lose' succ'
504−
505-- | Return both the result of a parse and the portion of the input
482-- | Return both the result of a parse and the portion of the input
506-- that was consumed while it was being parsed.
483-- that was consumed while it was being parsed.
507match :: Parser a -> Parser (Text, a)
484match :: Parser a -> Parser (Text, a)
@@ -510,12 +487,6 @@ match p = T.Parser $ \t pos more lose succ ->
510 (substring pos (pos'-pos) t', a)
487 (substring pos (pos'-pos) t', a)
511 in runParser p t pos more lose succ'
488 in runParser p t pos more lose succ'
512
489
513−-- | Return an indication of whether the end of input has been
514−-- reached.
515−atEnd :: Parser Bool
516−atEnd = not <$> wantInput
517−{-# INLINE atEnd #-}
518−
519lengthAtLeast :: Pos -> Int -> Buffer -> Maybe Pos
490lengthAtLeast :: Pos -> Int -> Buffer -> Maybe Pos
520lengthAtLeast pos n t = go 0 (fromPos pos)
491lengthAtLeast pos n t = go 0 (fromPos pos)
521 where go i !p
492 where go i !p
Data/Attoparsec/Types.hs+2−1
@@ -14,6 +14,7 @@ module Data.Attoparsec.Types
14 (
14 (
15 Parser
15 Parser
16 , IResult(..)
16 , IResult(..)
17+ , Chunk
17 ) where
18 ) where
18
19
19−import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
20+import Data.Attoparsec.Internal.Types (Parser(..), IResult(..), Chunk)