construct 0.2.0.1 → 0.3
raw patch · 5 files changed
+22/−203 lines, 5 filesdep +input-parsersdep ~incremental-parserPVP ok
version bump matches the API change (PVP)
Dependencies added: input-parsers
Dependency ranges changed: incremental-parser
API changes (from Hackage documentation)
- Construct.Classes: anyToken :: InputParsing m => m (ParserInput m)
- Construct.Classes: class (CharParsing m, InputParsing m) => InputCharParsing m
- Construct.Classes: class LookAheadParsing m => InputParsing m where {
- Construct.Classes: concatMany :: (InputParsing m, Monoid a, Alternative m) => m a -> m a
- Construct.Classes: getInput :: InputParsing m => m (ParserInput m)
- Construct.Classes: instance (Data.Monoid.Factorial.FactorialMonoid s, Data.Semigroup.Cancellative.LeftReductive s, Text.Parser.LookAhead.LookAheadParsing (Text.ParserCombinators.Incremental.Parser t s)) => Construct.Classes.InputParsing (Text.ParserCombinators.Incremental.Parser t s)
- Construct.Classes: instance (Data.Monoid.Textual.TextualMonoid s, Data.Semigroup.Cancellative.LeftReductive s, Text.Parser.LookAhead.LookAheadParsing (Text.ParserCombinators.Incremental.Parser t s)) => Construct.Classes.InputCharParsing (Text.ParserCombinators.Incremental.Parser t s)
- Construct.Classes: instance Construct.Classes.InputCharParsing Data.Attoparsec.ByteString.Internal.Parser
- Construct.Classes: instance Construct.Classes.InputCharParsing Data.Attoparsec.Text.Internal.Parser
- Construct.Classes: instance Construct.Classes.InputCharParsing Text.ParserCombinators.ReadP.ReadP
- Construct.Classes: instance Construct.Classes.InputParsing Data.Attoparsec.ByteString.Internal.Parser
- Construct.Classes: instance Construct.Classes.InputParsing Data.Attoparsec.Text.Internal.Parser
- Construct.Classes: instance Construct.Classes.InputParsing Text.ParserCombinators.ReadP.ReadP
- Construct.Classes: notSatisfy :: InputParsing m => (ParserInput m -> Bool) -> m ()
- Construct.Classes: notSatisfyChar :: InputCharParsing m => (Char -> Bool) -> m ()
- Construct.Classes: satisfy :: InputParsing m => (ParserInput m -> Bool) -> m (ParserInput m)
- Construct.Classes: satisfyCharInput :: (InputCharParsing m, IsString (ParserInput m)) => (Char -> Bool) -> m (ParserInput m)
- Construct.Classes: scan :: (InputParsing m, Monad m, FactorialMonoid (ParserInput m)) => state -> (state -> ParserInput m -> Maybe state) -> m (ParserInput m)
- Construct.Classes: scanChars :: (InputCharParsing m, Monad m, TextualMonoid (ParserInput m)) => state -> (state -> Char -> Maybe state) -> m (ParserInput m)
- Construct.Classes: string :: (InputParsing m, Monad m, LeftReductive (ParserInput m), FactorialMonoid (ParserInput m), Show (ParserInput m)) => ParserInput m -> m (ParserInput m)
- Construct.Classes: take :: InputParsing m => Int -> m (ParserInput m)
- Construct.Classes: takeCharsWhile :: (InputCharParsing m, Monad m, TextualMonoid (ParserInput m)) => (Char -> Bool) -> m (ParserInput m)
- Construct.Classes: takeCharsWhile1 :: (InputCharParsing m, Monad m, TextualMonoid (ParserInput m)) => (Char -> Bool) -> m (ParserInput m)
- Construct.Classes: takeWhile :: (InputParsing m, Monad m, FactorialMonoid (ParserInput m)) => (ParserInput m -> Bool) -> m (ParserInput m)
- Construct.Classes: takeWhile1 :: (InputParsing m, Monad m, FactorialMonoid (ParserInput m)) => (ParserInput m -> Bool) -> m (ParserInput m)
- Construct.Classes: type family ParserInput m;
- Construct.Classes: }
Files
- CHANGELOG.md +4/−0
- construct.cabal +5/−4
- src/Construct.hs +8/−6
- src/Construct/Bits.hs +1/−0
- src/Construct/Classes.hs +4/−193
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for construct +## 0.3 -- 2020-07-18++* Import the Input[Char]Parser classes from the `input-parsers` package+ ## 0.2.0.1 -- 2020-03-08 * Incremented the upper bound for the `rank2classes` dependency
construct.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: construct-version: 0.2.0.1+version: 0.3 synopsis: Haskell version of the Construct library for easy specification of file formats description: A Haskell version of the <https://construct.readthedocs.io/en/latest/intro.html Construct> library for Python. A@@ -32,8 +32,9 @@ bytestring >= 0.10 && < 0.11, text >= 0.10 && < 1.3, monoid-subclasses >= 1.0 && < 1.1,- incremental-parser >= 0.4 && < 0.5,+ incremental-parser >= 0.5 && < 0.6, parsers >= 0.11 && < 0.13,+ input-parsers < 0.2, attoparsec >= 0.12 && < 0.14, cereal >= 0.5 && < 0.6, rank2classes >= 1 && < 1.5@@ -48,7 +49,7 @@ other-modules: README ghc-options: -threaded -pgmL markdown-unlit build-depends: base, construct,- bytestring >= 0.10 && < 0.11, incremental-parser >= 0.4 && < 0.5, rank2classes >= 1.0.2 && < 1.5,+ bytestring >= 0.10 && < 0.11, incremental-parser >= 0.5 && < 0.6, rank2classes >= 1.0.2 && < 1.5, doctest >= 0.8 build-tool-depends: markdown-unlit:markdown-unlit >= 0.5 && < 0.6 x-doctest-options: -XTypeApplications@@ -58,7 +59,7 @@ hs-source-dirs: test build-depends: base >=4.9 && < 5, construct, bytestring < 0.11, text < 1.3, cereal, rank2classes >= 1.0.2 && < 1.5,- monoid-subclasses >= 1.0 && < 1.1, incremental-parser < 0.5, attoparsec >= 0.12 && < 0.14,+ monoid-subclasses >= 1.0 && < 1.1, incremental-parser < 0.6, attoparsec >= 0.12 && < 0.14, directory < 2, filepath < 1.5, tasty >= 0.7, tasty-hunit main-is: Test.hs
src/Construct.hs view
@@ -50,12 +50,14 @@ import Text.ParserCombinators.Incremental.Symmetric (Symmetric) import Data.Serialize (Serialize, Result(Done, Fail, Partial), Get, Putter, runGetPartial, runPut) import qualified Data.Serialize as Serialize+import Text.Parser.Input (InputParsing (ParserInput), InputCharParsing)+import qualified Text.Parser.Input as Input import qualified Rank2 -import qualified Construct.Classes as Input-import Construct.Classes (AlternativeFail(failure), InputParsing (ParserInput), InputCharParsing, InputMappableParsing,- FixTraversable, Error, errorString, expectedName)+import Construct.Classes (AlternativeFail(failure), InputMappableParsing(mapParserInput, mapMaybeParserInput),+ FixTraversable(fixSequence), Error,+ errorString, expectedName) import Construct.Internal import Prelude hiding (pred, take, takeWhile)@@ -234,7 +236,7 @@ s ~ ParserInput (m s), t ~ ParserInput (m t), InputMappableParsing m, Functor n) => (s -> t) -> (t -> s) -> Format (m s) n s a -> Format (m t) n t a mapSerialized f f' format = Format{- parse = Input.mapParserInput f f' (parse format),+ parse = mapParserInput f f' (parse format), serialize = (f <$>) . serialize format} -- | Converts a format for serialized streams of type @s@ so it works for streams of type @t@ instead. The argument@@ -243,7 +245,7 @@ s ~ ParserInput (m s), t ~ ParserInput (m t), InputMappableParsing m, Functor n) => (s -> Maybe t) -> (t -> Maybe s) -> Format (m s) n s a -> Format (m t) n t a mapMaybeSerialized f f' format = Format{- parse = Input.mapMaybeParserInput f f' (parse format),+ parse = mapMaybeParserInput f f' (parse format), serialize = (fromMaybe (error "Partial serialization") . f <$>) . serialize format} -- | Converts a format for in-memory values of type @a@ so it works for values of type @b@ instead.@@ -328,7 +330,7 @@ (forall a. o (n a) -> n a) -> g (Format m n s) -> Format m n s (g o) -- | Converts a record of field formats into a single format of the whole record, a generalized form of 'record'. recordWith collapse formats = Format{- parse = Input.fixSequence (parse Rank2.<$> formats),+ parse = fixSequence (parse Rank2.<$> formats), serialize = getAp . Rank2.foldMap Functor.getConst . Rank2.liftA2 serializeField formats } where serializeField :: forall a. Format m n s a -> o a -> Functor.Const (Ap n s) a
src/Construct/Bits.hs view
@@ -16,6 +16,7 @@ import qualified Data.ByteString as ByteString import qualified Data.List as List import Data.Word (Word8)+import Text.Parser.Input (InputParsing (ParserInput, anyToken)) import Construct import Construct.Classes
src/Construct/Classes.hs view
@@ -9,40 +9,13 @@ import qualified Text.ParserCombinators.Incremental as Incremental import Control.Applicative (Alternative ((<|>), empty))-import Control.Monad (void)-import Data.String (IsString (fromString))-import Text.ParserCombinators.ReadP (ReadP)-import qualified Text.ParserCombinators.ReadP as ReadP--import Text.Parser.Char (CharParsing)-import Text.Parser.Combinators (count, eof, notFollowedBy, try, unexpected)-import Text.Parser.LookAhead (LookAheadParsing, lookAhead)-import qualified Text.Parser.Char as Char--import qualified Data.Monoid.Factorial as Factorial-import qualified Data.Monoid.Null as Null-import qualified Data.Monoid.Textual as Textual-import qualified Data.Semigroup.Cancellative as Cancellative-import Data.Monoid.Factorial (FactorialMonoid)-import Data.Monoid.Textual (TextualMonoid)-import Data.Semigroup.Cancellative (LeftReductive)--import Data.ByteString (ByteString)-import Data.Text (Text)-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Char8 as ByteString.Char8-import qualified Data.Text as Text- import qualified Data.Attoparsec.ByteString as Attoparsec-import qualified Data.Attoparsec.ByteString.Char8 as Attoparsec.Char8-import qualified Data.Attoparsec.Text as Attoparsec.Text--import Prelude hiding (take, takeWhile)+import Text.Parser.Input (InputParsing (ParserInput)) -- | Subclass of 'Alternative' that carries an error message in case of failure class Alternative m => AlternativeFail m where -- | Equivalent to 'empty' except it takes an error message it may carry or drop on the floor. The grammatical form- -- of the argument be a noun representing the unexpected value.+ -- of the argument should be a noun representing the unexpected value. failure :: String -> m a -- | Sets or modifies the expected value. expectedName :: String -> m a -> m a@@ -50,115 +23,10 @@ failure = const empty expectedName = const id --- | Methods for parsing factorial monoid inputs-class LookAheadParsing m => InputParsing m where- type ParserInput m- -- | Always sucessful parser that returns the remaining input without consuming it.- getInput :: m (ParserInput m)-- -- | A parser that accepts any single atomic prefix of the input stream.- -- > anyToken == satisfy (const True)- -- > anyToken == take 1- anyToken :: m (ParserInput m)- -- | A parser that accepts exactly the given number of input atoms.- take :: Int -> m (ParserInput m)- -- | A parser that accepts an input atom only if it satisfies the given predicate.- satisfy :: (ParserInput m -> Bool) -> m (ParserInput m)- -- | A parser that succeeds exactly when satisfy doesn't, equivalent to- -- 'Text.Parser.Combinators.notFollowedBy' @. satisfy@- notSatisfy :: (ParserInput m -> Bool) -> m ()-- -- | A stateful scanner. The predicate modifies a state argument, and each transformed state is passed to successive- -- invocations of the predicate on each token of the input until one returns 'Nothing' or the input ends.- --- -- This parser does not fail. It will return an empty string if the predicate returns 'Nothing' on the first- -- character.- --- -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers- -- loop until a failure occurs. Careless use will thus result in an infinite loop.- scan :: state -> (state -> ParserInput m -> Maybe state) -> m (ParserInput m)- -- | A parser that consumes and returns the given prefix of the input.- string :: ParserInput m -> m (ParserInput m)-- -- | A parser accepting the longest sequence of input atoms that match the given predicate; an optimized version of- -- 'concatMany . satisfy'.- --- -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers- -- loop until a failure occurs. Careless use will thus result in an infinite loop.- takeWhile :: (ParserInput m -> Bool) -> m (ParserInput m)- -- | A parser accepting the longest non-empty sequence of input atoms that match the given predicate; an optimized- -- version of 'concatSome . satisfy'.- takeWhile1 :: (ParserInput m -> Bool) -> m (ParserInput m)- -- | Zero or more argument occurrences like 'many', with concatenated monoidal results.- concatMany :: Monoid a => m a -> m a-- anyToken = take 1- notSatisfy predicate = try (void $ satisfy $ not . predicate) <|> eof- default concatMany :: (Monoid a, Alternative m) => m a -> m a- concatMany p = go- where go = mappend <$> try p <*> go <|> pure mempty-- default string :: (Monad m, LeftReductive (ParserInput m), FactorialMonoid (ParserInput m), Show (ParserInput m))- => ParserInput m -> m (ParserInput m)- string s = do i <- getInput- if s `Cancellative.isPrefixOf` i- then take (Factorial.length s)- else unexpected ("string " <> show s)- default scan :: (Monad m, FactorialMonoid (ParserInput m)) =>- state -> (state -> ParserInput m -> Maybe state) -> m (ParserInput m)- scan state f = do i <- getInput- let (prefix, _suffix, _state) = Factorial.spanMaybe' state f i- take (Factorial.length prefix)- default takeWhile :: (Monad m, FactorialMonoid (ParserInput m)) => (ParserInput m -> Bool) -> m (ParserInput m)- takeWhile predicate = do i <- getInput- take (Factorial.length $ Factorial.takeWhile predicate i)- default takeWhile1 :: (Monad m, FactorialMonoid (ParserInput m)) => (ParserInput m -> Bool) -> m (ParserInput m)- takeWhile1 predicate = do x <- takeWhile predicate- if Null.null x then unexpected "takeWhile1" else pure x- {-# INLINE concatMany #-}---- | Methods for parsing textual monoid inputs-class (CharParsing m, InputParsing m) => InputCharParsing m where- -- | Specialization of 'satisfy' on textual inputs, accepting an input character only if it satisfies the given- -- predicate, and returning the input atom that represents the character. Equivalent to @fmap singleton- -- . Char.satisfy@- satisfyCharInput :: (Char -> Bool) -> m (ParserInput m)- -- | A parser that succeeds exactly when satisfy doesn't, equivalent to @notFollowedBy . Char.satisfy@- notSatisfyChar :: (Char -> Bool) -> m ()-- -- | Stateful scanner like `scan`, but specialized for 'TextualMonoid' inputs.- scanChars :: state -> (state -> Char -> Maybe state) -> m (ParserInput m)-- -- | Specialization of 'takeWhile' on 'TextualMonoid' inputs, accepting the longest sequence of input characters that- -- match the given predicate; an optimized version of @fmap fromString . many . Char.satisfy@.- --- -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers- -- loop until a failure occurs. Careless use will thus result in an infinite loop.- takeCharsWhile :: (Char -> Bool) -> m (ParserInput m)- -- | Specialization of 'takeWhile1' on 'TextualMonoid' inputs, accepting the longest sequence of input characters- -- that match the given predicate; an optimized version of @fmap fromString . some . Char.satisfy@.- takeCharsWhile1 :: (Char -> Bool) -> m (ParserInput m)-- default satisfyCharInput :: IsString (ParserInput m) => (Char -> Bool) -> m (ParserInput m)- satisfyCharInput = fmap (fromString . (:[])) . Char.satisfy- notSatisfyChar = notFollowedBy . Char.satisfy- default scanChars :: (Monad m, TextualMonoid (ParserInput m)) =>- state -> (state -> Char -> Maybe state) -> m (ParserInput m)- scanChars state f = do i <- getInput- let (prefix, _suffix, _state) = Textual.spanMaybe' state (const $ const Nothing) f i- take (Factorial.length prefix)-- default takeCharsWhile :: (Monad m, TextualMonoid (ParserInput m)) => (Char -> Bool) -> m (ParserInput m)- takeCharsWhile predicate = do i <- getInput- take (Factorial.length $ Textual.takeWhile_ False predicate i)- default takeCharsWhile1 :: (Monad m, TextualMonoid (ParserInput m)) => (Char -> Bool) -> m (ParserInput m)- takeCharsWhile1 predicate = do x <- takeCharsWhile predicate- if Null.null x then unexpected "takeCharsWhile1" else pure x- -- | A subclass of 'InputParsing' for parsers that can switch the input stream type class InputMappableParsing m where- -- | Converts a parser accepting one input stream type to another. The functions @forth@ and @back@ must be inverses of- -- each other and they must distribute through '<>':+ -- | Converts a parser accepting one input stream type to another. The functions @forth@ and @back@ must be+ -- inverses of each other and they must distribute through '<>': -- -- > f (s1 <> s2) == f s1 <> f s2 mapParserInput :: (InputParsing (m s), s ~ ParserInput (m s), Monoid s, Monoid s') =>@@ -214,63 +82,6 @@ oxfordComma :: String -> [String] -> String oxfordComma e [] = "or " <> e oxfordComma e (e':es) = e <> ", " <> oxfordComma e' es--instance InputParsing ReadP where- type ParserInput ReadP = String- getInput = ReadP.look- take n = count n ReadP.get- anyToken = pure <$> ReadP.get- satisfy predicate = pure <$> ReadP.satisfy (predicate . pure)- string = ReadP.string--instance InputCharParsing ReadP where- satisfyCharInput predicate = pure <$> ReadP.satisfy predicate--instance InputParsing Attoparsec.Parser where- type ParserInput Attoparsec.Parser = ByteString- getInput = lookAhead Attoparsec.takeByteString- anyToken = Attoparsec.take 1- take = Attoparsec.take- satisfy predicate = Attoparsec.satisfyWith ByteString.singleton predicate- string = Attoparsec.string--instance InputCharParsing Attoparsec.Parser where- satisfyCharInput predicate = ByteString.Char8.singleton <$> Attoparsec.Char8.satisfy predicate- scanChars = Attoparsec.Char8.scan- takeCharsWhile = Attoparsec.Char8.takeWhile- takeCharsWhile1 = Attoparsec.Char8.takeWhile1--instance InputParsing Attoparsec.Text.Parser where- type ParserInput Attoparsec.Text.Parser = Text- getInput = lookAhead Attoparsec.Text.takeText- anyToken = Attoparsec.Text.take 1- take = Attoparsec.Text.take- satisfy predicate = Attoparsec.Text.satisfyWith Text.singleton predicate- string = Attoparsec.Text.string--instance InputCharParsing Attoparsec.Text.Parser where- satisfyCharInput predicate = Text.singleton <$> Attoparsec.Text.satisfy predicate- scanChars = Attoparsec.Text.scan- takeCharsWhile = Attoparsec.Text.takeWhile- takeCharsWhile1 = Attoparsec.Text.takeWhile1--instance (FactorialMonoid s, Cancellative.LeftReductive s, LookAheadParsing (Incremental.Parser t s)) =>- InputParsing (Incremental.Parser t s) where- type ParserInput (Incremental.Parser t s) = s- getInput = lookAhead Incremental.acceptAll- anyToken = Incremental.anyToken- take n = Incremental.count n Incremental.anyToken- satisfy = Incremental.satisfy- string = Incremental.string- takeWhile = Incremental.takeWhile- takeWhile1 = Incremental.takeWhile1- concatMany = Incremental.concatMany--instance (TextualMonoid s, Cancellative.LeftReductive s, LookAheadParsing (Incremental.Parser t s)) =>- InputCharParsing (Incremental.Parser t s) where- satisfyCharInput = Incremental.satisfyChar- takeCharsWhile = Incremental.takeCharsWhile- takeCharsWhile1 = Incremental.takeCharsWhile1 instance FixTraversable Attoparsec.Parser