@@ -22,6 +22,7 @@ module Data.ParserCombinators.Attoparsec.Incremental
22 , Result(..)
22 , Result(..)
24 , parseWith
24 , parseWith
27 , takeWhile
28 , takeWhile
@@ -35,14 +36,7 @@ module Data.ParserCombinators.Attoparsec.Incremental
35 , notWord8
36 , notWord8
36 , anyWord8
37 , anyWord8
39 , skipWhile
39 , skipWhile
@@ -59,6 +53,7 @@ import Prelude hiding (takeWhile)
59data S = S {-# UNPACK #-} !S.ByteString -- ^ first chunk of input
53data S = S {-# UNPACK #-} !S.ByteString -- ^ first chunk of input
60 L.ByteString -- ^ rest of input
54 L.ByteString -- ^ rest of input
61 [L.ByteString] -- ^ input acquired during backtracks
55 [L.ByteString] -- ^ input acquired during backtracks
56+ !Bool -- ^ have we hit EOF yet?
62 {-# UNPACK #-} !Int -- ^ failure depth
57 {-# UNPACK #-} !Int -- ^ failure depth
64-- | The result of a partial parse
59-- | The result of a partial parse
@@ -73,9 +68,10 @@ data Result a = Failed String
73 -- parse pass more data to the given continuation
68 -- parse pass more data to the given continuation
75instance (Show a) => Show (Result a) where
70instance (Show a) => Show (Result a) where
76− show (Failed err) = "Failed " ++ err
71+ show (Failed err) = "Failed " ++ show err
72+ show (Done L.Empty rs) = "Done Empty " ++ show rs
77− show (Done rest rs) = "Done " ++ show rest ++ " " ++ show rs
73+ show (Done rest rs) = "Done (" ++ show rest ++ ") " ++ show rs
78− show (Partial _) = "Partial"
74+ show (Partial _) = "Partial"
80-- | This is the internal version of the above. This is the type which is
76-- | This is the internal version of the above. This is the type which is
81-- actually used by the code, as it has the extra information needed
77-- actually used by the code, as it has the extra information needed
@@ -86,9 +82,9 @@ data IResult a = IFailed S String
86 | IPartial (L.ByteString -> IResult a)
82 | IPartial (L.ByteString -> IResult a)
88instance Show (IResult a) where
84instance Show (IResult a) where
89− show (IFailed _ err) = "IFailed " ++ err
85+ show (IFailed _ err) = "IFailed " ++ show err
90− show (IDone _ _) = "IDone"
86+ show (IDone _ _) = "IDone"
91− show (IPartial _) = "IPartial"
87+ show (IPartial _) = "IPartial"
93newtype Parser r a = Parser {
89newtype Parser r a = Parser {
94 unParser :: S -> (a -> S -> IResult r) -> IResult r
90 unParser :: S -> (a -> S -> IResult r) -> IResult r
@@ -115,7 +111,7 @@ zero = fail ""
115cutContinuation :: (a -> S -> IResult r) -> a -> S -> IResult r
111cutContinuation :: (a -> S -> IResult r) -> a -> S -> IResult r
116cutContinuation k v s =
112cutContinuation k v s =
117 case k v s of
113 case k v s of
118− IFailed (S lb i adds failDepth) err -> IFailed (S lb i adds (failDepth - 1)) err
114+ IFailed (S lb i adds eof failDepth) err -> IFailed (S lb i adds eof (failDepth - 1)) err
121appL :: L.ByteString -> L.ByteString -> L.ByteString
117appL :: L.ByteString -> L.ByteString -> L.ByteString
@@ -125,17 +121,17 @@ appL xs ys = xs `L.append` ys
126plus :: Parser r a -> Parser r a -> Parser r a
122plus :: Parser r a -> Parser r a -> Parser r a
127plus p1 p2 =
123plus p1 p2 =
128− Parser $ \(S sb lb adds failDepth) k ->
124+ Parser $ \(S sb lb adds eof failDepth) k ->
130− filt f@(IFailed (S _ _ adds' failDepth') _)
126+ filt f@(IFailed (S _ _ adds' eof' failDepth') _)
131 | failDepth' == failDepth + 1 =
127 | failDepth' == failDepth + 1 =
132 let lb' = lb `appL` L.concat (reverse adds')
128 let lb' = lb `appL` L.concat (reverse adds')
133− in unParser p2 (S sb lb' (adds' ++ adds) failDepth) k
129+ in unParser p2 (S sb lb' (adds' ++ adds) eof' failDepth) k
134 | otherwise = f
130 | otherwise = f
135 filt (IPartial cont) = IPartial (filt . cont)
131 filt (IPartial cont) = IPartial (filt . cont)
136 filt v@(IDone _ _) = v
132 filt v@(IDone _ _) = v
138− filt $ unParser p1 (S sb lb [] (failDepth + 1)) (cutContinuation k)
134+ filt $ unParser p1 (S sb lb [] eof (failDepth + 1)) (cutContinuation k)
140instance Functor (Parser r) where
136instance Functor (Parser r) where
141 fmap f m = Parser $ \s cont -> unParser m s (cont . f)
137 fmap f m = Parser $ \s cont -> unParser m s (cont . f)
@@ -152,34 +148,39 @@ p <?> msg =
154initState :: L.ByteString -> S
150initState :: L.ByteString -> S
155−initState (L.Chunk sb lb) = S sb lb [] 0
151+initState (L.Chunk sb lb) = S sb lb [] False 0
156−initState _ = S S.empty L.empty [] 0
152+initState _ = S S.empty L.empty [] False 0
158−mkState :: L.ByteString -> [L.ByteString] -> Int -> S
154+mkState :: L.ByteString -> [L.ByteString] -> Bool -> Int -> S
159−mkState bs adds failDepth =
155+mkState bs adds eof failDepth =
160 case bs of
156 case bs of
161− L.Empty -> S S.empty L.empty adds failDepth
157+ L.Empty -> S S.empty L.empty adds eof failDepth
162− L.Chunk sb lb -> S sb lb adds failDepth
158+ L.Chunk sb lb -> S sb lb adds eof failDepth
164addX :: L.ByteString -> [L.ByteString] -> [L.ByteString]
160addX :: L.ByteString -> [L.ByteString] -> [L.ByteString]
165addX s adds | L.null s = adds
161addX s adds | L.null s = adds
166 | otherwise = s : adds
162 | otherwise = s : adds
168yield :: Parser r ()
164yield :: Parser r ()
169−yield = Parser $ \(S sb lb adds failDepth) k ->
165+yield = Parser $ \(S sb lb adds eof failDepth) k ->
170− IPartial $ \s -> k () (S sb (lb `appL` s) (addX s adds) failDepth)
166+ IPartial $ \s -> k () (S sb (lb `appL` s) (addX s adds) eof failDepth)
168+continue :: (S -> IResult r) -> Parser r a
169+ -> (a -> S -> IResult r) -> S -> IResult r
170+continue onEOF p k (S _sb _lb adds eof failDepth) =
172+ then onEOF (S S.empty L.empty adds True failDepth)
173+ else IPartial $ \s -> let st = contState s adds failDepth
172takeWith :: (L.ByteString -> (L.ByteString, L.ByteString))
176takeWith :: (L.ByteString -> (L.ByteString, L.ByteString))
173 -> Parser r L.ByteString
177 -> Parser r L.ByteString
174takeWith splitf =
178takeWith splitf =
175− Parser $ \(S sb lb adds failDepth) k ->
179+ Parser $ \st@(S sb lb adds eof failDepth) k ->
176 let (left,rest) = splitf (sb +: lb)
180 let (left,rest) = splitf (sb +: lb)
177− in case rest of
181+ in if L.null rest
178− L.Empty -> IPartial $ \s ->
179− let s' = mkState s (addX s adds) failDepth
180− k' a = k (appL left a)
181− in unParser (takeWith splitf) s' k'
182+ then continue (k left) (takeWith splitf) (k . appL left) st
182− L.Chunk h t -> k left (S h t adds failDepth)
183+ else k left (mkState rest adds eof failDepth)
184takeWhile :: (Word8 -> Bool) -> Parser r L.ByteString
185takeWhile :: (Word8 -> Bool) -> Parser r L.ByteString
185takeWhile = takeWith . L.span
186takeWhile = takeWith . L.span
@@ -189,56 +190,53 @@ takeTill = takeWith . L.break
190takeCount :: Int -> Parser r L.ByteString
191takeCount :: Int -> Parser r L.ByteString
191takeCount = tc . fromIntegral where
192takeCount = tc . fromIntegral where
192− tc (!n) = Parser $ \(S sb lb adds failDepth) k ->
193+ tc n = Parser $ \st@(S sb lb adds eof failDepth) k ->
193− let (h,t) = L.splitAt n (sb +: lb)
194+ let (h,t) = L.splitAt n (sb +: lb)
194− l = L.length h
195+ l = L.length h
195− in if L.length h == n
196+ in if L.length h == n
196− then k h (mkState t adds failDepth)
197+ then k h (mkState t adds eof failDepth)
197− else IPartial $ \s ->
198+ else continue (`IFailed` "takeCount: EOF")
198− let st = mkState s (addX s adds) failDepth
199+ (tc (n - l)) (k . appL h) st
200− in unParser (tc (n - l)) st k'
202string :: L.ByteString -> Parser r L.ByteString
201string :: L.ByteString -> Parser r L.ByteString
203string s =
202string s =
204− Parser $ \st@(S sb lb adds failDepth) k ->
203+ Parser $ \st@(S sb lb adds eof failDepth) k ->
205 case L.splitAt (L.length s) (sb +: lb) of
204 case L.splitAt (L.length s) (sb +: lb) of
207− | h == s -> k s (mkState t adds failDepth)
206+ | h == s -> k s (mkState t adds eof failDepth)
208 (h,L.Empty)
207 (h,L.Empty)
209 | h `L.isPrefixOf` s ->
208 | h `L.isPrefixOf` s ->
210− IPartial $ \s' ->
209+ continue (`IFailed` "string: EOF")
211− let st' = mkState s' (addX s' adds) failDepth
213− r' = L.drop (L.length h) s
210+ (string (L.drop (L.length h) s))
214− in unParser (string r') st' k'
211+ (k . appL h)
215 _ -> IFailed st "string failed to match"
213 _ -> IFailed st "string failed to match"
215+contState :: L.ByteString -> [L.ByteString] -> Int -> S
216+contState s adds failDepth
217−emptyState = S S.empty L.empty
217+ | L.null s = S S.empty L.empty [] True failDepth
218+ | otherwise = mkState s (addX s adds) False failDepth
219satisfy :: (Word8 -> Bool) -> Parser r Word8
220satisfy :: (Word8 -> Bool) -> Parser r Word8
220satisfy p =
221satisfy p =
221− Parser $ \st@(S sb lb adds failDepth) k ->
222+ Parser $ \st@(S sb lb adds eof failDepth) k ->
222 case S.uncons sb of
223 case S.uncons sb of
223− Just (w, sb') | p w -> k w (S sb' lb adds failDepth)
224+ Just (w, sb') | p w -> k w (S sb' lb adds eof failDepth)
224 | otherwise -> IFailed st "failed to match"
225 | otherwise -> IFailed st "failed to match"
225 Nothing -> case L.uncons lb of
226 Nothing -> case L.uncons lb of
226− Just (w, lb') | p w -> k w (mkState lb' adds failDepth)
227+ Just (w, lb') | p w -> k w (mkState lb' adds eof failDepth)
227 | otherwise -> IFailed st "failed to match"
228 | otherwise -> IFailed st "failed to match"
228− Nothing -> IPartial $ \s ->
229+ Nothing -> continue (`IFailed` "satisfy: EOF")
229− let st' = emptyState adds failDepth
231− then IFailed st "barf"
232− else unParser (satisfy p) st' k
230+ (satisfy p) k st
234pushBack :: L.ByteString -> Parser r ()
232pushBack :: L.ByteString -> Parser r ()
235pushBack bs =
233pushBack bs =
236− Parser $ \(S sb lb adds failDepth) k ->
234+ Parser $ \(S sb lb adds eof failDepth) k ->
237− k () (mkState (bs `appL` (sb +: lb)) adds failDepth)
235+ k () (mkState (bs `appL` (sb +: lb)) adds eof failDepth)
239toplevelTranslate :: IResult a -> Result a
237toplevelTranslate :: IResult a -> Result a
240toplevelTranslate (IFailed _ err) = Failed err
238toplevelTranslate (IFailed _ err) = Failed err
241−toplevelTranslate (IDone (S sb lb _ _) value) = Done (sb +: lb) value
239+toplevelTranslate (IDone (S sb lb _ _ _) value) = Done (sb +: lb) value
242toplevelTranslate (IPartial k) = Partial $ toplevelTranslate . k
240toplevelTranslate (IPartial k) = Partial $ toplevelTranslate . k
244terminalContinuation :: a -> S -> IResult a
242terminalContinuation :: a -> S -> IResult a
@@ -255,5 +253,8 @@ parseWith refill p s =
255 Partial k -> k <$> refill
253 Partial k -> k <$> refill
256 ok -> pure ok
254 ok -> pure ok
256+parseTest :: (Show r) => Parser r r -> L.ByteString -> IO ()
257+parseTest p s = print (parse p s)
258#define PARSER Parser r
259#define PARSER Parser r
259#include "Word8Boilerplate.h"
260#include "Word8Boilerplate.h"