Navigation Menu

Skip to content

Commit

Permalink
Update to new version of iteratee
Browse files Browse the repository at this point in the history
  • Loading branch information
uzytkownik committed Jan 5, 2011
1 parent bac497f commit cabedfe
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 64 deletions.
4 changes: 2 additions & 2 deletions attoparsec-iteratee.cabal
@@ -1,5 +1,5 @@
name: attoparsec-iteratee
version: 0.1.2
version: 0.2.0
synopsis: An adapter to convert attoparsec Parsers into blazing-fast Iteratees
description:
An adapter to convert attoparsec Parsers into blazing-fast Iteratees
Expand All @@ -23,7 +23,7 @@ Library
attoparsec >= 0.8 && < 0.9,
base >= 4 && < 5,
bytestring,
iteratee >= 0.3.1 && <0.4,
iteratee >= 0.7 && <0.8,
monads-fd,
transformers

Expand Down
86 changes: 24 additions & 62 deletions src/Data/Attoparsec/Iteratee.hs
@@ -1,76 +1,38 @@
{-# LANGUAGE DeriveDataTypeable #-}
module Data.Attoparsec.Iteratee
( parserToIteratee ) where
( ParseError(..), parserToIteratee ) where


------------------------------------------------------------------------------
import Control.Exception
import qualified Data.Attoparsec as Atto
import Data.Attoparsec hiding (many, Result(..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as B
import Data.Iteratee
import Data.Iteratee.WrappedByteString
import Data.Word
import Data.Typeable
------------------------------------------------------------------------------

type Stream = StreamG WrappedByteString Word8
type IterV m = IterGV WrappedByteString Word8 m
data ParseError
= ParseError {errorContexts :: [String], errorMessage :: String}
deriving (Show, Typeable)

instance Exception ParseError

parserToIteratee :: (Monad m) =>
Parser a
-> IterateeG WrappedByteString Word8 m a
parserToIteratee p = IterateeG $ f (\s -> parse p s)
where
f :: (Monad m) =>
(ByteString -> Atto.Result a)
-> Stream
-> m (IterV m a)
f k (EOF Nothing) = finalChunk $ feed (k S.empty) S.empty
f _ (EOF (Just e)) = reportError e
f k (Chunk s) = let s' = S.concat $ L.toChunks $ fromWrap s
in if S.null s'
then return $ Cont (IterateeG $ f k) Nothing
else chunk s' k


finalChunk :: (Monad m) => Atto.Result a -> m (IterV m a)
finalChunk (Atto.Fail _ _ m) =
return $ Cont (error $ show m)
(Just $ Err m)

finalChunk (Atto.Done rest r)
| S.null rest =
return $ Done r (EOF Nothing)
| otherwise =
return $ Done r (Chunk $ toWrap $ L.fromChunks [rest])

finalChunk (Atto.Partial _) =
return $ Cont (error "parser did not produce a value")
(Just $ Err "parser did not produce a value")

reportError e = return $ Cont (error $ show e) (Just e)

chunk :: (Monad m) =>
ByteString
-> (ByteString -> Atto.Result a)
-> m (IterV m a)
chunk s k = do
let r = k s
case r of
(Atto.Fail _ _ m) -> return $
Cont (throwErr (Err m)) (Just $ Err m)
(Atto.Done rest x) -> return $ Done x (Chunk $ toWrap $ L.fromChunks [rest])
(Atto.Partial z) -> return $
Cont (IterateeG $ f z) Nothing


-- | lazy bytestring -> wrapped bytestring
toWrap :: L.ByteString -> WrappedByteString Word8
toWrap = WrapBS . S.concat . L.toChunks
{-# INLINE toWrap #-}

-- | wrapped bytestring -> lazy bytestring
fromWrap :: WrappedByteString Word8 -> L.ByteString
fromWrap = L.fromChunks . (:[]) . unWrap
{-# INLINE fromWrap #-}
-> Iteratee ByteString m a
parserToIteratee p = icont (f (parse p)) Nothing
where f k (EOF Nothing) = case feed (k B.empty) B.empty of
Atto.Fail _ err dsc -> throwErr (toException $ ParseError err dsc)
Atto.Partial _ -> throwErr (toException EofException)
Atto.Done rest v
| B.null rest -> idone v (EOF Nothing)
| otherwise -> idone v (Chunk rest)
f _ (EOF (Just e)) = throwErr e
f k (Chunk s)
| B.null s = icont (f k) Nothing
| otherwise = case k s of
Atto.Fail _ err dsc -> throwErr (toException $ ParseError err dsc)
Atto.Partial k' -> icont (f k') Nothing
Atto.Done rest v -> idone v (Chunk rest)

0 comments on commit cabedfe

Please sign in to comment.