git.iko.soy/typeable/attoparsec
on master help sign in
Implemented 'satisfyElem'.
commitb0fed373a89a283bb498584e7bff1ed05285d302 authorMikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com> dateTue 10 Jun 2014, 17:04 (12 years ago) parent49a8b2c
3 files changed+54−1
Data/Attoparsec/Combinator.hs+2−1 Data/Attoparsec/Internal.hs+41 Data/Attoparsec/Internal/Types.hs+11
Data/Attoparsec/Combinator.hs+2−1
@@ -30,6 +30,7 @@ module Data.Attoparsec.Combinator
3030 , skipMany1
3131 , eitherP
3232 , feed
33+ , satisfyElem
3334 , endOfInput
3435 , atEnd
3536 ) where
@@ -38,7 +39,7 @@ import Control.Applicative (Alternative(..), Applicative(..), empty, liftA2,
3839 many, (<|>), (*>), (<$>))
3940import Control.Monad (MonadPlus(..))
4041import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
41−import Data.Attoparsec.Internal (endOfInput, atEnd)
42+import Data.Attoparsec.Internal (endOfInput, atEnd, satisfyElem)
4243import Data.ByteString (ByteString)
4344import Data.Monoid (Monoid(mappend))
4445import Data.Text (Text)
Data/Attoparsec/Internal.hs+41
@@ -18,6 +18,7 @@ module Data.Attoparsec.Internal
1818 , wantInput
1919 , endOfInput
2020 , atEnd
21+ , satisfyElem
2122 ) where
2223
2324import Control.Applicative ((<$>))
@@ -112,3 +113,43 @@ endOfInput = Parser $ \t pos more lose succ ->
112113atEnd :: Chunk t => Parser t Bool
113114atEnd = not <$> wantInput
114115{-# INLINE atEnd #-}
116+
117+satisfySuspended :: forall t r . Chunk t
118+ => (ChunkElem t -> Bool)
119+ -> State t -> Pos -> More
120+ -> Failure t (State t) r
121+ -> Success t (State t) (ChunkElem t) r
122+ -> IResult t r
123+satisfySuspended p t pos more lose succ =
124+ runParser (demandInput >> go) t pos more lose succ
125+ where go = Parser $ \t' pos' more' lose' succ' ->
126+ case bufferElemAt (undefined :: t) pos' t' of
127+ Just (e, l) | p e -> succ' t' (pos' + Pos l) more' e
128+ | otherwise -> lose' t' pos' more' [] "satisfyElem"
129+ Nothing -> runParser (demandInput >> go) t' pos' more' lose' succ'
130+#if __GLASGOW_HASKELL__ >= 700
131+{-# SPECIALIZE satisfySuspended :: (ChunkElem ByteString -> Bool)
132+ -> State ByteString -> Pos -> More
133+ -> Failure ByteString (State ByteString) r
134+ -> Success ByteString (State ByteString)
135+ (ChunkElem ByteString) r
136+ -> IResult ByteString r #-}
137+{-# SPECIALIZE satisfySuspended :: (ChunkElem Text -> Bool)
138+ -> State Text -> Pos -> More
139+ -> Failure Text (State Text) r
140+ -> Success Text (State Text)
141+ (ChunkElem Text) r
142+ -> IResult Text r #-}
143+#endif
144+
145+-- | The parser @satisfyElem p@ succeeds for any chunk element for which the
146+-- predicate @p@ returns 'True'. Returns the element that is
147+-- actually parsed.
148+satisfyElem :: forall t . Chunk t
149+ => (ChunkElem t -> Bool) -> Parser t (ChunkElem t)
150+satisfyElem p = Parser $ \t pos more lose succ ->
151+ case bufferElemAt (undefined :: t) pos t of
152+ Just (e, l) | p e -> succ t (pos + Pos l) more e
153+ | otherwise -> lose t pos more [] "satisfyElem"
154+ Nothing -> satisfySuspended p t pos more lose succ
155+{-# INLINE satisfyElem #-}
Data/Attoparsec/Internal/Types.hs+11
@@ -34,6 +34,7 @@ import qualified Data.ByteString as BS
3434import Data.Monoid (Monoid(..))
3535import Data.Text (Text)
3636import qualified Data.Text as Text
37+import Data.Text.Unsafe (Iter(..))
3738import Prelude hiding (getChar, succ)
3839import qualified Data.Attoparsec.ByteString.Buffer as B
3940import qualified Data.Attoparsec.Text.Buffer as T
@@ -211,6 +212,8 @@ class Monoid c => Chunk c where
211212 pappendChunk :: State c -> c -> State c
212213 -- | Position at the end of a buffer. The first argument is ignored.
213214 atBufferEnd :: c -> State c -> Pos
215+ -- | Return the buffer element at the given position along with its length.
216+ bufferElemAt :: c -> Pos -> State c -> Maybe (ChunkElem c, Int)
214217
215218instance Chunk ByteString where
216219 type ChunkElem ByteString = Word8
@@ -220,6 +223,10 @@ instance Chunk ByteString where
220223 {-# INLINE pappendChunk #-}
221224 atBufferEnd _ = Pos . B.length
222225 {-# INLINE atBufferEnd #-}
226+ bufferElemAt _ (Pos i) buf
227+ | i < B.length buf = Just (B.unsafeIndex buf i, 1)
228+ | otherwise = Nothing
229+ {-# INLINE bufferElemAt #-}
223230
224231instance Chunk Text where
225232 type ChunkElem Text = Char
@@ -229,3 +236,7 @@ instance Chunk Text where
229236 {-# INLINE pappendChunk #-}
230237 atBufferEnd _ = Pos . T.length
231238 {-# INLINE atBufferEnd #-}
239+ bufferElemAt _ (Pos i) buf
240+ | i < T.length buf = let Iter c l = T.iter buf i in Just (c, l)
241+ | otherwise = Nothing
242+ {-# INLINE bufferElemAt #-}