git.iko.soy/typeable/attoparsec
on master help sign in
WIP
1abf7edBryan O'Sullivan
attoparsec.cabal+5
@@ -6,11 +6,15 @@ category: Text, Parsing
6author: Bryan O'Sullivan <bos@serpentine.com>
6author: Bryan O'Sullivan <bos@serpentine.com>
7maintainer: Bryan O'Sullivan <bos@serpentine.com>
7maintainer: Bryan O'Sullivan <bos@serpentine.com>
8stability: experimental
8stability: experimental
9+tested-with: GHC == 6.8.3, GHC == 6.10.1
9synopsis: Fast combinator parsing with Data.ByteString.Lazy
10synopsis: Fast combinator parsing with Data.ByteString.Lazy
10description: Fast combinator parsing with Data.ByteString.Lazy
11description: Fast combinator parsing with Data.ByteString.Lazy
11cabal-version: >= 1.2
12cabal-version: >= 1.2
12build-type: Simple
13build-type: Simple
13description: Fast, flexible text-oriented parsing of lazy ByteStrings.
14description: Fast, flexible text-oriented parsing of lazy ByteStrings.
15+extra-source-files:
16+ src/Data/ParserCombinators/Attoparsec/Char8Boilerplate.h
17+ src/Data/ParserCombinators/Attoparsec/Word8Boilerplate.h
14
18
15flag split-base
19flag split-base
16flag applicative-in-base
20flag applicative-in-base
@@ -35,6 +39,7 @@ library
35 exposed-modules: Data.ParserCombinators.Attoparsec
39 exposed-modules: Data.ParserCombinators.Attoparsec
36 Data.ParserCombinators.Attoparsec.Char8
40 Data.ParserCombinators.Attoparsec.Char8
37 Data.ParserCombinators.Attoparsec.Incremental
41 Data.ParserCombinators.Attoparsec.Incremental
42+ Data.ParserCombinators.Attoparsec.Incremental.Char8
38 Data.ParserCombinators.Attoparsec.FastSet
43 Data.ParserCombinators.Attoparsec.FastSet
39 Data.ParserCombinators.Attoparsec.Internal
44 Data.ParserCombinators.Attoparsec.Internal
40 hs-source-dirs: src
45 hs-source-dirs: src
src/Data/ParserCombinators/Attoparsec.hs−1
@@ -28,7 +28,6 @@ module Data.ParserCombinators.Attoparsec
28
28
29 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
29 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
30 , try
30 , try
31− , many
32 , many1
31 , many1
33 , manyTill
32 , manyTill
34 , eof
33 , eof
src/Data/ParserCombinators/Attoparsec/Char8.hs+5−67
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1-----------------------------------------------------------------------------
2-----------------------------------------------------------------------------
2-- |
3-- |
3-- Module : Data.ParserCombinators.Attoparsec.Char8
4-- Module : Data.ParserCombinators.Attoparsec.Char8
@@ -28,7 +29,6 @@ module Data.ParserCombinators.Attoparsec.Char8
28
29
29 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
30 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
30 , try
31 , try
31− , many
32 , many1
32 , many1
33 , manyTill
33 , manyTill
34 , eof
34 , eof
@@ -88,84 +88,19 @@ import Data.ParserCombinators.Attoparsec.Internal
88 (Parser, ParseError, (<?>), parse, parseAt, parseTest, try, manyTill, eof,
88 (Parser, ParseError, (<?>), parse, parseAt, parseTest, try, manyTill, eof,
89 skipMany, skipMany1, count, lookAhead, peek, sepBy, sepBy1, string,
89 skipMany, skipMany1, count, lookAhead, peek, sepBy, sepBy1, string,
90 eitherP, getInput, getConsumed, takeAll, takeCount, notEmpty, match,
90 eitherP, getInput, getConsumed, takeAll, takeCount, notEmpty, match,
91− endOfLine, setInput, many, many1)
91+ endOfLine, setInput, many1)
92import Data.ByteString.Lex.Lazy.Double (readDouble)
92import Data.ByteString.Lex.Lazy.Double (readDouble)
93import Prelude hiding (takeWhile)
93import Prelude hiding (takeWhile)
94
94
95−-- | Character parser.
96−satisfy :: (Char -> Bool) -> Parser Char
97−satisfy p = w2c <$> I.satisfy (p . w2c)
98−{-# INLINE satisfy #-}
99−
100−letter :: Parser Char
101−letter = satisfy isLetter <?> "letter"
102−{-# INLINE letter #-}
103−
104−digit :: Parser Char
105−digit = satisfy isDigit <?> "digit"
106−{-# INLINE digit #-}
107−
108−anyChar :: Parser Char
109−anyChar = satisfy $ const True
110−{-# INLINE anyChar #-}
111−
112−space :: Parser Char
113−space = satisfy isSpace <?> "space"
114−{-# INLINE space #-}
115−
116−-- | Satisfy a specific character.
117−char :: Char -> Parser Char
118−char c = satisfy (== c) <?> [c]
119−{-# INLINE char #-}
120−
121−-- | Satisfy a specific character.
122−notChar :: Char -> Parser Char
123−notChar c = satisfy (/= c) <?> "not " ++ [c]
124−{-# INLINE notChar #-}
125−
126−charClass :: String -> FastSet
127−charClass = set . SB.pack . go
128− where go (a:'-':b:xs) = [a..b] ++ go xs
129− go (x:xs) = x : go xs
130− go _ = ""
131−
132−inClass :: String -> Char -> Bool
133−inClass s = (`memberChar` myset)
134− where myset = charClass s
135−{-# INLINE inClass #-}
136−
137−notInClass :: String -> Char -> Bool
138−notInClass s = not . inClass s
139−{-# INLINE notInClass #-}
140−
141-- | Satisfy a literal string, ignoring case.
95-- | Satisfy a literal string, ignoring case.
142stringCI :: LB.ByteString -> Parser LB.ByteString
96stringCI :: LB.ByteString -> Parser LB.ByteString
143stringCI = I.stringTransform (LB.map toLower)
97stringCI = I.stringTransform (LB.map toLower)
144{-# INLINE stringCI #-}
98{-# INLINE stringCI #-}
145
99
146−-- | Consume characters while the predicate is true.
147−takeWhile :: (Char -> Bool) -> Parser LB.ByteString
148−takeWhile p = I.takeWhile (p . w2c)
149−{-# INLINE takeWhile #-}
150−
151−takeTill :: (Char -> Bool) -> Parser LB.ByteString
152−takeTill p = I.takeTill (p . w2c)
153−{-# INLINE takeTill #-}
154−
155takeWhile1 :: (Char -> Bool) -> Parser LB.ByteString
100takeWhile1 :: (Char -> Bool) -> Parser LB.ByteString
156takeWhile1 p = I.takeWhile1 (p . w2c)
101takeWhile1 p = I.takeWhile1 (p . w2c)
157{-# INLINE takeWhile1 #-}
102{-# INLINE takeWhile1 #-}
158
103
159−-- | Skip over characters while the predicate is true.
160−skipWhile :: (Char -> Bool) -> Parser ()
161−skipWhile p = I.skipWhile (p . w2c)
162−{-# INLINE skipWhile #-}
163−
164−-- | Skip over white space.
165−skipSpace :: Parser ()
166−skipSpace = takeWhile isSpace >> return ()
167−{-# INLINE skipSpace #-}
168−
169numeric :: String -> (LB.ByteString -> Maybe (a,LB.ByteString)) -> Parser a
104numeric :: String -> (LB.ByteString -> Maybe (a,LB.ByteString)) -> Parser a
170numeric desc f = do
105numeric desc f = do
171 s <- getInput
106 s <- getInput
@@ -184,3 +119,6 @@ integer = numeric "Integer" LB.readInteger
184-- | Parse a Double. The position counter is not updated.
119-- | Parse a Double. The position counter is not updated.
185double :: Parser Double
120double :: Parser Double
186double = numeric "Double" readDouble
121double = numeric "Double" readDouble
122+
123+#define PARSER Parser
124+#include "Char8Boilerplate.h"
src/Data/ParserCombinators/Attoparsec/Char8Boilerplate.hnew file+66
@@ -0,0 +1,66 @@
1+-- -*- haskell -*-
2+
3+-- | Character parser.
4+satisfy :: (Char -> Bool) -> PARSER Char
5+satisfy p = w2c <$> I.satisfy (p . w2c)
6+{-# INLINE satisfy #-}
7+
8+letter :: PARSER Char
9+letter = satisfy isLetter <?> "letter"
10+{-# INLINE letter #-}
11+
12+digit :: PARSER Char
13+digit = satisfy isDigit <?> "digit"
14+{-# INLINE digit #-}
15+
16+anyChar :: PARSER Char
17+anyChar = satisfy $ const True
18+{-# INLINE anyChar #-}
19+
20+space :: PARSER Char
21+space = satisfy isSpace <?> "space"
22+{-# INLINE space #-}
23+
24+-- | Satisfy a specific character.
25+char :: Char -> PARSER Char
26+char c = satisfy (== c) <?> [c]
27+{-# INLINE char #-}
28+
29+-- | Satisfy a specific character.
30+notChar :: Char -> PARSER Char
31+notChar c = satisfy (/= c) <?> "not " ++ [c]
32+{-# INLINE notChar #-}
33+
34+charClass :: String -> FastSet
35+charClass = set . SB.pack . go
36+ where go (a:'-':b:xs) = [a..b] ++ go xs
37+ go (x:xs) = x : go xs
38+ go _ = ""
39+
40+inClass :: String -> Char -> Bool
41+inClass s = (`memberChar` myset)
42+ where myset = charClass s
43+{-# INLINE inClass #-}
44+
45+notInClass :: String -> Char -> Bool
46+notInClass s = not . inClass s
47+{-# INLINE notInClass #-}
48+
49+-- | Consume characters while the predicate is true.
50+takeWhile :: (Char -> Bool) -> PARSER LB.ByteString
51+takeWhile p = I.takeWhile (p . w2c)
52+{-# INLINE takeWhile #-}
53+
54+takeTill :: (Char -> Bool) -> PARSER LB.ByteString
55+takeTill p = I.takeTill (p . w2c)
56+{-# INLINE takeTill #-}
57+
58+-- | Skip over characters while the predicate is true.
59+skipWhile :: (Char -> Bool) -> PARSER ()
60+skipWhile p = I.skipWhile (p . w2c)
61+{-# INLINE skipWhile #-}
62+
63+-- | Skip over white space.
64+skipSpace :: PARSER ()
65+skipSpace = takeWhile isSpace >> return ()
66+{-# INLINE skipSpace #-}
src/Data/ParserCombinators/Attoparsec/Incremental.hs+83−40
@@ -1,3 +1,4 @@
1+{-# LANGUAGE BangPatterns, CPP #-}
1-----------------------------------------------------------------------------
2-----------------------------------------------------------------------------
2-- |
3-- |
3-- Module : Data.ParserCombinators.Attoparsec.Incremental
4-- Module : Data.ParserCombinators.Attoparsec.Incremental
@@ -11,8 +12,8 @@
11-- Simple, efficient parser combinators for lazy 'LB.ByteString'
12-- Simple, efficient parser combinators for lazy 'LB.ByteString'
12-- strings, loosely based on 'Text.ParserCombinators.Parsec'.
13-- strings, loosely based on 'Text.ParserCombinators.Parsec'.
13--
14--
14−-- Heavily influenced by Adam Langley's incremental parser in the
15+-- This module is heavily influenced by Adam Langley's incremental
15−-- binary-strict package.
16+-- parser in his binary-strict package.
16--
17--
17-----------------------------------------------------------------------------
18-----------------------------------------------------------------------------
18module Data.ParserCombinators.Attoparsec.Incremental
19module Data.ParserCombinators.Attoparsec.Incremental
@@ -21,14 +22,31 @@ module Data.ParserCombinators.Attoparsec.Incremental
21 , Result(..)
22 , Result(..)
22 , parse
23 , parse
23
24
25+ , (<?>)
24 , takeWhile
26 , takeWhile
25 , takeTill
27 , takeTill
28+ , takeCount
26 , string
29 , string
30+ , satisfy
31+ , pushBack
32+
33+ , word8
34+ , notWord8
35+ , anyWord8
36+
37+ , many1
38+ , skipWhile
39+ , skipMany
40+ , skipMany1
41+ , sepBy
42+ , sepBy1
43+ , manyTill
44+ , count
27
45
28 , yield
46 , yield
29 ) where
47 ) where
30
48
31−import Control.Applicative (Alternative(..), Applicative(..))
49+import Control.Applicative
32import Control.Monad (MonadPlus(..), ap)
50import Control.Monad (MonadPlus(..), ap)
33import Data.ParserCombinators.Attoparsec.Internal ((+:))
51import Data.ParserCombinators.Attoparsec.Internal ((+:))
34import Data.Word (Word8)
52import Data.Word (Word8)
@@ -121,17 +139,16 @@ plus p1 p2 =
121instance Functor (Parser r) where
139instance Functor (Parser r) where
122 fmap f m = Parser $ \s cont -> unParser m s (cont . f)
140 fmap f m = Parser $ \s cont -> unParser m s (cont . f)
123
141
124−instance MonadPlus (Parser r) where
142+infix 0 <?>
125− mzero = zero
126− mplus = plus
127
143
128−instance Applicative (Parser r) where
144+-- | Name the parser.
129− pure = return
145+(<?>) :: Parser r a -> String -> Parser r a
130− (<*>) = ap
146+{-# INLINE (<?>) #-}
131−
147+p <?> msg =
132−instance Alternative (Parser r) where
148+ Parser $ \st k ->
133− empty = zero
149+ case unParser p st k of
134− (<|>) = plus
150+ IFailed st' _ -> IFailed st' msg
151+ ok -> ok
135
152
136initState :: S.ByteString -> S
153initState :: S.ByteString -> S
137initState input = S input L.empty [] 0
154initState input = S input L.empty [] 0
@@ -158,39 +175,62 @@ takeWith :: (L.ByteString -> (L.ByteString, L.ByteString))
158 -> Parser r L.ByteString
175 -> Parser r L.ByteString
159takeWith splitf =
176takeWith splitf =
160 Parser $ \(S sb lb adds failDepth) k ->
177 Parser $ \(S sb lb adds failDepth) k ->
161− let bs = sb +: lb
162− (left,rest) = splitf bs
178+ let (left,rest) = splitf (sb +: lb)
163− in case rest of
179+ in case rest of
164− L.Empty -> IPartial $ \s ->
180+ L.Empty -> IPartial $ \s ->
165− let s' = S s L.empty (addX s adds) failDepth
181+ let s' = S s L.empty (addX s adds) failDepth
166− k' a = k (appL left a)
182+ k' a = k (appL left a)
167− in unParser (takeWith splitf) s' k'
183+ in unParser (takeWith splitf) s' k'
168− L.Chunk h t -> k left (S h t adds failDepth)
184+ L.Chunk h t -> k left (S h t adds failDepth)
169−
185+
170−string :: L.ByteString -> Parser r L.ByteString
171−string s = string' s
172− where
173− string' r =
174− Parser $ \st@(S sb lb adds failDepth) k ->
175− let bs = sb +: lb
176− l = L.length r
177− in case L.splitAt l bs of
178− (h,t)
179− | h == r -> k s (mkState t adds failDepth)
180− (h,L.Empty)
181− | h `L.isPrefixOf` r ->
182− IPartial $ \s' ->
183− let st' = S s' L.empty (addX s' adds) failDepth
184− k' a = k (appL h a)
185− in unParser (string (L.drop (L.length h) r)) st' k'
186− _ -> IFailed st "string failed to match"
187−
188takeWhile :: (Word8 -> Bool) -> Parser r L.ByteString
186takeWhile :: (Word8 -> Bool) -> Parser r L.ByteString
189takeWhile = takeWith . L.span
187takeWhile = takeWith . L.span
190
188
191takeTill :: (Word8 -> Bool) -> Parser r L.ByteString
189takeTill :: (Word8 -> Bool) -> Parser r L.ByteString
192takeTill = takeWith . L.break
190takeTill = takeWith . L.break
193
191
192+takeCount :: Int -> Parser r L.ByteString
193+takeCount = tc . fromIntegral where
194+ tc (!n) = Parser $ \(S sb lb adds failDepth) k ->
195+ let (h,t) = L.splitAt n (sb +: lb)
196+ l = L.length h
197+ in if L.length h == n
198+ then k h (mkState t adds failDepth)
199+ else IPartial $ \s ->
200+ let st = S s L.empty (addX s adds) failDepth
201+ k' a = k (appL h a)
202+ in unParser (tc (n - l)) st k'
203+
204+string :: L.ByteString -> Parser r L.ByteString
205+string s =
206+ Parser $ \st@(S sb lb adds failDepth) k ->
207+ case L.splitAt (L.length s) (sb +: lb) of
208+ (h,t)
209+ | h == s -> k s (mkState t adds failDepth)
210+ (h,L.Empty)
211+ | h `L.isPrefixOf` s ->
212+ IPartial $ \s' ->
213+ let st' = S s' L.empty (addX s' adds) failDepth
214+ k' a = k (appL h a)
215+ r' = L.drop (L.length h) s
216+ in unParser (string r') st' k'
217+ _ -> IFailed st "string failed to match"
218+
219+satisfy :: (Word8 -> Bool) -> Parser r Word8
220+satisfy p =
221+ Parser $ \st@(S sb lb adds failDepth) k ->
222+ case L.uncons (sb +: lb) of
223+ Just (w, lb') | p w -> k w (mkState lb' adds failDepth)
224+ | otherwise -> IFailed st "failed to match"
225+ Nothing -> IPartial $ \s ->
226+ let st' = S s L.empty (addX s adds) failDepth
227+ in unParser (satisfy p) st' k
228+
229+pushBack :: L.ByteString -> Parser r ()
230+pushBack bs =
231+ Parser $ \(S sb lb adds failDepth) k ->
232+ k () (mkState (bs `appL` (sb +: lb)) adds failDepth)
233+
194toplevelTranslate :: IResult a -> Result a
234toplevelTranslate :: IResult a -> Result a
195toplevelTranslate (IFailed _ err) = Failed err
235toplevelTranslate (IFailed _ err) = Failed err
196toplevelTranslate (IDone (S sb lb _ _) value) = Done (sb +: lb) value
236toplevelTranslate (IDone (S sb lb _ _) value) = Done (sb +: lb) value
@@ -202,3 +242,6 @@ terminalContinuation v s = IDone s v
202parse :: Parser r r -> S.ByteString -> Result r
242parse :: Parser r r -> S.ByteString -> Result r
203parse m input =
243parse m input =
204 toplevelTranslate $ unParser m (initState input) terminalContinuation
244 toplevelTranslate $ unParser m (initState input) terminalContinuation
245+
246+#define PARSER Parser r
247+#include "Word8Boilerplate.h"
src/Data/ParserCombinators/Attoparsec/Incremental/Char8.hsnew file+103
@@ -0,0 +1,103 @@
1+{-# LANGUAGE CPP #-}
2+-----------------------------------------------------------------------------
3+-- |
4+-- Module : Data.ParserCombinators.Attoparsec.Incremental.Char8
5+-- Copyright : Daan Leijen 1999-2001, Jeremy Shaw 2006, Bryan O'Sullivan 2007-2008
6+-- License : BSD3
7+--
8+-- Maintainer : bos@serpentine.com
9+-- Stability : experimental
10+-- Portability : unknown
11+--
12+-- Simple, efficient parser combinators for lazy 'LB.ByteString'
13+-- strings, loosely based on 'Text.ParserCombinators.Parsec'.
14+--
15+-----------------------------------------------------------------------------
16+module Data.ParserCombinators.Attoparsec.Incremental.Char8
17+ (
18+ -- * Parser
19+ Parser
20+ , Result(..)
21+
22+ -- * Running parsers
23+ , parse
24+
25+ -- * Combinators
26+ , (<?>)
27+
28+ -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
29+ , many1
30+ , manyTill
31+ , skipMany
32+ , skipMany1
33+ , count
34+ , sepBy
35+ , sepBy1
36+ , pushBack
37+
38+ -- * Things like in @Parsec.Char@
39+ , satisfy
40+ , letter
41+ , digit
42+ , anyChar
43+ , space
44+ , char
45+ , notChar
46+ , string
47+
48+ -- * Numeric parsers.
49+ , int
50+ , integer
51+ , double
52+
53+ -- * Miscellaneous functions.
54+ , takeWhile
55+ , takeTill
56+ , takeCount
57+ , skipWhile
58+ , skipSpace
59+ , inClass
60+ , notInClass
61+ ) where
62+
63+import Control.Applicative ((<$>))
64+import qualified Data.ByteString.Char8 as SB
65+import qualified Data.ByteString.Lazy.Char8 as LB
66+import Data.ByteString.Internal (w2c)
67+import Data.Char (isDigit, isLetter, isSpace)
68+import Data.ParserCombinators.Attoparsec.FastSet
69+ (FastSet, memberChar, set)
70+import qualified Data.ParserCombinators.Attoparsec.Incremental as I
71+import Data.ParserCombinators.Attoparsec.Incremental
72+ (Parser, Result(..), (<?>), parse, manyTill, pushBack,
73+ skipMany, skipMany1, count, sepBy, sepBy1, string,
74+ takeCount, many1)
75+import Data.ByteString.Lex.Lazy.Double (readDouble)
76+import Prelude hiding (takeWhile)
77+
78+numeric :: String -> (Char -> Bool)
79+ -> (LB.ByteString -> Maybe (a,LB.ByteString)) -> Parser r a
80+numeric desc p f = do
81+ s <- takeWhile p
82+ case f s of
83+ Nothing -> pushBack s >> fail desc
84+ Just (i,s') -> pushBack s' >> return i
85+
86+isIntegral :: Char -> Bool
87+isIntegral c = isDigit c || c == '-'
88+
89+-- | Parse an integer. The position counter is not updated.
90+int :: Parser r Int
91+int = numeric "Int" isIntegral LB.readInt
92+
93+-- | Parse an integer. The position counter is not updated.
94+integer :: Parser r Integer
95+integer = numeric "Integer" isIntegral LB.readInteger
96+
97+-- | Parse a Double. The position counter is not updated.
98+double :: Parser r Double
99+double = numeric "Double" isDouble readDouble
100+ where isDouble c = isIntegral c || c == 'e' || c == '+'
101+
102+#define PARSER Parser r
103+#include "../Char8Boilerplate.h"
src/Data/ParserCombinators/Attoparsec/Internal.hs+11−68
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1-----------------------------------------------------------------------------
2-----------------------------------------------------------------------------
2-- |
3-- |
3-- Module : Data.ParserCombinators.Attoparsec.Internal
4-- Module : Data.ParserCombinators.Attoparsec.Internal
@@ -28,7 +29,6 @@ module Data.ParserCombinators.Attoparsec.Internal
28
29
29 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
30 -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@)
30 , try
31 , try
31− , many
32 , many1
32 , many1
33 , manyTill
33 , manyTill
34 , eof
34 , eof
@@ -69,8 +69,8 @@ module Data.ParserCombinators.Attoparsec.Internal
69 , (+:)
69 , (+:)
70 ) where
70 ) where
71
71
72−import Control.Applicative (Alternative(..), Applicative(..), (<$>))
72+import Control.Applicative
73−import Control.Monad (MonadPlus(..), ap, liftM2)
73+import Control.Monad (MonadPlus(..), ap)
74import Control.Monad.Fix (MonadFix(..))
74import Control.Monad.Fix (MonadFix(..))
75import qualified Data.ByteString as SB
75import qualified Data.ByteString as SB
76import qualified Data.ByteString.Lazy as LB
76import qualified Data.ByteString.Lazy as LB
@@ -132,18 +132,6 @@ plus p1 p2 =
132 ok -> ok
132 ok -> ok
133{-# INLINE plus #-}
133{-# INLINE plus #-}
134
134
135−instance MonadPlus Parser where
136− mzero = zero
137− mplus = plus
138−
139−instance Applicative Parser where
140− pure = return
141− (<*>) = ap
142−
143−instance Alternative Parser where
144− empty = zero
145− (<|>) = plus
146−
147mkState :: LB.ByteString -> Int64 -> S
135mkState :: LB.ByteString -> Int64 -> S
148mkState s = case s of
136mkState s = case s of
149 LB.Empty -> S SB.empty s
137 LB.Empty -> S SB.empty s
@@ -194,26 +182,6 @@ satisfy p =
194 Nothing -> unParser (nextChunk >> satisfy p) s
182 Nothing -> unParser (nextChunk >> satisfy p) s
195{-# INLINE satisfy #-}
183{-# INLINE satisfy #-}
196
184
197−anyWord8 :: Parser Word8
198−anyWord8 = satisfy $ const True
199−{-# INLINE anyWord8 #-}
200−
201−-- | Satisfy a specific character.
202−word8 :: Word8 -> Parser Word8
203−word8 c = satisfy (== c) <?> show c
204−{-# INLINE word8 #-}
205−
206−-- | Satisfy a specific character.
207−notWord8 :: Word8 -> Parser Word8
208−notWord8 c = satisfy (/= c) <?> "not " ++ show c
209−{-# INLINE notWord8 #-}
210−
211−sepBy :: Parser a -> Parser s -> Parser [a]
212−sepBy p s = liftM2 (:) p ((s >> sepBy1 p s) <|> return []) <|> return []
213−
214−sepBy1 :: Parser a -> Parser s -> Parser [a]
215−sepBy1 p s = liftM2 (:) p ((s >> sepBy1 p s) <|> return [])
216−
217-- | Satisfy a literal string.
185-- | Satisfy a literal string.
218string :: LB.ByteString -> Parser LB.ByteString
186string :: LB.ByteString -> Parser LB.ByteString
219string s = Parser $ \(S sb lb n) ->
187string s = Parser $ \(S sb lb n) ->
@@ -253,11 +221,6 @@ stringTransform f s = Parser $ \(S sb lb n) ->
253 where fs = f s
221 where fs = f s
254{-# INLINE stringTransform #-}
222{-# INLINE stringTransform #-}
255
223
256−-- | Apply the given parser repeatedly, returning every parse result.
257−count :: Int -> Parser a -> Parser [a]
258−count n p = sequence (replicate n p)
259−{-# INLINE count #-}
260−
261try :: Parser a -> Parser a
224try :: Parser a -> Parser a
262try p = Parser $ \s@(S sb lb _) ->
225try p = Parser $ \s@(S sb lb _) ->
263 case unParser p s of
226 case unParser p s of
@@ -275,13 +238,14 @@ takeAll = Parser $ \(S sb lb n) ->
275 let bs = sb +: lb
238 let bs = sb +: lb
276 in Right (bs, mkState LB.empty (n + LB.length bs))
239 in Right (bs, mkState LB.empty (n + LB.length bs))
277
240
278−takeCount :: Int64 -> Parser LB.ByteString
241+takeCount :: Int -> Parser LB.ByteString
279takeCount k =
242takeCount k =
280 Parser $ \(S sb lb n) ->
243 Parser $ \(S sb lb n) ->
281 let bs = sb +: lb
244 let bs = sb +: lb
245+ k' = fromIntegral k
282− (h,t) = LB.splitAt k bs
246+ (h,t) = LB.splitAt k' bs
283− in if LB.length h == k
247+ in if LB.length h == k'
284− then Right (h, mkState t (n + k))
248+ then Right (h, mkState t (n + k'))
285 else Left (bs, [show k ++ " bytes"])
249 else Left (bs, [show k ++ " bytes"])
286
250
287-- | Consume characters while the predicate is true.
251-- | Consume characters while the predicate is true.
@@ -308,30 +272,6 @@ takeWhile1 p =
308 | otherwise -> Right (h, mkState t (n + LB.length h))
272 | otherwise -> Right (h, mkState t (n + LB.length h))
309{-# INLINE takeWhile1 #-}
273{-# INLINE takeWhile1 #-}
310
274
311−-- | Skip over characters while the predicate is true.
312−skipWhile :: (Word8 -> Bool) -> Parser ()
313−skipWhile p = takeWhile p >> return ()
314−{-# INLINE skipWhile #-}
315−
316−manyTill :: Parser a -> Parser b -> Parser [a]
317−manyTill p end = scan
318− where scan = (end >> return []) <|> liftM2 (:) p scan
319−
320−many :: Parser a -> Parser [a]
321−many p = ((:) <$> p <*> many p) <|> return []
322−
323−many1 :: Parser a -> Parser [a]
324−many1 p = (:) <$> p <*> many p
325−
326−-- |'skipMany' - skip zero or many instances of the parser
327−skipMany :: Parser a -> Parser ()
328−skipMany p = scan
329− where scan = (p >> scan) <|> return ()
330−
331−-- |'skipMany1' - skip one or many instances of the parser
332−skipMany1 :: Parser a -> Parser ()
333−skipMany1 p = p >> skipMany p
334−
335-- | Test that a parser returned a non-null ByteString.
275-- | Test that a parser returned a non-null ByteString.
336notEmpty :: Parser LB.ByteString -> Parser LB.ByteString
276notEmpty :: Parser LB.ByteString -> Parser LB.ByteString
337notEmpty p = Parser $ \s ->
277notEmpty p = Parser $ \s ->
@@ -391,3 +331,6 @@ parseTest p s =
391 case parse p s of
331 case parse p s of
392 (st, Left msg) -> putStrLn $ msg ++ "\nGot:\n" ++ show st
332 (st, Left msg) -> putStrLn $ msg ++ "\nGot:\n" ++ show st
393 (_, Right r) -> print r
333 (_, Right r) -> print r
334+
335+#define PARSER Parser
336+#include "Word8Boilerplate.h"
src/Data/ParserCombinators/Attoparsec/Word8Boilerplate.hnew file+60
@@ -0,0 +1,60 @@
1+-- -*- haskell -*-
2+-- This file is intended to be #included by other source files.
3+
4+instance MonadPlus (PARSER) where
5+ mzero = zero
6+ mplus = plus
7+
8+instance Applicative (PARSER) where
9+ pure = return
10+ (<*>) = ap
11+
12+instance Alternative (PARSER) where
13+ empty = zero
14+ (<|>) = plus
15+
16+-- | Skip over characters while the predicate is true.
17+skipWhile :: (Word8 -> Bool) -> PARSER ()
18+skipWhile p = takeWhile p *> pure ()
19+{-# INLINE skipWhile #-}
20+
21+many1 :: PARSER a -> PARSER [a]
22+many1 p = liftA2 (:) p (many p)
23+
24+sepBy :: PARSER a -> PARSER s -> PARSER [a]
25+sepBy p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure []) <|> pure []
26+
27+sepBy1 :: PARSER a -> PARSER s -> PARSER [a]
28+sepBy1 p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure [])
29+
30+manyTill :: PARSER a -> PARSER b -> PARSER [a]
31+manyTill p end = scan
32+ where scan = (end *> pure []) <|> liftA2 (:) p scan
33+
34+-- | Skip zero or more instances of the parser.
35+skipMany :: PARSER a -> PARSER ()
36+skipMany p = scan
37+ where scan = (p >> scan) <|> return ()
38+
39+-- | Skip one or more instances of the parser.
40+skipMany1 :: PARSER a -> PARSER ()
41+skipMany1 p = p >> skipMany p
42+
43+-- | Apply the given parser repeatedly, returning every parse result.
44+count :: Int -> PARSER a -> PARSER [a]
45+count n p = sequence (replicate n p)
46+{-# INLINE count #-}
47+
48+anyWord8 :: PARSER Word8
49+anyWord8 = satisfy $ const True
50+{-# INLINE anyWord8 #-}
51+
52+-- | Satisfy a specific character.
53+word8 :: Word8 -> PARSER Word8
54+word8 c = satisfy (== c) <?> show c
55+{-# INLINE word8 #-}
56+
57+-- | Satisfy a specific character.
58+notWord8 :: Word8 -> PARSER Word8
59+notWord8 c = satisfy (/= c) <?> "not " ++ show c
60+{-# INLINE notWord8 #-}