packages feed

hexpat-streamparser 0.0.1 → 0.0.2

raw patch · 2 files changed

+71/−15 lines, 2 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Text.XML.Expat.StreamParser: instance GHC.Base.Functor m => GHC.Base.Functor (Text.XML.Expat.StreamParser.EventParser l e m)
+ Text.XML.Expat.StreamParser: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Text.XML.Expat.StreamParser.CPSExceptT e m)
+ Text.XML.Expat.StreamParser: instance Control.Monad.Trans.Class.MonadTrans (Text.XML.Expat.StreamParser.CPSExceptT e)
+ Text.XML.Expat.StreamParser: instance GHC.Base.Functor (Text.XML.Expat.StreamParser.CPSExceptT e m)
+ Text.XML.Expat.StreamParser: instance GHC.Base.Functor (Text.XML.Expat.StreamParser.EventParser l e m)
+ Text.XML.Expat.StreamParser: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError e (Text.XML.Expat.StreamParser.CPSExceptT e m)
+ Text.XML.Expat.StreamParser: instance GHC.Base.Monad m => GHC.Base.Applicative (Text.XML.Expat.StreamParser.CPSExceptT e m)
+ Text.XML.Expat.StreamParser: instance GHC.Base.Monad m => GHC.Base.Monad (Text.XML.Expat.StreamParser.CPSExceptT e m)
+ Text.XML.Expat.StreamParser: noAttrs :: AttrParser e ()
+ Text.XML.Expat.StreamParser: type EventListParser e a = EventParser [] e Identity a
- Text.XML.Expat.StreamParser: parseXMLByteString :: EventParser [] e Identity a -> ParseOptions Text Text -> ByteString -> Either (EventParseError e, Maybe XMLParseLocation) a
+ Text.XML.Expat.StreamParser: parseXMLByteString :: EventListParser e a -> ParseOptions Text Text -> ByteString -> Either (EventParseError e, Maybe XMLParseLocation) a
- Text.XML.Expat.StreamParser: parseXMLFile :: EventParser [] e Identity a -> ParseOptions Text Text -> FilePath -> IOMode -> IO (Either (EventParseError e, Maybe XMLParseLocation) a)
+ Text.XML.Expat.StreamParser: parseXMLFile :: EventListParser e a -> ParseOptions Text Text -> FilePath -> IOMode -> IO (Either (EventParseError e, Maybe XMLParseLocation) a)

Files

