attoparsec-run (empty) → 0.0.0.0
raw patch · 7 files changed
+227/−0 lines, 7 filesdep +attoparsecdep +basedep +bytestring
Dependencies added: attoparsec, base, bytestring, text
Files
- attoparsec-run.cabal +45/−0
- changelog.md +3/−0
- library/Data/Attoparsec/ByteString/Run.hs +26/−0
- library/Data/Attoparsec/Run.hs +41/−0
- library/Data/Attoparsec/Text/Run.hs +26/−0
- license.txt +13/−0
- readme.md +73/−0
+ attoparsec-run.cabal view
@@ -0,0 +1,45 @@+cabal-version: 3.0++name: attoparsec-run+version: 0.0.0.0+synopsis: Conveniently run Attoparsec parsers+category: Parsing++description: This package fixes a number of problems with the API that+ Attoparsec provides for running parsers. The difficulties stem from+ the that that Attoparsec's @IResult@ type encompasses three situations:+ When parsing has succeeded, when parsing has failed, and when parsing+ is awaiting further input. This is insufficient to describe situations+ in which we know we are dealing with a subset of these three cases.+ We address this by introducing two smaller types: @FinalResult@ and+ @ParseError@.++license: Apache-2.0+license-file: license.txt++author: Chris Martin+maintainer: Chris Martin, Julie Moronuki++homepage: https://github.com/typeclasses/attoparsec-run+bug-Reports: https://github.com/typeclasses/attoparsec-run/issues++extra-source-files: *.md++source-repository head+ type: git+ location: git://github.com/typeclasses/attoparsec-run.git++library+ default-language: Haskell2010+ ghc-options: -Wall+ hs-source-dirs: library+ build-depends:+ , attoparsec ^>= 0.14.4+ , base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17+ , bytestring ^>= 0.10.12 || ^>= 0.11+ , text ^>= 1.2.4 || ^>= 2.0+ exposed-modules:+ Data.Attoparsec.Run++ Data.Attoparsec.ByteString.Run+ Data.Attoparsec.Text.Run
+ changelog.md view
@@ -0,0 +1,3 @@+### 0.0.0.0 (2023-01-09)++Initial release
+ library/Data/Attoparsec/ByteString/Run.hs view
@@ -0,0 +1,26 @@+module Data.Attoparsec.ByteString.Run+ (+ parseStream, parseAndRestore,+ module Data.Attoparsec.Run,+ )+ where++import Data.Attoparsec.Run++import Control.Monad (unless)+import Data.Attoparsec.ByteString (parseWith, Parser)+import Data.ByteString (ByteString)+import Data.ByteString (null)+import Prelude (($), (<$>), pure, mempty, Monad, Either)++parseStream :: Monad m =>+ BufferedInput m ByteString -> Parser a -> m (FinalResult ByteString a)+parseStream (BufferedInput initial get) p =+ finalizeResult <$> parseWith get p initial++parseAndRestore :: Monad m =>+ RestorableInput m ByteString -> Parser a -> m (Either ParseError a)+parseAndRestore (RestorableInput get restore) p = do+ FinalResult remainder value <- parseStream (BufferedInput mempty get) p+ unless (null remainder) $ restore remainder+ pure value
+ library/Data/Attoparsec/Run.hs view
@@ -0,0 +1,41 @@+module Data.Attoparsec.Run where++import Data.Attoparsec.Types++import Data.List (intercalate)+import Prelude (Either (..), Eq, Ord, Show, String, error, otherwise, null, (++))++data FinalResult i a = FinalResult+ i -- ^ Remaining unparsed input+ (Either ParseError a) -- ^ Either an error or a successfully parsed value+ deriving (Eq, Ord, Show)++finalizeResult ::+ IResult i a -- ^ Must be either 'Done' or 'Fail', not 'Partial'+ -> FinalResult i a+finalizeResult r = case r of+ Done remainder v ->+ FinalResult remainder (Right v)+ Fail remainder context message ->+ FinalResult remainder (Left (ParseError context message))+ Partial{} ->+ error "parseWith should not return Partial"++data ParseError = ParseError+ [String] -- ^ A list of contexts in which the error occurred+ String -- ^ The message describing the error, if any+ deriving (Eq, Ord, Show)++-- | Format a parse error in a matter suitable for displaying in log output+showParseError :: ParseError -> String+showParseError (ParseError context message)+ | null context = message+ | otherwise = intercalate " > " context ++ ": " ++ message++data BufferedInput m i = BufferedInput+ i -- ^ Initial input+ (m i) -- ^ Should return an empty string once the end of input is reached++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
+ library/Data/Attoparsec/Text/Run.hs view
@@ -0,0 +1,26 @@+module Data.Attoparsec.Text.Run+ (+ parseStream, parseAndRestore,+ module Data.Attoparsec.Run,+ )+ where++import Data.Attoparsec.Run++import Control.Monad (unless)+import Data.Attoparsec.Text (parseWith, Parser)+import Data.Text (Text)+import Data.Text (null)+import Prelude (($), (<$>), pure, mempty, Monad, Either)++parseStream :: Monad m =>+ BufferedInput m Text -> Parser a -> m (FinalResult Text a)+parseStream (BufferedInput initial get) p =+ finalizeResult <$> parseWith get p initial++parseAndRestore :: Monad m =>+ RestorableInput m Text -> Parser a -> m (Either ParseError a)+parseAndRestore (RestorableInput get restore) p = do+ FinalResult remainder value <- parseStream (BufferedInput mempty get) p+ unless (null remainder) $ restore remainder+ pure value
+ license.txt view
@@ -0,0 +1,13 @@+Copyright 2023 Mission Valley Software LLC++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.
+ readme.md view
@@ -0,0 +1,73 @@+This package fixes a number of problems with the API that Attoparsec provides+for running parsers.++The difficulties stem from the that that Attoparsec's `IResult` type encompasses+three situations: When parsing has succeeded, when parsing has failed, and when+parsing is awaiting further input. This is insufficient to describe situations+in which we know we are dealing with a subset of these three cases. We address+this by introducing two smaller types: `FinalResult` and `ParseError`.++### FinalResult++`FinalResult` represents a result that we know not to be partial; for example,+the sort of result that we get when running a parser using `parseWith`.++```haskell+data FinalResult i a = FinalResult i (Either ParseError a)+```++### ParseError++`ParseError` represents only the case in which parsing has failed.++```haskell+data ParseError = ParseError [String] String+```++Our `showParseError` function gives an error string in the same format as+Attoparsec's `eitherResult` function.++```haskell+showParseError :: ParseError -> String+```++### BufferedInput++The `BufferedInput` type corresponds to two arguments of Attoparsec's+`parseWith`, the initial input and the action to obtain more input.++```haskell+data BufferedInput m i = BufferedInput i (m i)+```++In each of the modules `Data.Attoparsec.ByteString.Run` and+`Data.Attoparsec.Text.Run`, we provide a function called `parseStream`. This+closely corresponds to Attoparsec's `parseWith` function, but ours returns the+more specific `FinalResult` type, rather than `Result`, reflecting the fact that+a result returned here is never partial.++```haskell+parseStream :: Monad m =>+ BufferedInput m ByteString -> Parser a -> m (FinalResult ByteString a)+```++### RestorableInput++`RestorableInput` offers a new way to do streaming parsing that may be more+convenient than `parseStream` and `BufferedInput`. This type represents an input+stream with the ability to push unused input back to it.++```haskell+data RestorableInput m i = RestorableInput (m i) (i -> m ())+```++We use this type with the `parseAndRestore` function:++```haskell+parseAndRestore :: Monad m =>+ RestorableInput m ByteString -> Parser a -> m (Either ParseError a)+```++This shifts the burden of storing the unused remainder to feed back into the+next parsing step from the user of `parseStream` to the definer of the+`RestorableInput`.