parser-combinators 1.0.3 → 1.3.1
raw patch · 12 files changed
Files
- CHANGELOG.md +36/−0
- Control/Applicative/Combinators.hs +88/−73
- Control/Applicative/Combinators/NonEmpty.hs +14/−19
- Control/Applicative/Permutations.hs +74/−62
- Control/Monad/Combinators.hs +105/−108
- Control/Monad/Combinators/Expr.hs +70/−43
- Control/Monad/Combinators/NonEmpty.hs +14/−19
- Control/Monad/Permutations.hs +104/−0
- LICENSE.md +1/−1
- README.md +3/−3
- Setup.hs +0/−6
- parser-combinators.cabal +48/−40
CHANGELOG.md view
@@ -1,3 +1,39 @@+## Parser combinators 1.3.1++* Compiles with [MicroHs](https://github.com/augustss/MicroHs).++## Parser combinators 1.3.0++* Changed the `Control.Applicative.Permutations` module to only require+ `Applicative` and not `Monad`. This module is the least restrictive and works+ with parsers which are not `Monad`s.++* Added the `Control.Monad.Permutations` module. This module may be+ substantially more efficient for some parsers which are `Monad`s.++* Corrected how permutation parsers intercalate effects and components; parsing+ an effect requires that a component immediately follows or else a parse error+ will result.++## Parser combinators 1.2.1++* The tests in `parser-combinators-tests` now work with Megaparsec 8.++* Dropped support for GHC 8.2.++## Parser combinators 1.2.0++* Added `manyTill_` and `someTill_` combinators which work like the older+ `manyTill` and `someTill` except they also return the result of the `end`+ parser.++* Dropped support for GHC 8.0.++## Parser combinators 1.1.0++* Added support for ternary operators; see `TernR` in+ `Control.Monad.Combinators.Expr`.+ ## Parser combinators 1.0.3 * Dropped support for GHC 7.10.
Control/Applicative/Combinators.hs view
@@ -1,6 +1,9 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE TupleSections #-}+ -- | -- Module : Control.Applicative.Combinators--- Copyright : © 2017–2019 Mark Karpov+-- Copyright : © 2017–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -41,47 +44,49 @@ -- backtrack in order for the alternative branch of parsing to be tried. -- Thus it is the responsibility of the programmer to wrap more complex, -- composite parsers in @try@ to achieve correct behavior.--{-# LANGUAGE BangPatterns #-}- module Control.Applicative.Combinators ( -- * Re-exports from "Control.Applicative"- (<|>)+ (<|>), -- $assocbo- , many+ many, -- $many- , some+ some, -- $some- , optional+ optional, -- $optional- , empty+ empty, -- $empty -- * Original combinators- , between- , choice- , count- , count'- , eitherP- , endBy- , endBy1- , manyTill- , someTill- , option- , sepBy- , sepBy1- , sepEndBy- , sepEndBy1- , skipMany- , skipSome- , skipCount- , skipManyTill- , skipSomeTill )+ between,+ choice,+ count,+ count',+ eitherP,+ endBy,+ endBy1,+ manyTill,+ manyTill_,+ someTill,+ someTill_,+ option,+ sepBy,+ sepBy1,+ sepEndBy,+ sepEndBy1,+ skipMany,+ skipSome,+ skipCount,+ skipManyTill,+ skipSomeTill,+ ) where -import Control.Applicative+-- MicroHs has @Control.Applicative.asum :: Alternative f => [f a] -> f a@+-- so we use @Data.Foldable.asum@+import Control.Applicative hiding (asum) import Control.Monad (replicateM, replicateM_)-import Data.Foldable+import Data.Foldable (asum) ---------------------------------------------------------------------------- -- Re-exports from "Control.Applicative"@@ -129,8 +134,7 @@ -- Returns the value returned by @p@. -- -- > braces = between (symbol "{") (symbol "}")--between :: Applicative m => m open -> m close -> m a -> m a+between :: (Applicative m) => m open -> m close -> m a -> m a between open close p = open *> p <* close {-# INLINE between #-} @@ -138,7 +142,6 @@ -- until one of them succeeds. Returns the value of the succeeding parser. -- -- > choice = asum- choice :: (Foldable f, Alternative m) => f (m a) -> m a choice = asum {-# INLINE choice #-}@@ -150,8 +153,7 @@ -- > count = replicateM -- -- See also: 'skipCount', 'count''.--count :: Applicative m => Int -> m a -> m [a]+count :: (Applicative m) => Int -> m a -> m [a] count = replicateM {-# INLINE count #-} @@ -163,21 +165,19 @@ -- as if it were equal to zero. -- -- See also: 'skipCount', 'count'.--count' :: Alternative m => Int -> Int -> m a -> m [a]+count' :: (Alternative m) => Int -> Int -> m a -> m [a] count' m' n' p = go m' n' where go !m !n | n <= 0 || m > n = pure []- | m > 0 = liftA2 (:) p (go (m - 1) (n - 1))- | otherwise = liftA2 (:) p (go 0 (n - 1)) <|> pure []+ | m > 0 = liftA2 (:) p (go (m - 1) (n - 1))+ | otherwise = liftA2 (:) p (go 0 (n - 1)) <|> pure [] {-# INLINE count' #-} -- | Combine two alternatives. -- -- > eitherP a b = (Left <$> a) <|> (Right <$> b)--eitherP :: Alternative m => m a -> m b -> m (Either a b)+eitherP :: (Alternative m) => m a -> m b -> m (Either a b) eitherP a b = (Left <$> a) <|> (Right <$> b) {-# INLINE eitherP #-} @@ -185,38 +185,64 @@ -- ended by @sep@. Returns a list of values returned by @p@. -- -- > cStatements = cStatement `endBy` semicolon--endBy :: Alternative m => m a -> m sep -> m [a]+endBy :: (Alternative m) => m a -> m sep -> m [a] endBy p sep = many (p <* sep) {-# INLINE endBy #-} -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a list of values returned by @p@.--endBy1 :: Alternative m => m a -> m sep -> m [a]+endBy1 :: (Alternative m) => m a -> m sep -> m [a] endBy1 p sep = some (p <* sep) {-# INLINE endBy1 #-} -- | @'manyTill' p end@ applies parser @p@ /zero/ or more times until parser--- @end@ succeeds. Returns the list of values returned by @p@.+-- @end@ succeeds. Returns the list of values returned by @p@. @end@ result+-- is consumed and lost. Use 'manyTill_' if you wish to keep it. -- -- See also: 'skipMany', 'skipManyTill'.--manyTill :: Alternative m => m a -> m end -> m [a]+manyTill :: (Alternative m) => m a -> m end -> m [a] manyTill p end = go where go = ([] <$ end) <|> liftA2 (:) p go {-# INLINE manyTill #-} +-- | @'manyTill_' p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@ and the+-- @end@ result. Use 'manyTill' if you have no need in the result of the+-- @end@.+--+-- See also: 'skipMany', 'skipManyTill'.+--+-- @since 1.2.0+manyTill_ :: (Alternative m) => m a -> m end -> m ([a], end)+manyTill_ p end = go+ where+ go = (([],) <$> end) <|> liftA2 (\x (xs, y) -> (x : xs, y)) p go+{-# INLINE manyTill_ #-}+ -- | @'someTill' p end@ works similarly to @'manyTill' p end@, but @p@--- should succeed at least once.+-- should succeed at least once. @end@ result is consumed and lost. Use+-- 'someTill_' if you wish to keep it. --+-- > someTill p end = liftA2 (:) p (manyTill p end)+-- -- See also: 'skipSome', 'skipSomeTill'.--someTill :: Alternative m => m a -> m end -> m [a]+someTill :: (Alternative m) => m a -> m end -> m [a] someTill p end = liftA2 (:) p (manyTill p end) {-# INLINE someTill #-} +-- | @'someTill_' p end@ works similarly to @'manyTill_' p end@, but @p@+-- should succeed at least once. Use 'someTill' if you have no need in the+-- result of the @end@.+--+-- See also: 'skipSome', 'skipSomeTill'.+--+-- @since 1.2.0+someTill_ :: (Alternative m) => m a -> m end -> m ([a], end)+someTill_ p end =+ liftA2 (\x (xs, y) -> (x : xs, y)) p (manyTill_ p end)+{-# INLINE someTill_ #-}+ -- | @'option' x p@ tries to apply the parser @p@. If @p@ fails without -- consuming input, it returns the value @x@, otherwise the value returned -- by @p@.@@ -224,8 +250,7 @@ -- > option x p = p <|> pure x -- -- See also: 'optional'.--option :: Alternative m => a -> m a -> m a+option :: (Alternative m) => a -> m a -> m a option x p = p <|> pure x {-# INLINE option #-} @@ -233,29 +258,25 @@ -- @sep@. Returns a list of values returned by @p@. -- -- > commaSep p = p `sepBy` comma--sepBy :: Alternative m => m a -> m sep -> m [a]+sepBy :: (Alternative m) => m a -> m sep -> m [a] sepBy p sep = sepBy1 p sep <|> pure [] {-# INLINE sepBy #-} -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@.--sepBy1 :: Alternative m => m a -> m sep -> m [a]+sepBy1 :: (Alternative m) => m a -> m sep -> m [a] sepBy1 p sep = liftA2 (:) p (many (sep *> p)) {-# INLINE sepBy1 #-} -- | @'sepEndBy' p sep@ parses /zero/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy :: Alternative m => m a -> m sep -> m [a]+sepEndBy :: (Alternative m) => m a -> m sep -> m [a] sepEndBy p sep = sepEndBy1 p sep <|> pure [] {-# INLINE sepEndBy #-} -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy1 :: Alternative m => m a -> m sep -> m [a]+sepEndBy1 :: (Alternative m) => m a -> m sep -> m [a] sepEndBy1 p sep = liftA2 (:) p ((sep *> sepEndBy p sep) <|> pure []) {-# INLINEABLE sepEndBy1 #-} @@ -263,8 +284,7 @@ -- its result. -- -- See also: 'manyTill', 'skipManyTill'.--skipMany :: Alternative m => m a -> m ()+skipMany :: (Alternative m) => m a -> m () skipMany p = go where go = (p *> go) <|> pure ()@@ -274,22 +294,19 @@ -- result. -- -- See also: 'someTill', 'skipSomeTill'.--skipSome :: Alternative m => m a -> m ()+skipSome :: (Alternative m) => m a -> m () skipSome p = p *> skipMany p {-# INLINE skipSome #-} -- | @'skipCount' n p@ parses @n@ occurrences of @p@, skipping its result.--- If @n@ is not positive, the parser equals to @'pure' []@. Returns a list--- of @n@ values.+-- If @n@ is not positive, the parser equals to @'pure' ()@. -- -- > skipCount = replicateM_ -- -- See also: 'count', 'count''. -- -- @since 0.3.0--skipCount :: Applicative m => Int -> m a -> m ()+skipCount :: (Applicative m) => Int -> m a -> m () skipCount = replicateM_ {-# INLINE skipCount #-} @@ -298,8 +315,7 @@ -- then returned. -- -- See also: 'manyTill', 'skipMany'.--skipManyTill :: Alternative m => m a -> m end -> m end+skipManyTill :: (Alternative m) => m a -> m end -> m end skipManyTill p end = go where go = end <|> (p *> go)@@ -310,7 +326,6 @@ -- then returned. -- -- See also: 'someTill', 'skipSome'.--skipSomeTill :: Alternative m => m a -> m end -> m end+skipSomeTill :: (Alternative m) => m a -> m end -> m end skipSomeTill p end = p *> skipManyTill p end {-# INLINE skipSomeTill #-}
Control/Applicative/Combinators/NonEmpty.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Control.Applicative.Combinators--- Copyright : © 2017–2019 Mark Karpov+-- Copyright : © 2017–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -11,33 +11,31 @@ -- from "Control.Applicative.Combinators". -- -- @since 0.2.0- module Control.Applicative.Combinators.NonEmpty- ( some- , endBy1- , someTill- , sepBy1- , sepEndBy1 )+ ( some,+ endBy1,+ someTill,+ sepBy1,+ sepEndBy1,+ ) where import Control.Applicative hiding (some)-import Data.List.NonEmpty (NonEmpty (..)) import qualified Control.Applicative.Combinators as C-import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: Alternative m => m a -> m (NonEmpty a)+some :: (Alternative m) => m a -> m (NonEmpty a) some p = NE.fromList <$> C.some p {-# INLINE some #-} -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a non-empty list of values returned by @p@.--endBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+endBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) endBy1 p sep = NE.fromList <$> C.endBy1 p sep {-# INLINE endBy1 #-} @@ -45,22 +43,19 @@ -- should succeed at least once. -- -- See also: 'C.skipSome', 'C.skipSomeTill'.--someTill :: Alternative m => m a -> m end -> m (NonEmpty a)+someTill :: (Alternative m) => m a -> m end -> m (NonEmpty a) someTill p end = NE.fromList <$> C.someTill p end {-# INLINE someTill #-} -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a non-empty list of values returned by @p@.--sepBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) sepBy1 p sep = NE.fromList <$> C.sepBy1 p sep {-# INLINE sepBy1 #-} -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a non-empty list of values returned by -- @p@.--sepEndBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepEndBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) sepEndBy1 p sep = NE.fromList <$> C.sepEndBy1 p sep {-# INLINE sepEndBy1 #-}
Control/Applicative/Permutations.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE ExistentialQuantification #-}+ -- | -- Module : Control.Applicative.Permutations--- Copyright : © 2017–2019 Alex Washburn+-- Copyright : © 2017–present Alex Washburn -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -30,8 +32,8 @@ -- -- For example, suppose we want to parse a permutation of: an optional -- string of @a@'s, the character @b@ and an optional @c@. Using a standard--- parsing library combinator @char@, this can be described using the--- 'Applicative' instance by:+-- parsing library combinator @char@ (e.g. 'Text.ParserCombinators.ReadP.ReadP')+-- this can be described using the 'Applicative' instance by: -- -- > test = runPermutation $ -- > (,,) <$> toPermutationWithDefault "" (some (char 'a'))@@ -39,53 +41,56 @@ -- > <*> toPermutationWithDefault '_' (char 'c') -- -- @since 0.2.0--{-# LANGUAGE CPP #-}- module Control.Applicative.Permutations ( -- ** Permutation type- Permutation+ Permutation,+ -- ** Permutation evaluators- , runPermutation- , intercalateEffect+ runPermutation,+ intercalateEffect,+ -- ** Permutation constructors- , toPermutation- , toPermutationWithDefault )+ toPermutation,+ toPermutationWithDefault,+ ) where import Control.Applicative+import Data.Function ((&)) -- | An 'Applicative' wrapper-type for constructing permutation parsers.+data Permutation m a = P !(Maybe a) [Branch m a] -data Permutation m a = P !(Maybe a) (m (Permutation m a))+data Branch m a = forall z. Branch (Permutation m (z -> a)) (m z) -instance Functor m => Functor (Permutation m) where- fmap f (P v p) = P (f <$> v) (fmap f <$> p)+instance (Functor m) => Functor (Permutation m) where+ fmap f (P v bs) = P (f <$> v) (fmap f <$> bs) -instance Alternative m => Applicative (Permutation m) where+instance (Functor p) => Functor (Branch p) where+ fmap f (Branch perm p) = Branch (fmap (f .) perm) p++instance (Functor m) => Applicative (Permutation m) where pure value = P (Just value) empty- lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) (lhsAlt <|> rhsAlt)+ lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) $ (ins2 <$> v) <> (ins1 <$> w) where- lhsAlt = (<*> rhs) <$> v- rhsAlt = (lhs <*>) <$> w-#if MIN_VERSION_base(4,10,0)- liftA2 f lhs@(P x v) rhs@(P y w) = P (liftA2 f x y) (lhsAlt <|> rhsAlt)+ ins1 (Branch perm p) = Branch ((.) <$> lhs <*> perm) p+ ins2 (Branch perm p) = Branch (flip <$> perm <*> rhs) p+ liftA2 f lhs@(P x v) rhs@(P y w) = P (liftA2 f x y) $ (ins2 <$> v) <> (ins1 <$> w) where- lhsAlt = (\p -> liftA2 f p rhs) <$> v- rhsAlt = liftA2 f lhs <$> w-#endif+ ins1 (Branch perm p) = Branch (liftA2 ((.) . f) lhs perm) p+ ins2 (Branch perm p) = Branch (liftA2 (\b g z -> f (g z) b) rhs perm) p -- | \"Unlifts\" a permutation parser into a parser to be evaluated.--runPermutation- :: ( Alternative m- , Monad m)- => Permutation m a -- ^ Permutation specification- -> m a -- ^ Resulting base monad capable of handling the permutation-runPermutation (P value parser) = optional parser >>= f- where- f Nothing = maybe empty pure value- f (Just p) = runPermutation p+runPermutation ::+ (Alternative m) =>+ -- | Permutation specification+ Permutation m a ->+ -- | Resulting base monad capable of handling the permutation+ m a+runPermutation = foldAlt f+ where+ -- INCORRECT = runPerms t <*> p+ f (Branch t p) = (&) <$> p <*> runPermutation t -- | \"Unlifts\" a permutation parser into a parser to be evaluated with an -- intercalated effect. Useful for separators between permutation elements.@@ -113,41 +118,48 @@ -- permutation. -- * No effects are intercalated between missing components with a -- default value.--intercalateEffect- :: ( Alternative m- , Monad m)- => m b -- ^ Effect to be intercalated between permutation components- -> Permutation m a -- ^ Permutation specification- -> m a -- ^ Resulting base monad capable of handling the permutation-intercalateEffect = run noEffect- where- noEffect = pure ()+-- * If an effect is encountered after a component, another component must+-- immediately follow the effect.+intercalateEffect ::+ (Alternative m) =>+ -- | Effect to be intercalated between permutation components+ m b ->+ -- | Permutation specification+ Permutation m a ->+ -- | Resulting base applicative capable of handling the permutation+ m a+intercalateEffect effect = foldAlt (runBranchEff effect)+ where+ runPermEff :: (Alternative m) => m b -> Permutation m a -> m a+ runPermEff eff (P v bs) =+ eff *> foldr ((<|>) . runBranchEff eff) empty bs <|> maybe empty pure v - run :: (Alternative m, Monad m) => m c -> m b -> Permutation m a -> m a- run headSep tailSep (P value parser) = optional headSep >>= f- where- f Nothing = maybe empty pure value- f (Just _) = optional parser >>= g- g Nothing = maybe empty pure value- g (Just p) = run tailSep tailSep p+ runBranchEff :: (Alternative m) => m b -> Branch m a -> m a+ runBranchEff eff (Branch t p) = (&) <$> p <*> runPermEff eff t -- | \"Lifts\" a parser to a permutation parser.--toPermutation- :: Alternative m- => m a -- ^ Permutation component- -> Permutation m a-toPermutation p = P Nothing $ pure <$> p+toPermutation ::+ (Alternative m) =>+ -- | Permutation component+ m a ->+ Permutation m a+toPermutation = P Nothing . pure . branch -- | \"Lifts\" a parser with a default value to a permutation parser. -- -- If no permutation containing the supplied parser can be parsed from the input, -- then the supplied default value is returned in lieu of a parse result.+toPermutationWithDefault ::+ (Alternative m) =>+ -- | Default Value+ a ->+ -- | Permutation component+ m a ->+ Permutation m a+toPermutationWithDefault v = P (Just v) . pure . branch -toPermutationWithDefault- :: Alternative m- => a -- ^ Default Value- -> m a -- ^ Permutation component- -> Permutation m a-toPermutationWithDefault v p = P (Just v) $ pure <$> p+branch :: (Functor m) => m a -> Branch m a+branch = Branch $ pure id++foldAlt :: (Alternative m) => (Branch m a -> m a) -> Permutation m a -> m a+foldAlt f (P v bs) = foldr ((<|>) . f) (maybe empty pure v) bs
Control/Monad/Combinators.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE BangPatterns #-}+ -- | -- Module : Control.Monad.Combinators--- Copyright : © 2017–2019 Mark Karpov+-- Copyright : © 2017–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -15,44 +17,44 @@ -- "Control.Applicative.Combinators". -- -- @since 0.4.0--{-# LANGUAGE BangPatterns #-}- module Control.Monad.Combinators ( -- * Re-exports from "Control.Applicative"- (C.<|>)+ (C.<|>), -- $assocbo- , C.optional+ C.optional, -- $optional- , C.empty+ C.empty, -- $empty -- * Original combinators- , C.between- , C.choice- , count- , count'- , C.eitherP- , endBy- , endBy1- , many- , manyTill- , some- , someTill- , C.option- , sepBy- , sepBy1- , sepEndBy- , sepEndBy1- , skipMany- , skipSome- , skipCount- , skipManyTill- , skipSomeTill )+ C.between,+ C.choice,+ count,+ count',+ C.eitherP,+ endBy,+ endBy1,+ many,+ manyTill,+ manyTill_,+ some,+ someTill,+ someTill_,+ C.option,+ sepBy,+ sepBy1,+ sepEndBy,+ sepEndBy1,+ skipMany,+ skipSome,+ skipCount,+ skipManyTill,+ skipSomeTill,+ ) where -import Control.Monad import qualified Control.Applicative.Combinators as C+import Control.Monad ---------------------------------------------------------------------------- -- Re-exports from "Control.Applicative"@@ -85,8 +87,7 @@ -- values. -- -- See also: 'skipCount', 'count''.--count :: Monad m => Int -> m a -> m [a]+count :: (Monad m) => Int -> m a -> m [a] count n' p = go id n' where go f !n =@@ -94,7 +95,7 @@ then return (f []) else do x <- p- go (f . (x:)) (n - 1)+ go (f . (x :)) (n - 1) {-# INLINE count #-} -- | @'count'' m n p@ parses from @m@ to @n@ occurrences of @p@. If @n@ is@@ -105,8 +106,7 @@ -- as if it were equal to zero. -- -- See also: 'skipCount', 'count'.--count' :: MonadPlus m => Int -> Int -> m a -> m [a]+count' :: (MonadPlus m) => Int -> Int -> m a -> m [a] count' m' n' p = if n' > 0 && n' >= m' then gom id m'@@ -116,15 +116,15 @@ if m > 0 then do x <- p- gom (f . (x:)) (m - 1)+ gom (f . (x :)) (m - 1) else god f (if m' <= 0 then n' else n' - m') god f !d = if d > 0 then do- r <- optional p+ r <- C.optional p case r of Nothing -> return (f [])- Just x -> god (f . (x:)) (d - 1)+ Just x -> god (f . (x :)) (d - 1) else return (f []) {-# INLINE count' #-} @@ -132,116 +132,134 @@ -- ended by @sep@. Returns a list of values returned by @p@. -- -- > cStatements = cStatement `endBy` semicolon--endBy :: MonadPlus m => m a -> m sep -> m [a]-endBy p sep = many (p >>= \x -> re x sep)+endBy :: (MonadPlus m) => m a -> m sep -> m [a]+endBy p sep = many (p >>= \x -> x <$ sep) {-# INLINE endBy #-} -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a list of values returned by @p@.--endBy1 :: MonadPlus m => m a -> m sep -> m [a]-endBy1 p sep = some (p >>= \x -> re x sep)+endBy1 :: (MonadPlus m) => m a -> m sep -> m [a]+endBy1 p sep = some (p >>= \x -> x <$ sep) {-# INLINE endBy1 #-} -- | @'many' p@ applies the parser @p@ /zero/ or more times and returns a -- list of the values returned by @p@. -- -- > identifier = (:) <$> letter <*> many (alphaNumChar <|> char '_')--many :: MonadPlus m => m a -> m [a]+many :: (MonadPlus m) => m a -> m [a] many p = go id where go f = do- r <- optional p+ r <- C.optional p case r of Nothing -> return (f [])- Just x -> go (f . (x:))+ Just x -> go (f . (x :)) {-# INLINE many #-} -- | @'manyTill' p end@ applies parser @p@ /zero/ or more times until parser--- @end@ succeeds. Returns the list of values returned by @p@.+-- @end@ succeeds. Returns the list of values returned by @p@. __Note__ that+-- @end@ result is consumed and lost. Use 'manyTill_' if you wish to keep+-- it. -- -- See also: 'skipMany', 'skipManyTill'.+manyTill :: (MonadPlus m) => m a -> m end -> m [a]+manyTill p end = fst <$> manyTill_ p end+{-# INLINE manyTill #-} -manyTill :: MonadPlus m => m a -> m end -> m [a]-manyTill p end = go id+-- | @'manyTill_' p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@ and the+-- @end@ result. Use 'manyTill' if you have no need in the result of the+-- @end@.+--+-- See also: 'skipMany', 'skipManyTill'.+--+-- @since 1.2.0+manyTill_ :: (MonadPlus m) => m a -> m end -> m ([a], end)+manyTill_ p end = go id where go f = do- done <- option False (re True end)- if done- then return (f [])- else do+ done <- C.optional end+ case done of+ Just done' -> return (f [], done')+ Nothing -> do x <- p- go (f . (x:))-{-# INLINE manyTill #-}+ go (f . (x :))+{-# INLINE manyTill_ #-} -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: MonadPlus m => m a -> m [a]+some :: (MonadPlus m) => m a -> m [a] some p = liftM2 (:) p (many p) {-# INLINE some #-} -- | @'someTill' p end@ works similarly to @'manyTill' p end@, but @p@--- should succeed at least once.+-- should succeed at least once. __Note__ that @end@ result is consumed and+-- lost. Use 'someTill_' if you wish to keep it. --+-- > someTill p end = liftM2 (:) p (manyTill p end)+-- -- See also: 'skipSome', 'skipSomeTill'.--someTill :: MonadPlus m => m a -> m end -> m [a]+someTill :: (MonadPlus m) => m a -> m end -> m [a] someTill p end = liftM2 (:) p (manyTill p end) {-# INLINE someTill #-} +-- | @'someTill_' p end@ works similarly to @'manyTill_' p end@, but @p@+-- should succeed at least once. Use 'someTill' if you have no need in the+-- result of the @end@.+--+-- See also: 'skipSome', 'skipSomeTill'.+--+-- @since 1.2.0+someTill_ :: (MonadPlus m) => m a -> m end -> m ([a], end)+someTill_ p end = liftM2 (\x (xs, y) -> (x : xs, y)) p (manyTill_ p end)+{-# INLINE someTill_ #-}+ -- | @'sepBy' p sep@ parses /zero/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@. -- -- > commaSep p = p `sepBy` comma--sepBy :: MonadPlus m => m a -> m sep -> m [a]+sepBy :: (MonadPlus m) => m a -> m sep -> m [a] sepBy p sep = do- r <- optional p+ r <- C.optional p case r of Nothing -> return []- Just x -> (x:) <$> many (sep >> p)+ Just x -> (x :) <$> many (sep >> p) {-# INLINE sepBy #-} -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@.--sepBy1 :: MonadPlus m => m a -> m sep -> m [a]+sepBy1 :: (MonadPlus m) => m a -> m sep -> m [a] sepBy1 p sep = do x <- p- (x:) <$> many (sep >> p)+ (x :) <$> many (sep >> p) {-# INLINE sepBy1 #-} -- | @'sepEndBy' p sep@ parses /zero/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy :: MonadPlus m => m a -> m sep -> m [a]+sepEndBy :: (MonadPlus m) => m a -> m sep -> m [a] sepEndBy p sep = go id where go f = do- r <- optional p+ r <- C.optional p case r of Nothing -> return (f [])- Just x -> do- more <- option False (re True sep)+ Just x -> do+ more <- C.option False (True <$ sep) if more- then go (f . (x:))+ then go (f . (x :)) else return (f [x]) {-# INLINE sepEndBy #-} -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy1 :: MonadPlus m => m a -> m sep -> m [a]+sepEndBy1 :: (MonadPlus m) => m a -> m sep -> m [a] sepEndBy1 p sep = do x <- p- more <- option False (re True sep)+ more <- C.option False (True <$ sep) if more- then (x:) <$> sepEndBy p sep+ then (x :) <$> sepEndBy p sep else return [x] {-# INLINE sepEndBy1 #-} @@ -249,12 +267,11 @@ -- its result. -- -- See also: 'manyTill', 'skipManyTill'.--skipMany :: MonadPlus m => m a -> m ()+skipMany :: (MonadPlus m) => m a -> m () skipMany p = go where go = do- more <- option False (re True p)+ more <- C.option False (True <$ p) when more go {-# INLINE skipMany #-} @@ -262,18 +279,15 @@ -- result. -- -- See also: 'someTill', 'skipSomeTill'.--skipSome :: MonadPlus m => m a -> m ()+skipSome :: (MonadPlus m) => m a -> m () skipSome p = p >> skipMany p {-# INLINE skipSome #-} -- | @'skipCount' n p@ parses @n@ occurrences of @p@, skipping its result.--- If @n@ is smaller or equal to zero, the parser equals to @'return' []@.--- Returns a list of @n@ values.+-- If @n@ is smaller or equal to zero, the parser equals to @'return' ()@. -- -- See also: 'count', 'count''.--skipCount :: Monad m => Int -> m a -> m ()+skipCount :: (Monad m) => Int -> m a -> m () skipCount n' p = go n' where go !n =@@ -286,15 +300,14 @@ -- then returned. -- -- See also: 'manyTill', 'skipMany'.--skipManyTill :: MonadPlus m => m a -> m end -> m end+skipManyTill :: (MonadPlus m) => m a -> m end -> m end skipManyTill p end = go where go = do- r <- optional end+ r <- C.optional end case r of Nothing -> p >> go- Just x -> return x+ Just x -> return x {-# INLINE skipManyTill #-} -- | @'skipSomeTill' p end@ applies the parser @p@ /one/ or more times@@ -302,22 +315,6 @@ -- then returned. -- -- See also: 'someTill', 'skipSome'.--skipSomeTill :: MonadPlus m => m a -> m end -> m end+skipSomeTill :: (MonadPlus m) => m a -> m end -> m end skipSomeTill p end = p >> skipManyTill p end {-# INLINE skipSomeTill #-}--------------------------------------------------------------------------------- Compat helpers (for older GHCs)--re :: Monad m => a -> m b -> m a-re x = fmap (const x)-{-# INLINE re #-}--option :: MonadPlus m => a -> m a -> m a-option x p = p `mplus` return x-{-# INLINE option #-}--optional :: MonadPlus m => m a -> m (Maybe a)-optional p = fmap Just p `mplus` return Nothing-{-# INLINE optional #-}
Control/Monad/Combinators/Expr.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Control.Monad.Combinators.Expr--- Copyright : © 2017–2019 Mark Karpov+-- Copyright : © 2017–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -11,10 +11,10 @@ -- of operators. -- -- @since 1.0.0- module Control.Monad.Combinators.Expr- ( Operator (..)- , makeExprParser )+ ( Operator (..),+ makeExprParser,+ ) where import Control.Monad@@ -23,13 +23,29 @@ -- | This data type specifies operators that work on values of type @a@. An -- operator is either binary infix or unary prefix or postfix. A binary -- operator has also an associated associativity.- data Operator m a- = InfixN (m (a -> a -> a)) -- ^ Non-associative infix- | InfixL (m (a -> a -> a)) -- ^ Left-associative infix- | InfixR (m (a -> a -> a)) -- ^ Right-associative infix- | Prefix (m (a -> a)) -- ^ Prefix- | Postfix (m (a -> a)) -- ^ Postfix+ = -- | Non-associative infix+ InfixN (m (a -> a -> a))+ | -- | Left-associative infix+ InfixL (m (a -> a -> a))+ | -- | Right-associative infix+ InfixR (m (a -> a -> a))+ | -- | Prefix+ Prefix (m (a -> a))+ | -- | Postfix+ Postfix (m (a -> a))+ | -- | Right-associative ternary. Right-associative means that+ -- @a ? b : d ? e : f@ parsed as+ -- @a ? b : (d ? e : f)@ and not as @(a ? b : d) ? e : f@.+ --+ -- The outer monadic action parses the first separator (e.g. @?@) and+ -- returns an action (of type @m (a -> a -> a -> a)@) that parses the+ -- second separator (e.g. @:@).+ --+ -- Example usage:+ --+ -- >>> TernR ((If <$ char ':') <$ char '?')+ TernR (m (m (a -> a -> a -> a))) -- | @'makeExprParser' term table@ builds an expression parser for terms -- @term@ with operators from @table@, taking the associativity and@@ -76,36 +92,38 @@ -- > binary name f = InfixL (f <$ symbol name) -- > prefix name f = Prefix (f <$ symbol name) -- > postfix name f = Postfix (f <$ symbol name)--makeExprParser :: MonadPlus m- => m a -- ^ Term parser- -> [[Operator m a]] -- ^ Operator table, see 'Operator'- -> m a -- ^ Resulting expression parser+makeExprParser ::+ (MonadPlus m) =>+ -- | Term parser+ m a ->+ -- | Operator table, see 'Operator'+ [[Operator m a]] ->+ -- | Resulting expression parser+ m a makeExprParser = foldl addPrecLevel {-# INLINEABLE makeExprParser #-} -- | @addPrecLevel p ops@ adds the ability to parse operators in table @ops@ -- to parser @p@.--addPrecLevel :: MonadPlus m => m a -> [Operator m a] -> m a+addPrecLevel :: (MonadPlus m) => m a -> [Operator m a] -> m a addPrecLevel term ops =- term' >>= \x -> choice [ras' x, las' x, nas' x, return x]+ term' >>= \x -> choice [ras' x, las' x, nas' x, tern' x, return x] where- (ras, las, nas, prefix, postfix) = foldr splitOp ([],[],[],[],[]) ops+ (ras, las, nas, prefix, postfix, tern) = foldr splitOp ([], [], [], [], [], []) ops term' = pTerm (choice prefix) term (choice postfix)- ras' = pInfixR (choice ras) term'- las' = pInfixL (choice las) term'- nas' = pInfixN (choice nas) term'+ ras' = pInfixR (choice ras) term'+ las' = pInfixL (choice las) term'+ nas' = pInfixN (choice nas) term'+ tern' = pTernR (choice tern) term' {-# INLINEABLE addPrecLevel #-} -- | @pTerm prefix term postfix@ parses a @term@ surrounded by optional -- prefix and postfix unary operators. Parsers @prefix@ and @postfix@ are -- allowed to fail, in this case 'id' is used.--pTerm :: MonadPlus m => m (a -> a) -> m a -> m (a -> a) -> m a+pTerm :: (MonadPlus m) => m (a -> a) -> m a -> m (a -> a) -> m a pTerm prefix term postfix = do- pre <- option id prefix- x <- term+ pre <- option id prefix+ x <- term post <- option id postfix return . post . pre $ x {-# INLINE pTerm #-}@@ -113,8 +131,7 @@ -- | @pInfixN op p x@ parses non-associative infix operator @op@, then term -- with parser @p@, then returns result of the operator application on @x@ -- and the term.--pInfixN :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixN :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixN op p x = do f <- op y <- p@@ -124,8 +141,7 @@ -- | @pInfixL op p x@ parses left-associative infix operator @op@, then term -- with parser @p@, then returns result of the operator application on @x@ -- and the term.--pInfixL :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixL :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixL op p x = do f <- op y <- p@@ -136,27 +152,38 @@ -- | @pInfixR op p x@ parses right-associative infix operator @op@, then -- term with parser @p@, then returns result of the operator application on -- @x@ and the term.--pInfixR :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixR :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixR op p x = do f <- op y <- p >>= \r -> pInfixR op p r <|> return r return $ f x y {-# INLINE pInfixR #-} +-- | Parse the first separator of a ternary operator+pTernR :: (MonadPlus m) => m (m (a -> a -> a -> a)) -> m a -> a -> m a+pTernR sep1 p x = do+ sep2 <- sep1+ y <- p >>= \r -> pTernR sep1 p r `mplus` return r+ f <- sep2+ z <- p >>= \r -> pTernR sep1 p r `mplus` return r+ return $ f x y z+{-# INLINE pTernR #-}+ type Batch m a =- ( [m (a -> a -> a)]- , [m (a -> a -> a)]- , [m (a -> a -> a)]- , [m (a -> a)]- , [m (a -> a)] )+ ( [m (a -> a -> a)],+ [m (a -> a -> a)],+ [m (a -> a -> a)],+ [m (a -> a)],+ [m (a -> a)],+ [m (m (a -> a -> a -> a))]+ ) -- | A helper to separate various operators (binary, unary, and according to -- associativity) and return them in a tuple.- splitOp :: Operator m a -> Batch m a -> Batch m a-splitOp (InfixR op) (r, l, n, pre, post) = (op:r, l, n, pre, post)-splitOp (InfixL op) (r, l, n, pre, post) = (r, op:l, n, pre, post)-splitOp (InfixN op) (r, l, n, pre, post) = (r, l, op:n, pre, post)-splitOp (Prefix op) (r, l, n, pre, post) = (r, l, n, op:pre, post)-splitOp (Postfix op) (r, l, n, pre, post) = (r, l, n, pre, op:post)+splitOp (InfixR op) (r, l, n, pre, post, tern) = (op : r, l, n, pre, post, tern)+splitOp (InfixL op) (r, l, n, pre, post, tern) = (r, op : l, n, pre, post, tern)+splitOp (InfixN op) (r, l, n, pre, post, tern) = (r, l, op : n, pre, post, tern)+splitOp (Prefix op) (r, l, n, pre, post, tern) = (r, l, n, op : pre, post, tern)+splitOp (Postfix op) (r, l, n, pre, post, tern) = (r, l, n, pre, op : post, tern)+splitOp (TernR op) (r, l, n, pre, post, tern) = (r, l, n, pre, post, op : tern)
Control/Monad/Combinators/NonEmpty.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Control.Monad.Combinators.NonEmpty--- Copyright : © 2017–2019 Mark Karpov+-- Copyright : © 2017–present Mark Karpov -- License : BSD 3 clause -- -- Maintainer : Mark Karpov <markkarpov92@gmail.com>@@ -11,33 +11,31 @@ -- from "Control.Monad.Combinators". -- -- @since 0.4.0- module Control.Monad.Combinators.NonEmpty- ( some- , endBy1- , someTill- , sepBy1- , sepEndBy1 )+ ( some,+ endBy1,+ someTill,+ sepBy1,+ sepEndBy1,+ ) where import Control.Monad-import Data.List.NonEmpty (NonEmpty (..)) import qualified Control.Monad.Combinators as C-import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: MonadPlus m => m a -> m (NonEmpty a)+some :: (MonadPlus m) => m a -> m (NonEmpty a) some p = NE.fromList <$> C.some p {-# INLINE some #-} -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a non-empty list of values returned by @p@.--endBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)+endBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a) endBy1 p sep = NE.fromList <$> C.endBy1 p sep {-# INLINE endBy1 #-} @@ -45,22 +43,19 @@ -- should succeed at least once. -- -- See also: 'C.skipSome', 'C.skipSomeTill'.--someTill :: MonadPlus m => m a -> m end -> m (NonEmpty a)+someTill :: (MonadPlus m) => m a -> m end -> m (NonEmpty a) someTill p end = NE.fromList <$> C.someTill p end {-# INLINE someTill #-} -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a non-empty list of values returned by @p@.--sepBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)+sepBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a) sepBy1 p sep = NE.fromList <$> C.sepBy1 p sep {-# INLINE sepBy1 #-} -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a non-empty list of values returned by -- @p@.--sepEndBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)+sepEndBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a) sepEndBy1 p sep = NE.fromList <$> C.sepEndBy1 p sep {-# INLINE sepEndBy1 #-}
+ Control/Monad/Permutations.hs view
@@ -0,0 +1,104 @@+-- |+-- Module : Control.Monad.Permutations+-- Copyright : © 2017–present Alex Washburn+-- License : BSD 3 clause+--+-- Maintainer : Mark Karpov <markkarpov92@gmail.com>+-- Stability : experimental+-- Portability : portable+--+-- This module specialized the interface to 'Monad' for potential efficiency+-- considerations, depending on the monad the permutations are run over.+--+-- For a more general interface requiring only 'Applicative', and for more+-- complete documentation, see the "Control.Applicative.Permutations" module.+--+-- @since 1.3.0+module Control.Monad.Permutations+ ( -- ** Permutation type+ Permutation,++ -- ** Permutation evaluators+ runPermutation,+ intercalateEffect,++ -- ** Permutation constructors+ toPermutation,+ toPermutationWithDefault,+ )+where++import Control.Applicative++-- | An 'Applicative' wrapper-type for constructing permutation parsers.+data Permutation m a = P !(Maybe a) (m (Permutation m a))++instance (Functor m) => Functor (Permutation m) where+ fmap f (P v p) = P (f <$> v) (fmap f <$> p)++instance (Alternative m) => Applicative (Permutation m) where+ pure value = P (Just value) empty+ lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) (lhsAlt <|> rhsAlt)+ where+ lhsAlt = (<*> rhs) <$> v+ rhsAlt = (lhs <*>) <$> w+ liftA2 f lhs@(P x v) rhs@(P y w) = P (liftA2 f x y) (lhsAlt <|> rhsAlt)+ where+ lhsAlt = (\p -> liftA2 f p rhs) <$> v+ rhsAlt = liftA2 f lhs <$> w++-- | \"Unlifts\" a permutation parser into a parser to be evaluated.+runPermutation ::+ ( Alternative m,+ Monad m+ ) =>+ -- | Permutation specification+ Permutation m a ->+ -- | Resulting base monad capable of handling the permutation+ m a+runPermutation (P value parser) = optional parser >>= f+ where+ f Nothing = maybe empty pure value+ f (Just p) = runPermutation p++-- | \"Unlifts\" a permutation parser into a parser to be evaluated with an+-- intercalated effect. Useful for separators between permutation elements.+intercalateEffect ::+ ( Alternative m,+ Monad m+ ) =>+ -- | Effect to be intercalated between permutation components+ m b ->+ -- | Permutation specification+ Permutation m a ->+ -- | Resulting base monad capable of handling the permutation+ m a+intercalateEffect = run noEffect+ where+ noEffect = pure ()+ run :: (Alternative m, Monad m) => m c -> m b -> Permutation m a -> m a+ run headSep tailSep (P value parser) = optional (headSep *> parser) >>= f+ where+ f Nothing = maybe empty pure value+ f (Just p) = run tailSep tailSep p++-- | \"Lifts\" a parser to a permutation parser.+toPermutation ::+ (Alternative m) =>+ -- | Permutation component+ m a ->+ Permutation m a+toPermutation p = P Nothing $ pure <$> p++-- | \"Lifts\" a parser with a default value to a permutation parser.+--+-- If no permutation containing the supplied parser can be parsed from the input,+-- then the supplied default value is returned in lieu of a parse result.+toPermutationWithDefault ::+ (Alternative m) =>+ -- | Default Value+ a ->+ -- | Permutation component+ m a ->+ Permutation m a+toPermutationWithDefault v p = P (Just v) $ pure <$> p
LICENSE.md view
@@ -1,4 +1,4 @@-Copyright © 2017–2019 Mark Karpov+Copyright © 2017–present Mark Karpov All rights reserved.
README.md view
@@ -4,7 +4,7 @@ [](https://hackage.haskell.org/package/parser-combinators) [](http://stackage.org/nightly/package/parser-combinators) [](http://stackage.org/lts/package/parser-combinators)-[](https://travis-ci.org/mrkkrp/parser-combinators)+[](https://github.com/mrkkrp/parser-combinators/actions/workflows/ci.yaml) The package provides common parser combinators defined in terms of `Applicative` and `Alternative` without any dependencies but `base`. There@@ -16,10 +16,10 @@ Issues, bugs, and questions may be reported in [the GitHub issue tracker for this project](https://github.com/mrkkrp/parser-combinators/issues). -Pull requests are also welcome and will be reviewed quickly.+Pull requests are also welcome. ## License -Copyright © 2017–2019 Mark Karpov+Copyright © 2017–present Mark Karpov Distributed under BSD 3 clause license.
− Setup.hs
@@ -1,6 +0,0 @@-module Main (main) where--import Distribution.Simple--main :: IO ()-main = defaultMain
parser-combinators.cabal view
@@ -1,46 +1,54 @@-name: parser-combinators-version: 1.0.3-cabal-version: 1.18-tested-with: GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5-license: BSD3-license-file: LICENSE.md-author: Mark Karpov <markkarpov92@gmail.com>- Alex Washburn <github@recursion.ninja>-maintainer: Mark Karpov <markkarpov92@gmail.com>-homepage: https://github.com/mrkkrp/parser-combinators-bug-reports: https://github.com/mrkkrp/parser-combinators/issues-category: Parsing-synopsis: Lightweight package providing commonly useful parser combinators-build-type: Simple-description: Lightweight package providing commonly useful parser combinators.-extra-doc-files: CHANGELOG.md- , README.md+cabal-version: 2.4+name: parser-combinators+version: 1.3.1+license: BSD-3-Clause+license-file: LICENSE.md+maintainer: Mark Karpov <markkarpov92@gmail.com>+author:+ Mark Karpov <markkarpov92@gmail.com>+ Alex Washburn <github@recursion.ninja> +tested-with: ghc ==9.8.4 ghc ==9.10.3 ghc ==9.12.1+homepage: https://github.com/mrkkrp/parser-combinators+bug-reports: https://github.com/mrkkrp/parser-combinators/issues+synopsis:+ Lightweight package providing commonly useful parser combinators++description:+ Lightweight package providing commonly useful parser combinators.++category: Parsing+build-type: Simple+extra-doc-files:+ CHANGELOG.md+ README.md+ source-repository head- type: git- location: https://github.com/mrkkrp/parser-combinators.git+ type: git+ location: https://github.com/mrkkrp/parser-combinators.git flag dev- description: Turn on development settings.- manual: True- default: False+ description: Turn on development settings.+ default: False+ manual: True library- build-depends: base >= 4.9 && < 5.0- exposed-modules: Control.Applicative.Combinators- , Control.Applicative.Combinators.NonEmpty- , Control.Applicative.Permutations- , Control.Monad.Combinators- , Control.Monad.Combinators.Expr- , Control.Monad.Combinators.NonEmpty- if flag(dev)- ghc-options: -Wall -Werror- else- ghc-options: -O2 -Wall- if flag(dev)- ghc-options: -Wcompat- -Wincomplete-record-updates- -Wincomplete-uni-patterns- -Wnoncanonical-monad-instances- -Wnoncanonical-monadfail-instances- default-language: Haskell2010+ exposed-modules:+ Control.Applicative.Combinators+ Control.Applicative.Combinators.NonEmpty+ Control.Applicative.Permutations+ Control.Monad.Combinators+ Control.Monad.Combinators.Expr+ Control.Monad.Combinators.NonEmpty+ Control.Monad.Permutations++ default-language: Haskell2010+ build-depends: base >=4.15 && <5++ if flag(dev)+ ghc-options:+ -Wall -Werror -Wredundant-constraints -Wpartial-fields+ -Wunused-packages++ else+ ghc-options: -O2 -Wall