hexpat-streamparser.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12 name: hexpat-streamparser description: streaming xml parser combinators using hexpat-version: 0.0.1+version: 0.0.2 maintainer: kristof@resonata.be copyright: Kristof Bastiaensen 2020 license: BSD3
src/Text/XML/Expat/StreamParser.hs view
@@ -4,6 +4,8 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE RankNTypes #-}  {-| Module      : Text.XML.Expat.StreamParser@@ -28,7 +30,8 @@ module Text.XML.Expat.StreamParser   (     -- * Event parser datatype-    EventParser+    EventListParser+  , EventParser   , EventLoc   , EventParseError (..)   , runEventParser@@ -43,6 +46,7 @@   , peekAttr   , findAttr   , skipAttrs+  , noAttrs   , -- * Event parsers     someTag   , skipTag@@ -85,7 +89,7 @@  import Control.Applicative hiding (many) import Control.Monad.Combinators as C-import Control.Monad.Except hiding (fail, lift)+import Control.Monad.Error.Class import Control.Monad.Fail import Control.Monad.State hiding (fail, lift) import Control.Monad.Trans (lift)@@ -100,6 +104,46 @@ import Data.Text (Text) import Text.XML.Expat.SAX as Expat +newtype CPSExceptT e m a =+  CPSExceptT { getCPSExceptT :: forall r. ((e -> m r) -> (a -> m r) -> m r) }++runCPSExceptT :: Applicative m => CPSExceptT e m a -> m (Either e a)+runCPSExceptT (CPSExceptT f) = f (pure . Left)  (pure . Right)+{-# INLINE runCPSExceptT #-}++instance Functor (CPSExceptT e m) where+  fmap f (CPSExceptT g) = CPSExceptT $ \failC successC ->+    g failC (successC . f)+  {-# INLINE fmap #-}++instance Monad m => Applicative (CPSExceptT e m) where+  pure x = CPSExceptT $ \_failC successC -> successC x+  {-# INLINE pure #-}+  (<*>) = ap+  {-# INLINE (<*>) #-}++instance Monad m => Monad (CPSExceptT e m) where+  CPSExceptT f >>= g = CPSExceptT $ \failC successC ->+    f failC (\a -> getCPSExceptT (g a) failC successC)+  {-# INLINE (>>=) #-}++instance Monad m => MonadError e (CPSExceptT e m) where+  throwError e = CPSExceptT $ \failC _successC -> failC e+  {-# INLINE throwError #-}+  catchError (CPSExceptT f) handler =+    CPSExceptT $ \failC successC ->+    f (\e -> getCPSExceptT (handler e) failC successC)+    successC+  {-# INLINE catchError #-}++instance MonadTrans (CPSExceptT e) where+  lift m = CPSExceptT $ \_failC successC -> m >>= successC+  {-# INLINE lift #-}++instance MonadState s m => MonadState s (CPSExceptT e m) where+  state f = lift $ state f+  {-# INLINE state #-}+ type EventLoc = (SAXEvent Text Text, XMLParseLocation)  type Attrs = [(Text, Text)]@@ -142,13 +186,19 @@ instance Monoid (EventParseError e) where   mempty = Empty +-- | A parser that parses a lazy list of SAX events into a value of+-- type `a`, or an error of type `@EventParseError@ e`, where `e` is a+-- custom error type.+type EventListParser e a = EventParser [] e Identity a+      -- | A parser that parses a stream of SAX events of type @l -- `EventLoc`@ into to a value of type @a@ using `m` as the underlying -- monad.  l should be an instance of `List`, and m should be equal to -- the type instance (@`ItemM` l@).  Custom error messages are -- possible using the type e. newtype EventParser l e m a = EventParser-  { getEventParser :: ExceptT (EventParseError e) (StateT (ParserState l) m) a+  { getEventParser :: CPSExceptT (EventParseError e) (StateT (ParserState l) m)+                      a   } deriving (Functor, Applicative, Monad, MonadError (EventParseError e))  -- | Throw an error with a custom type.  If the custom error type@@ -233,13 +283,13 @@   firstItem <- List.runList events   let initState = ParserState False (Ordered firstItem)   do (a, ParserState _ (Ordered item)) <--       flip runStateT initState $ runExceptT parser+       flip runStateT initState $ runCPSExceptT parser      case a of        Right res -> pure $ Right res        Left err -> pure $ Left $ case item of          Nil -> (err, Nothing)          (Cons (_, loc) _) -> (err, Just loc)-     + -- | Parse a lazy bytestring with the given parser.  Evaluating the -- result to WHNF will consume the bytestring (as much as needed). -- However this function does not close resources, for example a file@@ -247,21 +297,21 @@ -- a resource, /after/ evaluating to WHNF, or use the streaming -- version of this library (hexpat-streamparser-conduit).  For reading -- from a file use the `parseXMLFile` function.-parseXMLByteString :: EventParser [] e Identity a-                -> Expat.ParseOptions Text Text-                -> LazyBS.ByteString-                -> Either (EventParseError e, Maybe XMLParseLocation) a+parseXMLByteString :: EventListParser e a+                   -> Expat.ParseOptions Text Text+                   -> LazyBS.ByteString+                   -> Either (EventParseError e, Maybe XMLParseLocation) a parseXMLByteString parser parseOptions bs =   runIdentity $ runEventParser parser $ Expat.parseLocations parseOptions bs  -- | Lazily parse an xml file into a value.  This function ensures the --  input is consumed and the file handle closed, before returning the --  value.-parseXMLFile :: EventParser [] e Identity a-          -> Expat.ParseOptions Text Text-          -> FilePath-          -> IOMode-          -> IO (Either (EventParseError e, Maybe XMLParseLocation) a)+parseXMLFile :: EventListParser e a+             -> Expat.ParseOptions Text Text+             -> FilePath+             -> IOMode+             -> IO (Either (EventParseError e, Maybe XMLParseLocation) a) parseXMLFile parser parseOptions fp mode =   withFile fp mode $ \h -> do   bs <- LazyBS.hGetContents h@@ -365,6 +415,10 @@ skipAttrs :: AttrParser e () skipAttrs = AttrParser $ put [] +-- | expect no attributes.  This is the same as `pure ()`+noAttrs :: AttrParser e ()+noAttrs = pure ()+ -- | Annotate the parser with a name for better parse errors (<?>) :: Monad m => EventParser l e m a -> Text -> EventParser l e m a parser <?> msg = parser <|> EventParser (throwError $ Expected [msg])@@ -395,6 +449,7 @@               throwError $ UnknownAttributes $ map fst attributes       | otherwise -> throwError ExpectedTag     Ordered _ -> throwError ExpectedTag+{-# INLINABLE someTag #-}      --  UnOrdered [] -> throwError "Unexpected end of input." --  UnOrdered lst -> _ @@ -409,6 +464,7 @@ skipTag :: (Monad (ItemM l), List l) => EventParser l e (ItemM l) () skipTag = (someTag (const True) skipAttrs $ const skipTags)           <?> "Any Tag"+{-# INLINE skipTag #-}            -- | Skip remaining tags and text, if any. skipTags :: (Monad (ItemM l), List l) => EventParser l e(ItemM l) ()