git.iko.soy/typeable/attoparsec
on master help sign in
Work in progress. New Word8 API is more or less done for now.
commit497b2bb390a097cb8a077ddf23a44fd8a82a944e authorBryan O'Sullivan <bos@serpentine.com> dateMon 15 Feb 2010, 20:22 (17 years ago) parent91af999
8 files changed+305−857
Data/Attoparsec.hs+9−14 Data/Attoparsec/Char8.hs+1−7 Data/Attoparsec/Combinator.hs+10−2 Data/Attoparsec/Incremental.hs−358 Data/Attoparsec/Incremental/Char8.hs−121 Data/Attoparsec/Internal.hs+281−277 Data/Attoparsec/Word8Boilerplate.h−69 attoparsec.cabal+4−9
Data/Attoparsec.hs+9−14
@@ -1,26 +1,25 @@
11-----------------------------------------------------------------------------
22-- |
33-- Module : Data.Attoparsec
4−-- Copyright : Daan Leijen 1999-2001, Jeremy Shaw 2006, Bryan O'Sullivan 2007-2008
4+-- Copyright : Bryan O'Sullivan 2007-2010
55-- License : BSD3
66--
77-- Maintainer : bos@serpentine.com
88-- Stability : experimental
99-- Portability : unknown
1010--
11−-- Simple, efficient parser combinators for lazy 'ByteString'
12−-- strings, loosely based on 'Text.ParserCombinators.Parsec'.
11+-- Simple, efficient parser combinators for 'ByteString' strings,
12+-- loosely based on 'Text.ParserCombinators.Parsec'.
1313--
1414-----------------------------------------------------------------------------
1515module Data.Attoparsec
1616 (
1717 -- * Parser types
18− ParseError
19− , Parser
18+ Parser
19+ , Result
2020
2121 -- * Running parsers
2222 , parse
23− , parseAt
2423 , parseTest
2524
2625 -- * Combinators
@@ -42,22 +41,18 @@ module Data.Attoparsec
4241 , string
4342 , skipWhile
4443 , stringTransform
45− , takeAll
4644 , takeTill
4745 , takeWhile
4846 , takeWhile1
4947
50− -- ** Combinators
51− , match
52− , notEmpty
53−
5448 -- * State observation functions
5549 , endOfInput
56− , getConsumed
57− , getInput
58− , lookAhead
5950 ) where
6051
6152import Data.Attoparsec.Combinator
6253import Data.Attoparsec.Internal
6354import Prelude hiding (takeWhile)
55+import qualified Data.ByteString as B
56+
57+parseTest :: (Show a) => Parser a -> B.ByteString -> IO ()
58+parseTest p s = print (parse p s)
Data/Attoparsec/Char8.hs+1−7
@@ -80,7 +80,6 @@ module Data.Attoparsec.Char8
8080 , module Data.Attoparsec.Combinator
8181 ) where
8282
83−import qualified Data.ByteString.Lazy.Char8 as LB
8483import Data.ByteString.Internal (c2w, w2c)
8584import Data.Char (isDigit, isLetter, isSpace, toLower)
8685import Data.Attoparsec.FastSet (charClass, memberChar)
@@ -88,12 +87,7 @@ import Data.Word (Word8)
8887import qualified Data.Attoparsec.Internal as I
8988import Data.Attoparsec.Combinator
9089import Data.Attoparsec.Internal
91− (Parser, ParseError, (<?>), parse, parseAt, parseTest, try, endOfInput,
92− lookAhead, string,
93− getInput, getConsumed, takeAll, takeCount, notEmpty, match,
94− endOfLine, setInput)
95−import Data.ByteString.Lex.Lazy.Double (readDouble)
96−import Prelude hiding (takeWhile)
90+import Data.ByteString.Lex.Double (readDouble)
9791
9892-- | Satisfy a literal string, ignoring case.
9993stringCI :: LB.ByteString -> Parser LB.ByteString
Data/Attoparsec/Combinator.hs+10−2
@@ -24,10 +24,11 @@ module Data.Attoparsec.Combinator
2424 , skipMany
2525 , skipMany1
2626 , eitherP
27− , module Control.Applicative
27+ -- * Inlined implementations of existing functions
28+ , many
2829 ) where
2930
30−import Control.Applicative
31+import Control.Applicative (Alternative(..), Applicative(..), liftA2, (*>), (<$>))
3132
3233-- | @choice ps@ tries to apply the actions in the list @ps@ in order,
3334-- until one of them succeeds. Returns the value of the succeeding
@@ -49,6 +50,7 @@ option x p = p <|> pure x
4950-- > word = many1 letter
5051many1 :: Alternative f => f a -> f [a]
5152many1 p = liftA2 (:) p (many p)
53+{-# INLINE many1 #-}
5254
5355-- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
5456-- by @sep@. Returns a list of the values returned by @p@.
@@ -95,3 +97,9 @@ count n p = sequence (replicate n p)
9597eitherP :: (Alternative f) => f a -> f b -> f (Either a b)
9698eitherP a b = (Left <$> a) <|> (Right <$> b)
9799{-# INLINE eitherP #-}
100+
101+many :: (Alternative f) => f a -> f [a]
102+many v = many_v
103+ where many_v = some_v <|> pure []
104+ some_v = (:) <$> v <*> many_v
105+{-# INLINE many #-}
Data/Attoparsec/Incremental.hsdeleted−358
@@ -1,358 +0,0 @@
1−{-# LANGUAGE BangPatterns, CPP #-}
2−-----------------------------------------------------------------------------
3−-- |
4−-- Module : Data.Attoparsec.Incremental
5−-- Copyright : Bryan O'Sullivan 2009
6−-- License : BSD3
7−--
8−-- Maintainer : bos@serpentine.com
9−-- Stability : experimental
10−-- Portability : unknown
11−--
12−-- Simple, efficient, and incremental parser combinators for lazy
13−-- 'L.ByteString' strings, loosely based on the Parsec library.
14−--
15−-- This module is heavily influenced by Adam Langley's incremental
16−-- parser in his @binary-strict@ package.
17−--
18−-----------------------------------------------------------------------------
19−module Data.Attoparsec.Incremental
20− (
21− -- * Incremental parsing
22− -- $incremental
23−
24− -- * Parser types
25− Parser
26− , Result(..)
27−
28− -- * Running parsers
29− , parse
30− , parseWith
31− , parseTest
32− , feed
33−
34− -- * Combinators
35− , (<?>)
36− , try
37−
38− -- * Parsing individual bytes
39− , word8
40− , notWord8
41− , anyWord8
42− , satisfy
43−
44− -- ** Byte classes
45− , inClass
46− , notInClass
47−
48− -- * Efficient string handling
49− , string
50− , skipWhile
51− , takeCount
52− , takeTill
53− , takeWhile
54−
55− -- * State observation and manipulation functions
56− , endOfInput
57− , pushBack
58− , yield
59−
60− -- * Combinators
61− , module Data.Attoparsec.Combinator
62− ) where
63−
64−import Data.Attoparsec.Combinator
65−import Control.Monad (MonadPlus(..), ap)
66−import Data.Attoparsec.FastSet (charClass, memberWord8)
67−import Data.Attoparsec.Internal ((+:))
68−import Data.Word (Word8)
69−import qualified Data.ByteString as S
70−import qualified Data.ByteString.Lazy as L
71−import qualified Data.ByteString.Lazy.Internal as L
72−import Prelude hiding (takeWhile)
73−
74−-- $incremental
75−-- Incremental parsing makes it possible to supply a parser with only
76−-- a limited amount of input. If the parser cannot complete due to
77−-- lack of data, it will return a 'Partial' result with a continuation
78−-- to which more input can be supplied, as follows:
79−--
80−-- > case parse myParser someInput of
81−-- > Partial k -> k moreInput
82−--
83−-- To signal that no more input is available, pass an empty
84−-- string to this continuation.
85−
86−data S = S {-# UNPACK #-} !S.ByteString -- first chunk of input
87− L.ByteString -- rest of input
88− [L.ByteString] -- input acquired during backtracks
89− !Bool -- have we hit EOF yet?
90− {-# UNPACK #-} !Int -- failure depth
91−
92−-- | The result of a partial parse.
93−data Result a = Failed String
94− -- ^ The parse failed, with the given error message.
95− | Done L.ByteString a
96− -- ^ The parse succeeded, producing the given
97− -- result. The 'L.ByteString' contains any unconsumed
98− -- input.
99− | Partial (L.ByteString -> Result a)
100− -- ^ The parse ran out of data before finishing. To
101− -- resume the parse, pass more data to the given
102− -- continuation. To indicate that no more input is
103− -- available, pass the empty string.
104−
105−instance (Show a) => Show (Result a) where
106− show (Failed err) = "Failed " ++ show err
107− show (Done L.Empty rs) = "Done Empty " ++ show rs
108− show (Done rest rs) = "Done (" ++ show rest ++ ") " ++ show rs
109− show (Partial _) = "Partial"
110−
111−-- | This is the internal version of the above. This is the type which
112−-- is actually used by the code, as it has the extra information
113−-- needed for backtracking. This is converted to a friendly 'Result'
114−-- type just before giving it to the outside world.
115−data IResult a = IFailed S String
116− | IDone S a
117− | IPartial (L.ByteString -> IResult a)
118−
119−instance Show (IResult a) where
120− show (IFailed _ err) = "IFailed " ++ show err
121− show (IDone _ _) = "IDone"
122− show (IPartial _) = "IPartial"
123−
124−-- | The parser type.
125−newtype Parser r a = Parser {
126− unParser :: S -> (a -> S -> IResult r) -> IResult r
127− }
128−
129−returnP :: a -> Parser r a
130−returnP a = Parser $ \s k -> k a s
131−{-# INLINE returnP #-}
132−
133−bindP :: Parser r a -> (a -> Parser r b) -> Parser r b
134−bindP m k = Parser $ \s cont -> unParser m s $ \a s' -> unParser (k a) s' cont
135−{-# INLINE bindP #-}
136−
137−failP :: String -> Parser r a
138−failP err = Parser $ \s _ -> IFailed s err
139−{-# INLINE failP #-}
140−
141−zero :: Parser r a
142−zero = fail ""
143−{-# INLINE zero #-}
144−
145−-- | I'm not sure if this is a huge bodge or not. It probably is.
146−--
147−-- When performing a choice (in @plus@), the failure depth in the
148−-- current state is incremented. If a failure is generated inside the
149−-- attempted path, the state carried in the IFailure will have this
150−-- incremented failure depth. However, we don't want to backtrack
151−-- after the attempted path has completed. Thus we insert this cut
152−-- continuation, which decrements the failure count of any failure
153−-- passing though, thus it would be caught in @plus@ and doesn't
154−-- trigger a backtrack.
155−cutContinuation :: (a -> S -> IResult r) -> a -> S -> IResult r
156−cutContinuation k v s =
157− case k v s of
158− IFailed (S sb lb adds eof failDepth) err ->
159− IFailed (S sb lb adds eof (failDepth - 1)) err
160− x -> x
161−
162−appL :: L.ByteString -> L.ByteString -> L.ByteString
163−appL xs L.Empty = xs
164−appL L.Empty ys = ys
165−appL xs ys = xs `L.append` ys
166−
167−plus :: Parser r a -> Parser r a -> Parser r a
168−plus p1 p2 =
169− Parser $ \(S sb lb adds eof failDepth) k ->
170− let
171− filt f@(IFailed (S _ _ adds' eof' failDepth') _)
172− | failDepth' == failDepth + 1 =
173− let lb' = lb `appL` L.concat (reverse adds')
174− in unParser p2 (S sb lb' (adds' ++ adds) eof' failDepth) k
175− | otherwise = f
176− filt (IPartial cont) = IPartial (filt . cont)
177− filt v@(IDone _ _) = v
178− in
179− filt $ unParser p1 (S sb lb [] eof (failDepth + 1)) (cutContinuation k)
180−
181−-- | This is a no-op combinator for compatibility.
182−try :: Parser r a -> Parser r a
183−try p = p
184−
185−fmapP :: (a -> b) -> Parser r a -> Parser r b
186−fmapP f m = Parser $ \s cont -> unParser m s (cont . f)
187−{-# INLINE fmapP #-}
188−
189−infix 0 <?>
190−
191−-- | Name the parser, in case failure occurs.
192−(<?>) :: Parser r a
193− -> String -- ^ the name to use if parsing fails
194− -> Parser r a
195−{-# INLINE (<?>) #-}
196−p <?> msg =
197− Parser $ \st k ->
198− case unParser p st k of
199− IFailed st' _ -> IFailed st' msg
200− ok -> ok
201−
202−initState :: L.ByteString -> S
203−initState (L.Chunk sb lb) = S sb lb [] False 0
204−initState _ = S S.empty L.empty [] False 0
205−
206−mkState :: L.ByteString -> [L.ByteString] -> Bool -> Int -> S
207−mkState bs adds eof failDepth =
208− case bs of
209− L.Empty -> S S.empty L.empty adds eof failDepth
210− L.Chunk sb lb -> S sb lb adds eof failDepth
211−
212−addX :: L.ByteString -> [L.ByteString] -> [L.ByteString]
213−addX s adds | L.null s = adds
214− | otherwise = s : adds
215−
216−-- | Resume our caller, handing back a 'Partial' result. This function
217−-- is probably not useful, but provided for completeness.
218−yield :: Parser r ()
219−yield = Parser $ \(S sb lb adds eof failDepth) k ->
220− IPartial $ \s -> k () (S sb (lb `appL` s) (addX s adds) eof failDepth)
221−
222−continue :: (S -> IResult r) -> Parser r a
223− -> (a -> S -> IResult r) -> S -> IResult r
224−continue onEOF p k (S _sb _lb adds eof failDepth) =
225− if eof
226− then onEOF (S S.empty L.empty adds True failDepth)
227− else IPartial $ \s ->
228− let st | L.null s = S S.empty L.empty adds True failDepth
229− | otherwise = mkState s (addX s adds) False failDepth
230− in unParser p st k
231−
232−takeWith :: (L.ByteString -> (L.ByteString, L.ByteString))
233− -> Parser r L.ByteString
234−takeWith splitf =
235− Parser $ \st@(S sb lb adds eof failDepth) k ->
236− let (left,rest) = splitf (sb +: lb)
237− in if L.null rest
238− then continue (k left) (takeWith splitf) (k . appL left) st
239− else k left (mkState rest adds eof failDepth)
240−
241−-- | Consume bytes while the predicate succeeds.
242−takeWhile :: (Word8 -> Bool) -> Parser r L.ByteString
243−takeWhile = takeWith . L.span
244−
245−-- | Consume bytes while the predicate fails. If the predicate never
246−-- succeeds, the entire input string is returned.
247−takeTill :: (Word8 -> Bool) -> Parser r L.ByteString
248−takeTill = takeWith . L.break
249−
250−-- | Return exactly the given number of bytes. If not enough are
251−-- available, fail.
252−takeCount :: Int -> Parser r L.ByteString
253−takeCount = tc . fromIntegral where
254− tc n = Parser $ \st@(S sb lb adds eof failDepth) k ->
255− let (h,t) = L.splitAt n (sb +: lb)
256− l = L.length h
257− in if L.length h == n
258− then k h (mkState t adds eof failDepth)
259− else continue (`IFailed` "takeCount: EOF")
260− (tc (n - l)) (k . appL h) st
261−
262−-- | Match a literal string exactly.
263−string :: L.ByteString -> Parser r L.ByteString
264−string s =
265− Parser $ \st@(S sb lb adds eof failDepth) k ->
266− case L.splitAt (L.length s) (sb +: lb) of
267− (h,t)
268− | h == s -> k s (mkState t adds eof failDepth)
269− (h,L.Empty)
270− | h `L.isPrefixOf` s ->
271− continue (`IFailed` "string: EOF")
272− (string (L.drop (L.length h) s))
273− (k . appL h)
274− st
275− _ -> IFailed st "string failed to match"
276−
277−-- | Match a single byte based on the given predicate.
278−satisfy :: (Word8 -> Bool) -> Parser r Word8
279−satisfy p =
280− Parser $ \st@(S sb lb adds eof failDepth) k ->
281− case S.uncons sb of
282− Just (w, sb') | p w -> k w (S sb' lb adds eof failDepth)
283− | otherwise -> IFailed st "failed to match"
284− Nothing -> case L.uncons lb of
285− Just (w, lb') | p w -> k w (mkState lb' adds eof failDepth)
286− | otherwise -> IFailed st "failed to match"
287− Nothing -> continue (`IFailed` "satisfy: EOF")
288− (satisfy p) k st
289−
290−-- | Force the given string to appear next in the input stream.
291−pushBack :: L.ByteString -> Parser r ()
292−pushBack bs =
293− Parser $ \(S sb lb adds eof failDepth) k ->
294− k () (mkState (bs `appL` (sb +: lb)) adds eof failDepth)
295−
296−-- | Succeed if we have reached the end of the input string.
297−endOfInput :: Parser r ()
298−endOfInput = Parser $ \st@(S sb lb _adds _eof _failDepth) k ->
299− if not (S.null sb) || not (L.null lb)
300− then IFailed st "endOfInput: not EOF"
301− else continue (k ()) endOfInput k st
302−
303−toplevelTranslate :: IResult a -> Result a
304−toplevelTranslate (IFailed _ err) = Failed err
305−toplevelTranslate (IDone (S sb lb _ _ _) value) = Done (sb +: lb) value
306−toplevelTranslate (IPartial k) = Partial $ toplevelTranslate . k
307−
308−terminalContinuation :: a -> S -> IResult a
309−terminalContinuation v s = IDone s v
310−
311−-- | Run a parser.
312−parse :: Parser r r -> L.ByteString -> Result r
313−parse m input =
314− toplevelTranslate $ unParser m (initState input) terminalContinuation
315−
316−-- | Run a parser, using the given function to resupply it with input.
317−--
318−-- Here's an example that shows how to parse data from a socket, using
319−-- Johan Tibbell's @network-bytestring@ package.
320−--
321−-- > import qualified Data.ByteString.Lazy as L
322−-- > import Data.Attoparsec.Incremental (Parser, Result, parseWith)
323−-- > import Network.Socket.ByteString.Lazy (recv_)
324−-- > import Network.Socket (Socket)
325−-- >
326−-- > netParse :: Parser r r -> Socket -> IO (Result r)
327−-- > netParse p sock = parseWith (recv_ sock 65536) p L.empty
328−parseWith :: Applicative f => f L.ByteString -- ^ resupply parser with input
329− -> Parser r r -- ^ parser to run
330− -> L.ByteString -- ^ initial input
331− -> f (Result r)
332−parseWith refill p s =
333− case parse p s of
334− Partial k -> k <$> refill
335− ok -> pure ok
336−
337−-- | Try out a parser, and print its result.
338−parseTest :: (Show r) => Parser r r -> L.ByteString -> IO ()
339−parseTest p s = print (parse p s)
340−
341−-- | Attempt to feed more data to a 'Result'.
342−--
343−-- * If the original parse 'Failed', the string is not inspected, and
344−-- the result remains a failed parse.
345−--
346−-- * If the parse was 'Done', the string is appended to the remainder,
347−-- and the result of the parse is otherwise the same 'Done' as
348−-- before.
349−--
350−-- * If the parse was 'Partial', the string is fed to the continuation
351−-- and the new 'Result' returned.
352−feed :: Result a -> L.ByteString -> Result a
353−feed f@(Failed _) _ = f
354−feed (Done bs a) c = Done (L.append bs c) a
355−feed (Partial k) c = k c
356−
357−#define PARSER Parser r
358−#include "Word8Boilerplate.h"
Data/Attoparsec/Incremental/Char8.hsdeleted−121
@@ -1,121 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−-----------------------------------------------------------------------------
3−-- |
4−-- Module : Data.Attoparsec.Incremental.Char8
5−-- Copyright : Bryan O'Sullivan 2009
6−-- License : BSD3
7−--
8−-- Maintainer : bos@serpentine.com
9−-- Stability : experimental
10−-- Portability : unknown
11−--
12−-- Simple, efficient, character-oriented, and incremental parser
13−-- combinators for lazy 'L.ByteString' strings, loosely based on the
14−-- Parsec library.
15−--
16−-- /Note/: This module is intended for parsing text that is
17−-- represented using an 8-bit character set, e.g. ASCII or
18−-- ISO-8859-15. It /does not/ deal with character encodings,
19−-- multibyte characters, or wide characters. Any attempts to use
20−-- characters above code point 255 will give wrong answers.
21−-----------------------------------------------------------------------------
22−module Data.Attoparsec.Incremental.Char8
23− (
24− -- * Parser types
25− Parser
26− , Result(..)
27−
28− -- * Running parsers
29− , parse
30− , parseWith
31− , parseTest
32− , feed
33−
34− -- * Combinators
35− , (<?>)
36− , try
37−
38− -- * Parsing individual characters
39− , satisfy
40− , letter
41− , digit
42− , anyChar
43− , space
44− , char
45− , char8
46− , notChar
47−
48− -- ** Character classes
49− , inClass
50− , notInClass
51−
52− -- * Efficient string handling
53− , string
54− , skipSpace
55− , skipWhile
56− , takeCount
57− , takeTill
58− , takeWhile
59−
60− -- * Text parsing
61− , endOfLine
62−
63− -- * Numeric parsers
64− , int
65− , integer
66− , double
67−
68− -- * State observation and manipulation functions
69− , endOfInput
70− , pushBack
71− , yield
72−
73− -- * Combinators
74− , module Data.Attoparsec.Combinator
75− ) where
76−
77−import qualified Data.ByteString.Lazy.Char8 as LB
78−import Data.ByteString.Internal (c2w, w2c)
79−import Data.Char (isDigit, isLetter, isSpace)
80−import Data.Word (Word8)
81−import Data.Attoparsec.FastSet (charClass, memberChar)
82−import qualified Data.Attoparsec.Incremental as I
83−import Data.Attoparsec.Incremental
84− (Parser, Result(..), (<?>), endOfInput, feed, parse, parseWith, parseTest,
85− pushBack, string, takeCount, try, yield)
86−import Data.ByteString.Lex.Lazy.Double (readDouble)
87−import Prelude hiding (takeWhile)
88−import Data.Attoparsec.Combinator
89−
90−numeric :: String -> (Char -> Bool)
91− -> (LB.ByteString -> Maybe (a,LB.ByteString)) -> Parser r a
92−numeric desc p f = do
93− s <- takeWhile p
94− case f s of
95− Nothing -> pushBack s >> fail desc
96− Just (i,s') -> pushBack s' >> return i
97−
98−isIntegral :: Char -> Bool
99−isIntegral c = isDigit c || c == '-'
100−
101−-- | Parse an 'Int'.
102−int :: Parser r Int
103−int = numeric "Int" isIntegral LB.readInt
104−
105−-- | Parse an 'Integer'.
106−integer :: Parser r Integer
107−integer = numeric "Integer" isIntegral LB.readInteger
108−
109−-- | Parse a 'Double'.
110−double :: Parser r Double
111−double = numeric "Double" isDouble readDouble
112− where isDouble c = isIntegral c || c == 'e' || c == '+'
113−
114−-- | Match the end of a line. This may be any of a newline character,
115−-- a carriage return character, or a carriage return followed by a newline.
116−endOfLine :: Parser r ()
117−endOfLine = (char '\n' *> pure ()) <|> (string crlf *> pure ())
118− where crlf = LB.pack "\r\n"
119−
120−#define PARSER Parser r
121−#include "../Char8Boilerplate.h"
Data/Attoparsec/Internal.hs+281−277
@@ -1,32 +1,33 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE Rank2Types, RecordWildCards #-}
22-----------------------------------------------------------------------------
33-- |
44-- Module : Data.Attoparsec.Internal
5−-- Copyright : Daan Leijen 1999-2001, Jeremy Shaw 2006, Bryan O'Sullivan 2007-2008
5+-- Copyright : Bryan O'Sullivan 2007-2010
66-- License : BSD3
77--
88-- Maintainer : bos@serpentine.com
99-- Stability : experimental
1010-- Portability : unknown
1111--
12−-- Simple, efficient parser combinators for lazy 'LB.ByteString'
13−-- strings, loosely based on 'Text.ParserCombinators.Parsec'.
12+-- Simple, efficient parser combinators for 'bB.ByteString' strings,
13+-- loosely based on 'Text.ParserCombinators.Parsec'.
1414--
1515-----------------------------------------------------------------------------
1616module Data.Attoparsec.Internal
1717 (
1818 -- * Parser types
19− ParseError
20− , Parser
19+ Parser
20+ , Result(..)
2121
2222 -- * Running parsers
2323 , parse
24− , parseAt
25− , parseTest
24+ , parseAll
25+ , feed
2626
2727 -- * Combinators
2828 , (<?>)
2929 , try
30+ , module Data.Attoparsec.Combinator
3031
3132 -- * Parsing individual bytes
3233 , satisfy
@@ -38,312 +39,315 @@ module Data.Attoparsec.Internal
3839 , inClass
3940 , notInClass
4041
42+ -- * Parsing more complicated structures
43+ , storable
44+
4145 -- * Efficient string handling
42− , match
43− , notEmpty
4446 , skipWhile
4547 , string
4648 , stringTransform
47− , takeAll
48− , takeCount
49+ , take
4950 , takeTill
5051 , takeWhile
5152 , takeWhile1
5253
5354 -- * State observation functions
55+ , ensure
5456 , endOfInput
55− , getConsumed
56− , getInput
57− , lookAhead
58− , setInput
5957
6058 -- * Utilities
6159 , endOfLine
62− , (+:)
6360 ) where
6461
65−import Control.Applicative
66− (Alternative(..), Applicative(..), (*>))
67−import Control.Monad (MonadPlus(..))
68−import Control.Monad.Fix (MonadFix(..))
62+import Control.Applicative (Alternative(..), Applicative(..), (<$>))
63+import Control.Monad (MonadPlus(..), when)
64+import Data.Attoparsec.Combinator
6965import Data.Attoparsec.FastSet (charClass, memberWord8)
70−import qualified Data.ByteString as SB
71−import qualified Data.ByteString.Lazy as LB
72−import qualified Data.ByteString.Lazy.Char8 as L8
73−import qualified Data.ByteString.Unsafe as U
74−import qualified Data.ByteString.Internal as I
75−import qualified Data.ByteString.Lazy.Internal as LB
76−import Data.Int (Int64)
66+import Data.Monoid (Monoid(..))
7767import Data.Word (Word8)
78−import Prelude hiding (takeWhile)
68+import Foreign.ForeignPtr (withForeignPtr)
69+import Foreign.Ptr (castPtr, plusPtr)
70+import Foreign.Storable (Storable(peek, sizeOf))
71+import Prelude hiding (getChar, take, takeWhile)
72+import qualified Data.ByteString as B8
73+import qualified Data.ByteString.Char8 as B
74+import qualified Data.ByteString.Internal as B
75+import qualified Data.ByteString.Unsafe as B
76+
77+data Result r = Fail S [String] String
78+ | Partial (B.ByteString -> Result r)
79+ | Done S r
80+
81+-- | The Parser monad is an Exception and State monad.
82+newtype Parser a = Parser {
83+ runParser :: forall r. S
84+ -> Failure r
85+ -> Success a r
86+ -> Result r
87+ }
7988
80−-- ^ A description of a parsing error.
81−type ParseError = String
89+type Failure r = S -> [String] -> String -> Result r
90+type Success a r = S -> a -> Result r
8291
83−-- State invariants:
84−-- * If both strict and lazy bytestrings are empty, the entire input
85−-- is considered to be empty.
86−data S = S {-# UNPACK #-} !SB.ByteString
87− LB.ByteString
88− {-# UNPACK #-} !Int64
92+data More = Complete | Incomplete
93+ deriving (Eq, Show)
8994
90−-- ^ A parser that produces a result of type @a@.
91−newtype Parser a = Parser {
92− unParser :: S -> Either (LB.ByteString, [String]) (a, S)
93− }
95+plusMore :: More -> More -> More
96+plusMore Complete _ = Complete
97+plusMore _ Complete = Complete
98+plusMore _ _ = Incomplete
99+{-# INLINE plusMore #-}
94100
95−fmapP :: (a -> b) -> Parser a -> Parser b
96−fmapP f p = Parser $ \s ->
97− case unParser p s of
98− Right (a, s') -> Right (f a, s')
99− Left err -> Left err
100−{-# INLINE fmapP #-}
101+instance Monoid More where
102+ mempty = Incomplete
103+ mappend = plusMore
101104
102−returnP :: a -> Parser a
103−returnP a = Parser $ \s -> Right (a, s)
104−{-# INLINE returnP #-}
105+data S = S {
106+ input :: !B.ByteString
107+ , _added :: !B.ByteString
108+ , more :: !More
109+ } deriving (Show)
110+
111+instance Show r => Show (Result r) where
112+ show (Fail _ stack msg) = "Fail " ++ show stack ++ " " ++ show msg
113+ show (Partial _) = "Partial _"
114+ show (Done bs r) = "Done " ++ show bs ++ " " ++ show r
115+
116+addS :: S -> S -> S
117+addS (S s0 a0 c0) (S _s1 a1 c1) = S (s0 +++ a1) (a0 +++ a1) (mappend c0 c1)
118+{-# INLINE addS #-}
119+
120+instance Monoid S where
121+ mempty = S B.empty B.empty Incomplete
122+ mappend = addS
105123
106124bindP :: Parser a -> (a -> Parser b) -> Parser b
107−bindP m f = Parser $ \s ->
108− case unParser m s of
109− Right (a, s') -> unParser (f a) s'
110− Left (s', msgs) -> Left (s', msgs)
125+bindP m g =
126+ Parser (\st0 kf ks -> runParser m st0 kf (\s a -> runParser (g a) s kf ks))
111127{-# INLINE bindP #-}
112128
113−failP :: String -> Parser a
114−failP err = Parser $ \(S sb lb _) -> Left (sb +: lb, [err])
115−{-# INLINE failP #-}
129+returnP :: a -> Parser a
130+returnP a = Parser (\st0 _kf ks -> ks st0 a)
131+{-# INLINE returnP #-}
116132
117−instance MonadFix Parser where
118− mfix f = Parser $ \s ->
119− let r = case r of
120− Right (a, _) -> unParser (f a) s
121− err -> err
122− in r
133+instance Monad Parser where
134+ return = returnP
135+ (>>=) = bindP
136+ fail = failDesc
123137
124−zero :: Parser a
125−zero = Parser $ \(S sb lb _) -> Left (sb +: lb, [])
126−{-# INLINE zero #-}
138+clear :: S -> S
139+clear (S s0 _a0 c0) = S s0 B.empty c0
140+{-# INLINE clear #-}
127141
128142plus :: Parser a -> Parser a -> Parser a
129−plus p1 p2 =
130− Parser $ \s@(S sb lb _) ->
131− case unParser p1 s of
132− Left (_, msgs1) ->
133− case unParser p2 s of
134− Left (_, msgs2) -> Left (sb +: lb, (msgs1 ++ msgs2))
135− ok -> ok
136− ok -> ok
143+plus a b = Parser $ \st0 kf ks ->
144+ let kf' st1 _ _ = runParser b (mappend st0 st1) kf ks
145+ in runParser a (clear st0) kf' ks
137146{-# INLINE plus #-}
138147
139−mkState :: LB.ByteString -> Int64 -> S
140−mkState s = case s of
141− LB.Empty -> S SB.empty s
142− LB.Chunk x xs -> S x xs
148+instance MonadPlus Parser where
149+ mzero = failDesc "mzero"
150+ mplus = plus
143151
144−-- | Turn our split representation back into a normal lazy ByteString.
145−(+:) :: SB.ByteString -> LB.ByteString -> LB.ByteString
146−sb +: lb | SB.null sb = lb
147− | otherwise = LB.Chunk sb lb
148−{-# INLINE (+:) #-}
152+fmapP :: (a -> b) -> Parser a -> Parser b
153+fmapP p m = Parser (\st0 f k -> runParser m st0 f (\s a -> k s (p a)))
154+{-# INLINE fmapP #-}
149155
150−infix 0 <?>
156+instance Functor Parser where
157+ fmap = fmapP
158+
159+apP :: Parser (a -> b) -> Parser a -> Parser b
160+apP d e = do
161+ b <- d
162+ a <- e
163+ return (b a)
164+{-# INLINE apP #-}
165+
166+instance Applicative Parser where
167+ pure = returnP
168+ (<*>) = apP
169+
170+instance Alternative Parser where
171+ empty = failDesc "empty"
172+ (<|>) = mplus
173+
174+failDesc :: String -> Parser a
175+failDesc err = Parser (\st0 kf _ks -> kf st0 [] msg)
176+ where msg = "Failed reading: " ++ err
177+{-# INLINE failDesc #-}
178+
179+ensure :: Int -> Parser ()
180+ensure n = Parser $ \st0@(S s0 _a0 _c0) kf ks ->
181+ if B.length s0 >= n
182+ then ks st0 ()
183+ else runParser (requireInput >> ensure n) st0 kf ks
184+
185+requireInput :: Parser ()
186+requireInput = Parser $ \st0@(S s0 a0 c0) kf ks ->
187+ if c0 == Complete
188+ then kf st0 ["requireInput"] "not enough bytes"
189+ else Partial $ \s ->
190+ if B.null s
191+ then kf (S s0 a0 Complete) ["requireInput"] "not enough bytes"
192+ else let st1 = S (s0 +++ s) (a0 +++ s) Incomplete
193+ in ks st1 ()
194+
195+failK :: Failure a
196+failK st0 stack msg = Fail st0 stack msg
197+
198+successK :: Success a a
199+successK state a = Done state a
200+
201+get :: Parser B.ByteString
202+get = Parser (\st0 _kf ks -> ks st0 (input st0))
203+
204+put :: B.ByteString -> Parser ()
205+put s = Parser (\(S _s0 a0 c0) _kf ks -> ks (S s a0 c0) ())
206+
207+take :: Int -> Parser B.ByteString
208+take n = takeWith n (const True)
209+
210+(+++) :: B.ByteString -> B.ByteString -> B.ByteString
211+(+++) = B.append
212+{-# INLINE (+++) #-}
213+
214+try :: Parser a -> Parser a
215+try p = Parser $ \st0 kf ks ->
216+ runParser p (clear st0) (kf . mappend st0) ks
151217
152−-- | Name the parser, in case failure occurs.
153−(<?>) :: Parser a
154− -> String -- ^ the name to use if parsing fails
155− -> Parser a
156−p <?> msg =
157− Parser $ \s@(S sb lb _) ->
158− case unParser p s of
159− (Left _) -> Left (sb +: lb, [msg])
160− ok -> ok
161−{-# INLINE (<?>) #-}
162−
163−nextChunk :: Parser ()
164−nextChunk = Parser $ \(S _ lb n) ->
165− case lb of
166− LB.Chunk sb' lb' -> Right ((), S sb' lb' n)
167− LB.Empty -> Left (lb, [])
168−
169−-- | Get remaining input.
170−getInput :: Parser LB.ByteString
171−getInput = Parser $ \s@(S sb lb _) -> Right (sb +: lb, s)
172−
173−-- | Set the remaining input.
174−setInput :: LB.ByteString -> Parser ()
175−setInput bs = Parser $ \(S _ _ n) -> Right ((), mkState bs n)
176−
177−-- | Get number of bytes consumed so far.
178−getConsumed :: Parser Int64
179−getConsumed = Parser $ \s@(S _ _ n) -> Right (n, s)
180−
181−-- | Match a single byte based on the given predicate.
182218satisfy :: (Word8 -> Bool) -> Parser Word8
183−satisfy p =
184− Parser $ \s@(S sb lb n) ->
185− case SB.uncons sb of
186− Just (c, sb') | p c -> Right (c, mkState (sb' +: lb) (n + 1))
187− | otherwise -> Left (sb +: lb, [])
188− Nothing -> unParser (nextChunk >> satisfy p) s
219+satisfy p = do
220+ ensure 1
221+ s <- get
222+ let w = B.unsafeHead s
223+ if p w
224+ then put (B.unsafeTail s) >> return w
225+ else fail "satisfy"
189226{-# INLINE satisfy #-}
190227
191−-- | Match a literal string exactly.
192−string :: LB.ByteString -> Parser LB.ByteString
193−string s = Parser $ \(S sb lb n) ->
194− let bs = sb +: lb
195− l = LB.length s
196− (h,t) = LB.splitAt l bs
197− in if s == h
198− then Right (s, mkState t (n + l))
199− else Left (bs, [])
200−{-# INLINE string #-}
201−
202−-- | Match the end of a line. This may be any of a newline character,
203−-- a carriage return character, or a carriage return followed by a newline.
204−endOfLine :: Parser ()
205−endOfLine = Parser $ \(S sb lb n) ->
206− let bs = sb +: lb
207− in if SB.null sb
208− then Left (bs, ["EOL"])
209− else case I.w2c (U.unsafeHead sb) of
210− '\n' -> Right ((), mkState (LB.tail bs) (n + 1))
211− '\r' -> let (h,t) = LB.splitAt 2 bs
212− rn = L8.pack "\r\n"
213− in if h == rn
214− then Right ((), mkState t (n + 2))
215− else Right ((), mkState (LB.tail bs) (n + 1))
216− _ -> Left (bs, ["EOL"])
217−
218−-- | Match a literal string, after applying a transformation to both
219−-- it and the matching text. Useful for e.g. case insensitive string
220−-- comparison.
221−stringTransform :: (LB.ByteString -> LB.ByteString) -> LB.ByteString
222− -> Parser LB.ByteString
223−stringTransform f s = Parser $ \(S sb lb n) ->
224− let bs = sb +: lb
225− l = LB.length s
226− (h, t) = LB.splitAt l bs
227− in if fs == f h
228− then Right (s, mkState t (n + l))
229− else Left (bs, [])
230− where fs = f s
231−{-# INLINE stringTransform #-}
232−
233−-- | Attempt a parse, but do not consume any input if the parse fails.
234−try :: Parser a -> Parser a
235−try p = Parser $ \s@(S sb lb _) ->
236− case unParser p s of
237− Left (_, msgs) -> Left (sb +: lb, msgs)
238− ok -> ok
228+storable :: Storable a => Parser a
229+storable = hack undefined
230+ where
231+ hack :: Storable b => b -> Parser b
232+ hack dummy = do
233+ (fp,o,_) <- B.toForeignPtr `fmapP` take (sizeOf dummy)
234+ return . B.inlinePerformIO . withForeignPtr fp $ \p -> peek (castPtr $ p `plusPtr` o)
235+
236+takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString
237+takeWith n p = do
238+ ensure n
239+ s <- get
240+ let (h,t) = B.splitAt n s
241+ if p h
242+ then put t >> return h
243+ else failDesc "takeWith"
244+{-# INLINE takeWith #-}
245+
246+string :: B.ByteString -> Parser B.ByteString
247+string s = takeWith (B.length s) (==s)
248+
249+stringTransform :: (B.ByteString -> B.ByteString) -> B.ByteString
250+ -> Parser B.ByteString
251+stringTransform f s = takeWith (B.length s) ((==s) . f)
252+
253+skipWhile :: (Word8 -> Bool) -> Parser ()
254+skipWhile p = do
255+ (`when` requireInput) =<< B.null <$> get
256+ t <- B8.dropWhile p <$> get
257+ put t
258+ if B.null t
259+ then (skipWhile p <|> return ())
260+ else return ()
261+
262+takeTill :: (Word8 -> Bool) -> Parser B.ByteString
263+takeTill p = takeWhile (not . p)
264+
265+takeWhile :: (Word8 -> Bool) -> Parser B.ByteString
266+takeWhile p = do
267+ (`when` requireInput) =<< B.null <$> get
268+ (h,t) <- B8.span p <$> get
269+ put t
270+ if B.null t
271+ then (h+++) `fmapP` (takeWhile p <|> return B.empty)
272+ else return h
273+
274+takeWhile1 :: (Word8 -> Bool) -> Parser B.ByteString
275+takeWhile1 p = do
276+ (`when` requireInput) =<< B.null <$> get
277+ (h,t) <- B8.span p <$> get
278+ when (B.null h) $ failDesc "takeWhile1"
279+ put t
280+ if B.null t
281+ then (h+++) `fmapP` (takeWhile p <|> return B.empty)
282+ else return h
283+
284+-- | Match any character in a set.
285+--
286+-- > vowel = inClass "aeiou"
287+--
288+-- Range notation is supported.
289+--
290+-- > halfAlphabet = inClass "a-nA-N"
291+--
292+-- To add a literal \'-\' to a set, place it at the beginning or end
293+-- of the string.
294+inClass :: String -> Word8 -> Bool
295+inClass s = (`memberWord8` mySet)
296+ where mySet = charClass s
297+{-# INLINE inClass #-}
298+
299+-- | Match any character not in a set.
300+notInClass :: String -> Word8 -> Bool
301+notInClass s = not . inClass s
302+{-# INLINE notInClass #-}
303+
304+-- | Match any byte.
305+anyWord8 :: Parser Word8
306+anyWord8 = satisfy $ const True
307+{-# INLINE anyWord8 #-}
308+
309+-- | Match a specific byte.
310+word8 :: Word8 -> Parser Word8
311+word8 c = satisfy (== c) <?> show c
312+{-# INLINE word8 #-}
313+
314+-- | Match any byte except the given one.
315+notWord8 :: Word8 -> Parser Word8
316+notWord8 c = satisfy (/= c) <?> "not " ++ show c
317+{-# INLINE notWord8 #-}
239318
240−-- | Succeed if we have reached the end of the input string.
241319endOfInput :: Parser ()
242−endOfInput = Parser $ \s@(S sb lb _) -> if SB.null sb && LB.null lb
243− then Right ((), s)
244− else Left (sb +: lb, ["EOF"])
245−
246−-- | Return all of the remaining input as a single string.
247−takeAll :: Parser LB.ByteString
248−takeAll = Parser $ \(S sb lb n) ->
249− let bs = sb +: lb
250− in Right (bs, mkState LB.empty (n + LB.length bs))
251−
252−-- | Return exactly the given number of bytes. If not enough are
253−-- available, fail.
254−takeCount :: Int -> Parser LB.ByteString
255−takeCount k =
256− Parser $ \(S sb lb n) ->
257− let bs = sb +: lb
258− k' = fromIntegral k
259− (h,t) = LB.splitAt k' bs
260− in if LB.length h == k'
261− then Right (h, mkState t (n + k'))
262− else Left (bs, [show k ++ " bytes"])
263−
264−-- | Consume bytes while the predicate succeeds.
265−takeWhile :: (Word8 -> Bool) -> Parser LB.ByteString
266−takeWhile p =
267− Parser $ \(S sb lb n) ->
268− let (h,t) = LB.span p (sb +: lb)
269− in Right (h, mkState t (n + LB.length h))
270−{-# INLINE takeWhile #-}
271−
272−-- | Consume bytes while the predicate fails. If the predicate never
273−-- succeeds, the entire input string is returned.
274−takeTill :: (Word8 -> Bool) -> Parser LB.ByteString
275−takeTill p =
276− Parser $ \(S sb lb n) ->
277− let (h,t) = LB.break p (sb +: lb)
278− in Right (h, mkState t (n + LB.length h))
279−{-# INLINE takeTill #-}
280−
281−-- | Consume bytes while the predicate is true. Fails if the
282−-- predicate fails on the first byte.
283−takeWhile1 :: (Word8 -> Bool) -> Parser LB.ByteString
284−takeWhile1 p =
285− Parser $ \(S sb lb n) ->
286− case LB.span p (sb +: lb) of
287− (h,t) | LB.null h -> Left (t, [])
288− | otherwise -> Right (h, mkState t (n + LB.length h))
289−{-# INLINE takeWhile1 #-}
290−
291−-- | Test that a parser returned a non-null 'LB.ByteString'.
292−notEmpty :: Parser LB.ByteString -> Parser LB.ByteString
293−notEmpty p = Parser $ \s ->
294− case unParser p s of
295− o@(Right (a, _)) ->
296− if LB.null a
297− then Left (a, ["notEmpty"])
298− else o
299− x -> x
300−
301−-- | Parse some input with the given parser, and return the input it
302−-- consumed as a string.
303−match :: Parser a -> Parser LB.ByteString
304−match p = do bs <- getInput
305− start <- getConsumed
306− p
307− end <- getConsumed
308− return (LB.take (end - start) bs)
309−
310−-- | Apply a parser without consuming any input.
311−lookAhead :: Parser a -> Parser a
312−lookAhead p = Parser $ \s ->
313− case unParser p s of
314− Right (m, _) -> Right (m, s)
315− err -> err
316−
317−-- | Run a parser. The 'Int64' value is used as a base to count the
318−-- number of bytes consumed.
319−parseAt :: Parser a -- ^ parser to run
320− -> LB.ByteString -- ^ input to parse
321− -> Int64 -- ^ offset to count input from
322− -> (LB.ByteString, Either ParseError (a, Int64))
323−parseAt p bs n =
324− case unParser p (mkState bs n) of
325− Left (bs', msg) -> (bs', Left $ showError msg)
326− Right (a, ~(S sb lb n')) -> (sb +: lb, Right (a, n'))
327− where
328− showError [""] = "Parser error\n"
329− showError [msg] = "Parser error, expected:\n" ++ msg ++ "\n"
330− showError [] = "Parser error\n"
331− showError msgs = "Parser error, expected one of:\n" ++ unlines msgs
332−
333−-- | Run a parser.
334−parse :: Parser a -- ^ parser to run
335− -> LB.ByteString -- ^ input to parse
336− -> (LB.ByteString, Either ParseError a)
337−parse p bs = case parseAt p bs 0 of
338− (bs', Right (a, _)) -> (bs', Right a)
339− (bs', Left err) -> (bs', Left err)
340−
341−-- | Try out a parser, and print its result.
342−parseTest :: (Show a) => Parser a -> LB.ByteString -> IO ()
343−parseTest p s =
344− case parse p s of
345− (st, Left msg) -> putStrLn $ msg ++ "\nGot:\n" ++ show st
346− (_, Right r) -> print r
347−
348−#define PARSER Parser
349−#include "Word8Boilerplate.h"
320+endOfInput = Parser $ \st0@S{..} kf ks ->
321+ if B.null input
322+ then if more == Complete
323+ then ks st0 ()
324+ else let kf' st1 _ _ = ks (mappend st0 st1) ()
325+ ks' st1 _ = kf (mappend st0 st1) [] "endOfInput"
326+ in runParser requireInput st0 kf' ks'
327+ else kf st0 [] "endOfInput"
328+
329+endOfLine :: Parser ()
330+endOfLine = (word8 10 >> return ()) <|> (string (B.pack "\r\n") >> return ())
331+
332+--- | Name the parser, in case failure occurs.
333+(<?>) :: Parser a
334+ -> String -- ^ the name to use if parsing fails
335+ -> Parser a
336+p <?> _msg = p
337+infix 0 <?>
338+
339+parse :: Parser a -> B.ByteString -> Result a
340+parse m s = runParser m (S s B.empty Incomplete) failK successK
341+
342+feed :: Result r -> B.ByteString -> Result r
343+feed f@(Fail _ _ _) _ = f
344+feed (Partial k) d = k d
345+feed (Done (S s a c) r) d = Done (S (s +++ d) a c) r
346+
347+parseAll :: Parser a -> [B.ByteString] -> Result a
348+parseAll p ss = case ss of
349+ [] -> go (parse p B.empty) []
350+ (c:cs) -> go (parse p c) cs
351+ where go (Partial k) (c:cs) = go (k c) cs
352+ go (Partial k) [] = k B.empty
353+ go r _ = r
Data/Attoparsec/Word8Boilerplate.hdeleted−69
@@ -1,69 +0,0 @@
1−-- -*- haskell -*-
2−-- This file is intended to be #included by other source files.
3−
4−instance Monad (PARSER) where
5− return = returnP
6− (>>=) = bindP
7− fail = failP
8−
9−instance MonadPlus (PARSER) where
10− mzero = zero
11− mplus = plus
12−
13−apP :: PARSER (a -> b) -> PARSER a -> PARSER b
14−apP d e = do
15− b <- d
16− a <- e
17− return (b a)
18−{-# INLINE apP #-}
19−
20−instance Functor (PARSER) where
21− fmap = fmapP
22−
23−instance Applicative (PARSER) where
24− pure = returnP
25− (<*>) = apP
26−
27−instance Alternative (PARSER) where
28− empty = zero
29− (<|>) = plus
30−
31−-- | Match any character in a set.
32−--
33−-- > vowel = inClass "aeiou"
34−--
35−-- Range notation is supported.
36−--
37−-- > halfAlphabet = inClass "a-nA-N"
38−--
39−-- To add a literal \'-\' to a set, place it at the beginning or end
40−-- of the string.
41−inClass :: String -> Word8 -> Bool
42−inClass s = (`memberWord8` mySet)
43− where mySet = charClass s
44−{-# INLINE inClass #-}
45−
46−-- | Match any character not in a set.
47−notInClass :: String -> Word8 -> Bool
48−notInClass s = not . inClass s
49−{-# INLINE notInClass #-}
50−
51−-- | Skip over bytes while the predicate is true.
52−skipWhile :: (Word8 -> Bool) -> PARSER ()
53−skipWhile p = takeWhile p *> pure ()
54−{-# INLINE skipWhile #-}
55−
56−-- | Match any byte.
57−anyWord8 :: PARSER Word8
58−anyWord8 = satisfy $ const True
59−{-# INLINE anyWord8 #-}
60−
61−-- | Match a specific byte.
62−word8 :: Word8 -> PARSER Word8
63−word8 c = satisfy (== c) <?> show c
64−{-# INLINE word8 #-}
65−
66−-- | Match any byte except the given one.
67−notWord8 :: Word8 -> PARSER Word8
68−notWord8 c = satisfy (/= c) <?> "not " ++ show c
69−{-# INLINE notWord8 #-}
attoparsec.cabal+4−9
@@ -1,5 +1,5 @@
11name: attoparsec
2−version: 0.7.2
2+version: 0.8.0.0
33license: BSD3
44license-file: LICENSE
55category: Text, Parsing
@@ -7,14 +7,11 @@ author: Bryan O'Sullivan <bos@serpentine.com>
77maintainer: Bryan O'Sullivan <bos@serpentine.com>
88stability: experimental
99tested-with: GHC == 6.8.3, GHC == 6.10.1
10−synopsis: Fast combinator parsing with Data.ByteString.Lazy
11−description: Fast combinator parsing with Data.ByteString.Lazy
10+synopsis: Fast bytestring combinator parsing
11+description: Fast bytestring combinator parsing
1212cabal-version: >= 1.2
1313build-type: Simple
1414description: Fast, flexible text-oriented parsing of lazy ByteStrings.
15−extra-source-files:
16− Data/Attoparsec/Char8Boilerplate.h
17− Data/Attoparsec/Word8Boilerplate.h
1815
1916flag split-base
2017flag applicative-in-base
@@ -37,10 +34,8 @@ library
3734
3835 extensions: CPP
3936 exposed-modules: Data.Attoparsec
40− Data.Attoparsec.Char8
37+ --Data.Attoparsec.Char8
4138 Data.Attoparsec.Combinator
42− Data.Attoparsec.Incremental
43− Data.Attoparsec.Incremental.Char8
4439 Data.Attoparsec.FastSet
4540 other-modules: Data.Attoparsec.Internal
4641 ghc-options: -Wall