attoparsec-run 0.0.0.0 → 0.0.1.0
raw patch · 3 files changed
+53/−5 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Attoparsec.Run: newRestorableIO :: IO i -> IO (RestorableInput IO i)
Files
- attoparsec-run.cabal +1/−1
- changelog.md +11/−0
- library/Data/Attoparsec/Run.hs +41/−4
attoparsec-run.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: attoparsec-run-version: 0.0.0.0+version: 0.0.1.0 synopsis: Conveniently run Attoparsec parsers category: Parsing
changelog.md view
@@ -1,3 +1,14 @@+### 0.0.1.0 (2023-01-09)++New function:++```haskell+newRestorableIO :: IO i -> IO (RestorableInput IO i)+```++This makes it easy to turn any `IO` input source into a `RestorableInput`,+backed by an `IORef` that holds any unparsed remainder.+ ### 0.0.0.0 (2023-01-09) Initial release
library/Data/Attoparsec/Run.hs view
@@ -2,8 +2,10 @@ import Data.Attoparsec.Types +import Data.IORef (newIORef, readIORef, writeIORef) import Data.List (intercalate)-import Prelude (Either (..), Eq, Ord, Show, String, error, otherwise, null, (++))+import Prelude (Either (..), Eq, Ord, Show, String, IO,+ pure, error, otherwise, null, ($), ($!), (++)) data FinalResult i a = FinalResult i -- ^ Remaining unparsed input@@ -34,8 +36,43 @@ data BufferedInput m i = BufferedInput i -- ^ Initial input- (m i) -- ^ Should return an empty string once the end of input is reached+ (m i) -- ^ Get the next chunk of input, or an empty string if the+ -- end of input has been reached +{-| An effectful source of parser input which supports a "restore" operation+ that can be used to push unused portions of input back to the source++For an example, see 'newRestorableIO'. -} data RestorableInput m i = RestorableInput- (m i) -- ^ Return an empty string once the end of input is reached- (i -> m ()) -- ^ Return a non-empty chunk of input to the input stream+ (m i) -- ^ Get the next chunk of input, or an empty string if the+ -- end of input has been reached+ (i -> m ()) -- ^ Restore a non-empty chunk of input to the input stream++{-| Turn any 'IO' input source into a 'RestorableInput'++Internally, this is backed by an 'IORef' that holds any unparsed remainder. -}+newRestorableIO :: IO i -> IO (RestorableInput IO i)+newRestorableIO unbufferedGet = do+ buffer <- newIORef [] -- The buffer stores the unparsed inputs+ -- that have pushed back by "restore".+ pure $ RestorableInput (get buffer) (restore buffer)++ where+ -- Restoring writes an input chunk to the top of the stack.+ restore buffer x = do+ xs <- readIORef buffer+ writeIORef buffer $! (x : xs)++ get buffer = do+ bufferContent <- readIORef buffer+ case bufferContent of++ -- If the buffer is empty, then "get" just runs the action.+ [] -> unbufferedGet++ -- If there is content that has been pushed back onto the+ -- buffer, then "get" pops a chunk off of the stack instead+ -- of running the action.+ (x : xs) -> do+ writeIORef buffer $! xs+ pure x