packages feed

bookhound 0.1.25.0 → 0.1.26.0

raw patch · 19 files changed

+647/−642 lines, 19 filesdep +mtldep ~basedep ~containersdep ~textPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: mtl

Dependency ranges changed: base, containers, text, time

API changes (from Hackage documentation)

- Bookhound.Parser: NoMatch :: String -> ParseError
- Bookhound.Parser: UnexpectedChar :: Char -> ParseError
- Bookhound.Parser: UnexpectedString :: String -> ParseError
- Bookhound.Parser: char :: Parser Char
- Bookhound.Parser: check :: String -> (a -> Bool) -> Parser a -> Parser a
- Bookhound.Parser: errorParser :: ParseError -> Parser a
- Bookhound.Parser: isMatch :: (Char -> Char -> Bool) -> Parser Char -> Char -> Parser Char
- Bookhound.ParserCombinators: (<|>) :: Parser a -> Parser a -> Parser a
- Bookhound.ParserCombinators: anySepBy :: Parser a -> Parser b -> Parser [b]
- Bookhound.ParserCombinators: anyTimes :: Parser a -> Parser [a]
- Bookhound.ParserCombinators: contains :: Eq a => [a] -> Parser [a] -> Parser [a]
- Bookhound.ParserCombinators: containsAnyOf :: (Foldable t, Eq a) => t [a] -> Parser [a] -> Parser [a]
- Bookhound.ParserCombinators: containsNoneOf :: (Foldable t, Eq a) => t [a] -> Parser [a] -> Parser [a]
- Bookhound.ParserCombinators: infixl 3 <|>
- Bookhound.ParserCombinators: instance (GHC.Num.Num a, GHC.Read.Read a, GHC.Show.Show a) => Bookhound.ParserCombinators.IsMatch a
- Bookhound.ParserCombinators: maybeTimes :: Parser a -> Parser (Maybe a)
- Bookhound.ParserCombinators: maybeWithin :: Parser a -> Parser b -> Parser b
- Bookhound.ParserCombinators: maybeWithinBoth :: Parser a -> Parser b -> Parser c -> Parser c
- Bookhound.ParserCombinators: multipleTimes :: Parser a -> Parser [a]
- Bookhound.ParserCombinators: notContains :: Eq a => [a] -> Parser [a] -> Parser [a]
- Bookhound.ParserCombinators: satisfies :: (a -> Bool) -> Parser a -> Parser a
- Bookhound.ParserCombinators: someTimes :: Parser a -> Parser [a]
- Bookhound.ParserCombinators: within :: Parser a -> Parser b -> Parser b
- Bookhound.ParserCombinators: withinBoth :: Parser a -> Parser b -> Parser c -> Parser c
- Bookhound.Parsers.Char: letter :: Parser Char
- Bookhound.Parsers.Number: intLike :: Parser Integer
- Bookhound.Parsers.String: alphaNums :: Parser String
- Bookhound.Parsers.String: alphas :: Parser String
- Bookhound.Parsers.String: blankLine :: Parser String
- Bookhound.Parsers.String: blankLines :: Parser String
- Bookhound.Parsers.String: digits :: Parser String
- Bookhound.Parsers.String: letters :: Parser String
- Bookhound.Parsers.String: lowers :: Parser String
- Bookhound.Parsers.String: maybeWithinAngleBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: maybeWithinCurlyBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: maybeWithinDoubleQuotes :: Parser b -> Parser b
- Bookhound.Parsers.String: maybeWithinParens :: Parser b -> Parser b
- Bookhound.Parsers.String: maybeWithinQuotes :: Parser b -> Parser b
- Bookhound.Parsers.String: maybeWithinSquareBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: newLines :: Parser String
- Bookhound.Parsers.String: spaces :: Parser String
- Bookhound.Parsers.String: spacesOrTabs :: Parser String
- Bookhound.Parsers.String: spacing :: Parser String
- Bookhound.Parsers.String: string :: Parser String
- Bookhound.Parsers.String: tabs :: Parser String
- Bookhound.Parsers.String: uppers :: Parser String
- Bookhound.Parsers.String: withinAngleBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: withinCurlyBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: withinDoubleQuotes :: Parser b -> Parser b
- Bookhound.Parsers.String: withinParens :: Parser b -> Parser b
- Bookhound.Parsers.String: withinQuotes :: Parser b -> Parser b
- Bookhound.Parsers.String: withinSquareBrackets :: Parser b -> Parser b
- Bookhound.Parsers.String: word :: Parser String
- Bookhound.Utils.Applicative: extract :: Applicative m => m a1 -> m a2 -> m b -> m b
- Bookhound.Utils.Foldable: hasMultiple :: Foldable m => m a -> Bool
- Bookhound.Utils.Foldable: hasNone :: Foldable m => m a -> Bool
- Bookhound.Utils.Foldable: hasSome :: Foldable m => m a -> Bool
- Bookhound.Utils.String: class ToString a
- Bookhound.Utils.String: indent :: Int -> String -> String
- Bookhound.Utils.String: instance (Bookhound.Utils.String.ToString a, Data.Foldable.Foldable m) => Bookhound.Utils.String.ToString (m a)
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString Data.Text.Internal.Text
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString GHC.Num.Integer.Integer
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString GHC.Types.Char
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString GHC.Types.Double
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString GHC.Types.Float
- Bookhound.Utils.String: instance Bookhound.Utils.String.ToString GHC.Types.Int
- Bookhound.Utils.String: toString :: ToString a => a -> String
+ Bookhound.Parser: anyChar :: Parser Char
+ Bookhound.Parser: both :: Parser a -> Parser a -> Parser a
+ Bookhound.Parser: choice :: Foldable f => f (Parser a) -> Parser a
+ Bookhound.Parser: eof :: Parser ()
+ Bookhound.Parser: instance Control.Monad.Error.Class.MonadError Bookhound.Parser.ParseError Bookhound.Parser.Parser
+ Bookhound.Parser: instance GHC.Base.Alternative Bookhound.Parser.Parser
+ Bookhound.Parser: instance GHC.Base.MonadPlus Bookhound.Parser.Parser
+ Bookhound.Parser: instance GHC.Base.Monoid a => GHC.Base.Monoid (Bookhound.Parser.Parser a)
+ Bookhound.Parser: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Bookhound.Parser.Parser a)
+ Bookhound.Parser: lookAhead :: Parser a -> Parser a
+ Bookhound.Parser: mkParser :: (Input -> ParseResult a) -> Parser a
+ Bookhound.Parser: notFollowedBy :: Parser a -> Parser ()
+ Bookhound.Parser: satisfy :: (a -> Bool) -> Parser a -> Parser a
+ Bookhound.Parser: throwError :: MonadError e m => e -> m a
+ Bookhound.ParserCombinators: (</\>) :: Applicative f => f a -> f b -> f (a, b)
+ Bookhound.ParserCombinators: (<:>) :: Applicative f => f a -> f [a] -> f [a]
+ Bookhound.ParserCombinators: (||*) :: Parser Char -> Parser Text
+ Bookhound.ParserCombinators: (||+) :: Parser Char -> Parser Text
+ Bookhound.ParserCombinators: (||++) :: Parser Char -> Parser Text
+ Bookhound.ParserCombinators: (||?) :: Parser Char -> Parser Text
+ Bookhound.ParserCombinators: between :: Parser a -> Parser b -> Parser c -> Parser c
+ Bookhound.ParserCombinators: char :: Char -> Parser Char
+ Bookhound.ParserCombinators: instance Bookhound.ParserCombinators.IsMatch Data.Text.Internal.Text
+ Bookhound.ParserCombinators: many :: Parser a -> Parser [a]
+ Bookhound.ParserCombinators: manyEndBy :: forall a b. Parser a -> Parser b -> Parser [b]
+ Bookhound.ParserCombinators: manySepBy :: Parser a -> Parser b -> Parser [b]
+ Bookhound.ParserCombinators: maybeBetween :: Parser a -> Parser b -> Parser c -> Parser c
+ Bookhound.ParserCombinators: maybeSurroundedBy :: Parser a -> Parser b -> Parser b
+ Bookhound.ParserCombinators: multiple :: Parser a -> Parser [a]
+ Bookhound.ParserCombinators: multipleEndBy :: forall a b. Parser a -> Parser b -> Parser [b]
+ Bookhound.ParserCombinators: satisfy :: (a -> Bool) -> Parser a -> Parser a
+ Bookhound.ParserCombinators: some :: Parser a -> Parser [a]
+ Bookhound.ParserCombinators: someEndBy :: forall a b. Parser a -> Parser b -> Parser [b]
+ Bookhound.ParserCombinators: string :: Text -> Parser Text
+ Bookhound.ParserCombinators: surroundedBy :: Parser a -> Parser b -> Parser b
+ Bookhound.Parsers.Char: anyChar :: Parser Char
+ Bookhound.Parsers.Char: hexDigit :: Parser Char
+ Bookhound.Parsers.Char: octDigit :: Parser Char
+ Bookhound.Parsers.Text: alphaNums :: Parser Text
+ Bookhound.Parsers.Text: alphas :: Parser Text
+ Bookhound.Parsers.Text: betweenAngleBrackets :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenCurlyBrackets :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenDoubleQuotes :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenParens :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenQuotes :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenSpacing :: Parser b -> Parser b
+ Bookhound.Parsers.Text: betweenSquare :: Parser b -> Parser b
+ Bookhound.Parsers.Text: blankLine :: Parser Text
+ Bookhound.Parsers.Text: blankLines :: Parser Text
+ Bookhound.Parsers.Text: digits :: Parser Text
+ Bookhound.Parsers.Text: lowers :: Parser Text
+ Bookhound.Parsers.Text: maybeBetweenAngleBrackets :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenCurlyBrackets :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenDoubleQuotes :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenParens :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenQuotes :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenSpacing :: Parser b -> Parser b
+ Bookhound.Parsers.Text: maybeBetweenSquareBrackets :: Parser b -> Parser b
+ Bookhound.Parsers.Text: newLines :: Parser Text
+ Bookhound.Parsers.Text: spaces :: Parser Text
+ Bookhound.Parsers.Text: spacesOrTabs :: Parser Text
+ Bookhound.Parsers.Text: spacing :: Parser Text
+ Bookhound.Parsers.Text: string :: Parser Text
+ Bookhound.Parsers.Text: tabs :: Parser Text
+ Bookhound.Parsers.Text: uppers :: Parser Text
+ Bookhound.Parsers.Text: word :: Parser Text
+ Bookhound.Utils.List: hasMultiple :: [a] -> Bool
+ Bookhound.Utils.List: hasNone :: [a] -> Bool
+ Bookhound.Utils.List: hasSome :: [a] -> Bool
+ Bookhound.Utils.Text: class ToText a
+ Bookhound.Utils.Text: indent :: Int -> String -> String
+ Bookhound.Utils.Text: instance (Bookhound.Utils.Text.ToText a, Data.Foldable.Foldable f, GHC.Base.Functor f) => Bookhound.Utils.Text.ToText (f a)
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText Data.Text.Internal.Text
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText GHC.Num.Integer.Integer
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText GHC.Types.Char
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText GHC.Types.Double
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText GHC.Types.Float
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText GHC.Types.Int
+ Bookhound.Utils.Text: instance Bookhound.Utils.Text.ToText a => Bookhound.Utils.Text.ToText [a]
+ Bookhound.Utils.Text: toText :: ToText a => a -> Text
- Bookhound.Parser: ErrorAt :: String -> ParseError
+ Bookhound.Parser: ErrorAt :: Text -> ParseError
- Bookhound.Parser: allOf :: [Parser a] -> Parser a
+ Bookhound.Parser: allOf :: Foldable f => f (Parser a) -> Parser a
- Bookhound.Parser: andThen :: Parser String -> Parser a -> Parser a
+ Bookhound.Parser: andThen :: Parser Text -> Parser a -> Parser a
- Bookhound.Parser: anyOf :: [Parser a] -> Parser a
+ Bookhound.Parser: anyOf :: Foldable f => f (Parser a) -> Parser a
- Bookhound.Parser: withError :: String -> Parser a -> Parser a
+ Bookhound.Parser: withError :: Text -> Parser a -> Parser a
- Bookhound.Parser: withErrorN :: Int -> String -> Parser a -> Parser a
+ Bookhound.Parser: withErrorN :: Int -> Text -> Parser a -> Parser a
- Bookhound.ParserCombinators: (->>-) :: (ToString a, ToString b) => Parser a -> Parser b -> Parser String
+ Bookhound.ParserCombinators: (->>-) :: (ToText a, ToText b) => Parser a -> Parser b -> Parser Text
- Bookhound.ParserCombinators: (<?>) :: Parser a -> String -> Parser a
+ Bookhound.ParserCombinators: (<?>) :: Parser a -> Text -> Parser a
- Bookhound.Parsers.Number: hexInt :: Parser Integer
+ Bookhound.Parsers.Number: hexInt :: Parser Int
- Bookhound.Parsers.Number: int :: Parser Integer
+ Bookhound.Parsers.Number: int :: Parser Int
- Bookhound.Parsers.Number: negInt :: Parser Integer
+ Bookhound.Parsers.Number: negInt :: Parser Int
- Bookhound.Parsers.Number: octInt :: Parser Integer
+ Bookhound.Parsers.Number: octInt :: Parser Int
- Bookhound.Parsers.Number: posInt :: Parser Integer
+ Bookhound.Parsers.Number: posInt :: Parser Int
- Bookhound.Parsers.Number: unsignedInt :: Parser Integer
+ Bookhound.Parsers.Number: unsignedInt :: Parser Int

Files

bookhound.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.0.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack  name:           bookhound-version:        0.1.25.0+version:        0.1.26.0 synopsis:       Simple Parser Combinators description:    Please see the README on GitHub at <https://github.com/albertprz/bookhound#readme> category:       Parser Combinators@@ -32,13 +32,12 @@       Bookhound.Parsers.Collections       Bookhound.Parsers.DateTime       Bookhound.Parsers.Number-      Bookhound.Parsers.String-      Bookhound.Utils.Applicative+      Bookhound.Parsers.Text       Bookhound.Utils.DateTime       Bookhound.Utils.Foldable       Bookhound.Utils.List       Bookhound.Utils.Map-      Bookhound.Utils.String+      Bookhound.Utils.Text   other-modules:       Paths_bookhound   hs-source-dirs:@@ -47,40 +46,24 @@       LambdaCase       MultiWayIf       TupleSections-      PostfixOperators       BlockArguments+      PostfixOperators       RankNTypes-      ExplicitForAll       ScopedTypeVariables-      LiberalTypeSynonyms-      InstanceSigs-      FunctionalDependencies       DuplicateRecordFields       NamedFieldPuns       RecordWildCards-      ConstrainedClassMethods       MultiParamTypeClasses-      FlexibleContexts       FlexibleInstances       ApplicativeDo-      ParallelListComp-      MonadComprehensions-      GADTs-      TypeFamilies-      TypeFamilyDependencies-      DataKinds-      PolyKinds-      DeriveFunctor-      DeriveFoldable-      DeriveTraversable-      DeriveGeneric-      GeneralizedNewtypeDeriving+      OverloadedStrings   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wpartial-fields -Wincomplete-uni-patterns -Wredundant-constraints   build-depends:-      base >=4.7 && <5-    , containers >=0.6 && <1-    , text-    , time >=1.9 && <2+      base ==4.*+    , containers ==0.6.*+    , mtl ==2.*+    , text >=2.0 && <3+    , time ==1.*   default-language: Haskell2010  test-suite test@@ -99,44 +82,28 @@       LambdaCase       MultiWayIf       TupleSections-      PostfixOperators       BlockArguments+      PostfixOperators       RankNTypes-      ExplicitForAll       ScopedTypeVariables-      LiberalTypeSynonyms-      InstanceSigs-      FunctionalDependencies       DuplicateRecordFields       NamedFieldPuns       RecordWildCards-      ConstrainedClassMethods       MultiParamTypeClasses-      FlexibleContexts       FlexibleInstances       ApplicativeDo-      ParallelListComp-      MonadComprehensions-      GADTs-      TypeFamilies-      TypeFamilyDependencies-      DataKinds-      PolyKinds-      DeriveFunctor-      DeriveFoldable-      DeriveTraversable-      DeriveGeneric-      GeneralizedNewtypeDeriving-  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wpartial-fields -Wincomplete-uni-patterns -Wredundant-constraints -Wno-orphans+      OverloadedStrings+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wpartial-fields -Wincomplete-uni-patterns -Wredundant-constraints -Wno-type-defaults   build-tool-depends:       hspec-discover:hspec-discover   build-depends:       QuickCheck-    , base >=4.7 && <5+    , base ==4.*     , bookhound-    , containers >=0.6 && <1+    , containers ==0.6.*     , hspec+    , mtl ==2.*     , quickcheck-instances-    , text-    , time >=1.9 && <2+    , text >=2.0 && <3+    , time ==1.*   default-language: Haskell2010
src/Bookhound/Parser.hs view
@@ -1,15 +1,14 @@-module Bookhound.Parser (Parser(parse), ParseResult(..), ParseError(..), runParser, errorParser,-               andThen, exactly, isMatch, check, anyOf, allOf, char,-               withTransform, withError, withErrorN, except) where--import           Bookhound.Utils.Foldable (findJust)-import           Control.Applicative      (liftA2)-import           Data.Either              (fromRight)-import           Data.Set                 (Set)-import qualified Data.Set                 as Set-import           Data.Text                (Text, pack, uncons, unpack)+module Bookhound.Parser (Parser(parse), ParseResult(..), ParseError(..), mkParser, runParser, throwError, andThen, exactly, eof , lookAhead , notFollowedBy, both, choice, anyOf, allOf, anyChar, satisfy, withTransform, withError, withErrorN, except) where -type Input = Text+import           Bookhound.Utils.Foldable  (findJust)+import           Control.Applicative       (Alternative (..), liftA2)+import           Control.Monad             (MonadPlus)+import           Control.Monad.Error.Class (MonadError (..))+import           Data.Either               (fromRight)+import           Data.Set                  (Set)+import qualified Data.Set                  as Set+import           Data.Text                 (Text, unpack)+import qualified Data.Text                 as Text  data Parser a   = P@@ -18,26 +17,6 @@       , errors    :: Set (Int, ParseError)       } -data ParseResult a-  = Result Input a-  | Error ParseError-  deriving (Eq)--data ParseError-  = UnexpectedEof-  | ExpectedEof Input-  | UnexpectedChar Char-  | UnexpectedString String-  | NoMatch String-  | ErrorAt String-  deriving (Eq, Ord)---instance Functor ParseResult where-  fmap f (Result i a) = Result i (f a)-  fmap _ (Error pe)   = Error pe-- instance Functor Parser where   fmap f (P p t e) = applyTransformError t e $     mkParser (fmap f . p)@@ -45,138 +24,134 @@ instance Applicative Parser where   pure a      = mkParser (`Result` a)   liftA2 f (P p t e) mb@(P _ t' e') =-    applyTransformsErrors [t, t'] [e, e'] $ mkParser (\x ->+    applyTransformsErrors [t, t'] [e, e'] $ mkParser \x ->       case p x of         Result i a -> parse (f a <$> mb) i         Error pe   -> Error pe-    )  instance Monad Parser where   (>>=) (P p t e) f =-    applyTransformError t e $ mkParser (\x ->+    applyTransformError t e $ mkParser \x ->       case p x of         Result i a -> parse (f a) i         Error pe   -> Error pe-    ) +instance Semigroup a => Semigroup (Parser a) where+  (<>) = liftA2 (<>)++instance Monoid a => Monoid (Parser a) where+  mempty = pure mempty++instance Alternative Parser where+  (<|>) (P p t e) (P p' t' e') =+    applyTransformsErrors [ t, t' ] [ e, e' ] $+      mkParser+        \x -> case p x of+          Error _ -> p' x+          result  -> result+  empty = mkParser \i ->+    if Text.null i then+      Error UnexpectedEof+    else+      Error $ ExpectedEof i++instance MonadPlus Parser++instance MonadError ParseError Parser where+  throwError = mkParser . const . Error+  catchError p errFn = mkParser+        \x -> case parse p x of+          Error err -> parse (errFn err) x+          result    -> result++anyChar :: Parser Char+anyChar = mkParser $+   maybe (Error UnexpectedEof) (uncurry $ flip Result) . Text.uncons+ runParser :: Parser a -> Input -> Either [ParseError] a runParser p@(P _ _ e) i = toEither $ parse (exactly p) i   where     toEither = \case       Result _ a -> Right a-      Error pe   -> Left $ filter hasPriorityError       [pe] <>-                          (snd <$> reverse (Set.toList e))   <>-                          filter (not . hasPriorityError) [pe]--errorParser :: ParseError -> Parser a-errorParser = mkParser . const . Error+      Error pe   -> Left $ filter hasPriorityError [pe]+        <> (snd <$> reverse (Set.toList e))+        <> filter (not . hasPriorityError) [pe] -andThen :: Parser String -> Parser a -> Parser a+andThen :: Parser Text -> Parser a -> Parser a andThen p1 p2@(P _ t e) = applyTransformError t e $-  mkParser (\i -> parse p2 $ fromRight i $ pack <$> runParser p1 i)--char :: Parser Char-char = mkParser $-   maybe (Error UnexpectedEof) (\(ch, rest) -> Result rest ch) . uncons-+  mkParser (\i -> parse p2 $ fromRight i (runParser p1 i))  exactly :: Parser a -> Parser a-exactly (P p t e) = applyTransformError t e $-  mkParser (\x ->-    case p x of-      result@(Result i _) | i == mempty -> result-      Result i _                        -> Error $ ExpectedEof i-      err                               -> err-    )--anyOf :: [Parser a] -> Parser a-anyOf ps = anyOfHelper ps Nothing mempty--allOf :: [Parser a] -> Parser a-allOf ps = allOfHelper ps Nothing mempty---anyOfHelper :: [Parser a]-            -> (forall b. Maybe (Parser b -> Parser b))-            -> Set (Int, ParseError)-            -> Parser a-anyOfHelper [] _ _  = errorParser $ NoMatch "anyOf"-anyOfHelper [p] _ _ = p-anyOfHelper ((P p t e) : rest) t' e' =-  applyTransformsErrors [t, t'] [e, e'] $-    mkParser (\x ->-      case p x of-        Error _ -> parse (anyOfHelper rest t e) x-        result  -> result-      )+exactly p = p <* eof +eof :: Parser ()+eof = mkParser \i ->+    if i == mempty then+      Result i ()+    else+      Error $ ExpectedEof i -allOfHelper :: [Parser a]-            -> (forall b. Maybe (Parser b -> Parser b))-            -> Set (Int, ParseError)-            -> Parser a-allOfHelper [] _ _ = errorParser $ NoMatch "allOf"-allOfHelper [p] _ _ = p-allOfHelper ((P p t e) : rest) t' e' =-  applyTransformsErrors [t, t'] [e, e'] $-    mkParser (\x ->-      case p x of-        Result _ _ -> parse (allOfHelper rest t e) x+lookAhead :: Parser a -> Parser a+lookAhead (P p t e) =+  applyTransformError t e $+    mkParser+      \x -> case p x of+        Result _ a -> Result x a         err        -> err-      ) +notFollowedBy :: Parser a -> Parser ()+notFollowedBy (P p t e) =+  applyTransformError t e $+    mkParser+      \x -> case p x of+        Result _ _ -> Error UnexpectedEof+        _          -> Result x () -isMatch :: (Char -> Char -> Bool) -> Parser Char -> Char -> Parser Char-isMatch cond parser c1 =-  do c2 <- parser-     if cond c1 c2-       then pure c2-       else errorParser $ UnexpectedChar c2+choice :: Foldable f => f (Parser a) -> Parser a+choice = anyOf -check :: String -> (a -> Bool) -> Parser a -> Parser a-check condName cond parser =-  do c2 <- parser-     if cond c2-       then pure c2-       else errorParser $ NoMatch condName+anyOf :: Foldable f => f (Parser a) -> Parser a+anyOf = foldl (<|>) empty +allOf :: Foldable f => f (Parser a) -> Parser a+allOf = foldl both (pure undefined) +both :: Parser a -> Parser a -> Parser a+both (P p t e) (P p' t' e') =+  applyTransformsErrors [ t, t' ] [ e, e' ] $+    mkParser+      \x -> case p x of+        Result _ _ -> p' x+        err        -> err+ except :: Parser a -> Parser a -> Parser a except (P p t e) (P p' _ _) = applyTransformError t e $ mkParser (   \x -> case p' x of-    Result _ _ -> Error $ NoMatch "except"+    Result _ _ -> Error $ ExpectedEof x     Error _    -> p x   ) -withError :: String -> Parser a -> Parser a+satisfy :: (a -> Bool) -> Parser a -> Parser a+satisfy cond ma = do+  c2 <- ma+  if cond c2 then+    pure c2+  else+    empty++withError :: Text -> Parser a -> Parser a withError = withErrorN 0 -withErrorN :: Int -> String -> Parser a -> Parser a+withErrorN :: Int -> Text -> Parser a -> Parser a withErrorN n str = applyError . Set.singleton $ (n, ErrorAt str)   withTransform :: (forall b. Parser b -> Parser b) -> Parser a -> Parser a withTransform t = applyTransform $ Just t -instance Show a => Show (ParseResult a) where-  show (Result i a) = "Pending: " <> " >" <> unpack i <> "< "-                                  <> "\n\nResult: \n" <> show a-  show (Error err)  = show err -instance Show ParseError where-  show UnexpectedEof        = "Unexpected end of stream"-  show (ExpectedEof i)      = "Expected end of stream, but got "-                               <> ">" <> unpack i <> "<"-  show (UnexpectedChar c)   = "Unexpected char: "-                               <> "[" <> show c <> "]"-  show (UnexpectedString s) = "Unexpected string: "-                               <> "[" <> s <> "]"-  show (NoMatch s)          = "Did not match condition: " <> s-  show (ErrorAt s)          = "Error at " <> s  -- applyTransformsErrors :: (forall b. [Maybe (Parser b -> Parser b)])                       -> [Set (Int, ParseError)]                       -> Parser a@@ -206,3 +181,32 @@ hasPriorityError :: ParseError -> Bool hasPriorityError (ErrorAt _) = True hasPriorityError _           = False++data ParseResult a+  = Result Input a+  | Error ParseError+  deriving (Eq)++instance Functor ParseResult where+  fmap f (Result i a) = Result i (f a)+  fmap _ (Error pe)   = Error pe+++instance Show a => Show (ParseResult a) where+  show (Result i a) = "Pending: " <> " >" <> unpack i <> "< "+                                  <> "\n\nResult: \n" <> show a+  show (Error err)  = show err++data ParseError+  = UnexpectedEof+  | ExpectedEof Input+  | ErrorAt Text+  deriving (Eq, Ord)++instance Show ParseError where+  show UnexpectedEof        = "Unexpected end of stream"+  show (ExpectedEof i)      = "Expected end of stream, but got "+                               <> ">" <> unpack i <> "<"+  show (ErrorAt s)          = "Error at " <> unpack s++type Input = Text
src/Bookhound/ParserCombinators.hs view
@@ -1,24 +1,17 @@-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}-{-# HLINT ignore "Use optional" #-}--module Bookhound.ParserCombinators (IsMatch(..), satisfies, contains, notContains,-                          containsAnyOf, containsNoneOf,-                          times, maybeTimes, anyTimes, someTimes, multipleTimes,-                          within, maybeWithin, withinBoth, maybeWithinBoth,-                          anySepBy, someSepBy, multipleSepBy, sepByOps, sepByOp,-                          (<|>), (<?>), (<#>), (->>-), (|?), (|*), (|+), (|++))  where--import Bookhound.Parser            (Parser, allOf, anyOf, char, check, except,-                                    isMatch, withError)-import Bookhound.Utils.Applicative (extract)-import Bookhound.Utils.Foldable    (hasMultiple, hasSome)-import Bookhound.Utils.String      (ToString (..))+module Bookhound.ParserCombinators (IsMatch(..), satisfy, char, string, times, many, some, multiple,+                          between, maybeBetween, surroundedBy, maybeSurroundedBy,+                          manySepBy, someSepBy, multipleSepBy, sepByOps, sepByOp, manyEndBy, someEndBy, multipleEndBy,+                          (<?>), (<#>), (</\>), (<:>), (->>-), (|?), (|*), (|+), (|++), (||?), (||*), (||+), (||++))  where+import Bookhound.Parser (Parser, allOf, anyChar, anyOf, except, satisfy,+                         withError) -import Data.List (isInfixOf)+import Bookhound.Utils.List (hasMultiple, hasSome)+import Bookhound.Utils.Text (ToText (..))+import Control.Applicative  (liftA2, optional, (<|>)) -import           Data.Bifunctor (Bifunctor (first))-import qualified Data.Foldable  as Foldable+import qualified Data.Foldable as Foldable+import           Data.Text     (Text, pack, unpack)+import qualified Data.Text     as Text   class IsMatch a where@@ -31,124 +24,155 @@   oneOf xs  = anyOf $ is <$> xs   noneOf xs = allOf $ isNot <$> xs - instance   IsMatch Char where-  is      = isMatch (==) char-  isNot   = isMatch (/=) char-  inverse = except char+  is      = isMatch (==) anyChar+  isNot   = isMatch (/=) anyChar+  inverse = except anyChar  instance   IsMatch String where-  is      = traverse (isMatch (==) char)-  isNot   = traverse (isMatch (/=) char)-  inverse = except (char |*)+  is      = traverse is+  isNot   = traverse is+  inverse = except (anyChar |*) -instance {-# OVERLAPPABLE #-} (Num a, Read a, Show a) => IsMatch a where-  is n      = read <$> (is . show) n-  isNot n   = read <$> (isNot . show) n-  inverse p = read <$> inverse (show <$> p)+instance   IsMatch Text where+  is      = fmap pack . is . unpack+  isNot   = fmap pack . is . unpack+  inverse = except (anyChar ||*)  --- Condition combinators-satisfies :: (a -> Bool) -> Parser a -> Parser a-satisfies = check "satisfies"--contains :: Eq a => [a] -> Parser [a] -> Parser [a]-contains val = check "contains" (isInfixOf val)--notContains :: Eq a => [a] -> Parser [a] -> Parser [a]-notContains val = check "notContains" (isInfixOf val)--containsAnyOf :: (Foldable t, Eq a) => t [a] -> Parser [a] -> Parser [a]-containsAnyOf x y = foldr contains y x+isMatch :: (Char -> Char -> Bool) -> Parser Char -> Char -> Parser Char+isMatch cond p c1 = satisfy (cond c1) p -containsNoneOf :: (Foldable t, Eq a) => t [a] -> Parser [a] -> Parser [a]-containsNoneOf x y = foldr notContains y x+char :: Char -> Parser Char+char = is +string :: Text -> Parser Text+string = is   -- Frequency combinators-times :: Int -> Parser a  -> Parser [a]-times n p = sequence $ p <$ [1 .. n]---maybeTimes :: Parser a -> Parser (Maybe a)-maybeTimes p = Just <$> p <|> pure Nothing+many :: Parser a -> Parser [a]+many p = (p >>= \x -> (x :) <$> many p)+  <|> pure [] -anyTimes :: Parser a -> Parser [a]-anyTimes p = (p >>= \x -> (x :) <$> anyTimes p) <|> pure []+some :: Parser a -> Parser [a]+some = satisfy hasSome . many -someTimes :: Parser a -> Parser [a]-someTimes = check "someTimes" hasSome . anyTimes+multiple :: Parser a -> Parser [a]+multiple = satisfy hasMultiple . many -multipleTimes :: Parser a -> Parser [a]-multipleTimes = check "multipleTimes" hasMultiple . anyTimes+times :: Int -> Parser a  -> Parser [a]+times n p+  | n < 1 = pure []+  | otherwise = sequence $ p <$ [1 .. n]  --- Within combinators-withinBoth :: Parser a -> Parser b -> Parser c -> Parser c-withinBoth = extract+-- Between combinators+between :: Parser a -> Parser b -> Parser c -> Parser c+between start end p = start *> p <* end -maybeWithinBoth :: Parser a -> Parser b -> Parser c -> Parser c-maybeWithinBoth p1 p2 = withinBoth (p1 |?) (p2 |?)+maybeBetween :: Parser a -> Parser b -> Parser c -> Parser c+maybeBetween p1 p2 = between (p1 |?) (p2 |?) -within :: Parser a -> Parser b -> Parser b-within p = withinBoth p p+surroundedBy :: Parser a -> Parser b -> Parser b+surroundedBy p = between p p -maybeWithin :: Parser a -> Parser b -> Parser b-maybeWithin p = within (p |?)+maybeSurroundedBy :: Parser a -> Parser b -> Parser b+maybeSurroundedBy p = surroundedBy (p |?)  --- Separated by combinators+-- Sep by combinators sepBy :: (Parser b -> Parser (Maybe b)) -> (Parser b -> Parser [b])                 -> Parser a -> Parser b -> Parser [b] sepBy freq1 freq2 sep p = (<>) <$> (Foldable.toList <$> freq1 p)                                <*> freq2 (sep *> p) -anySepBy :: Parser a -> Parser b -> Parser [b]-anySepBy = sepBy (|?) (|*)+manySepBy :: Parser a -> Parser b -> Parser [b]+manySepBy = sepBy optional many  someSepBy :: Parser a -> Parser b -> Parser [b]-someSepBy = sepBy (fmap Just) (|*)+someSepBy = sepBy (fmap Just) many  multipleSepBy :: Parser a -> Parser b -> Parser [b]-multipleSepBy = sepBy (fmap Just) (|+)+multipleSepBy = sepBy (fmap Just) some  sepByOps :: Parser a -> Parser b -> Parser ([a], [b]) sepByOps sep p = do x <-  p-                    y <- (((,) <$> sep <*> p) |+)-                    pure (fst <$> y, x : (snd <$> y))+                    y <- (|+) (sep </\> p)+                    pure (fmap fst y, x : fmap snd y)  sepByOp :: Parser a -> Parser b -> Parser (a, [b])-sepByOp sep p = first head <$> sepByOps sep p+sepByOp sepP p = do+  x1 <- p+  sep <- sepP+  x2 <- p+  xs <- (|*) (sepP *> p)+  pure (sep, x1 : x2 : xs) +-- End by combinators+endBy+  :: forall a b+   . (Parser b -> Parser (Maybe b))+  -> (Parser b -> Parser [b])+  -> Parser a+  -> Parser b+  -> Parser [b]+endBy freq1 freq2 sep p =+  sepBy freq1 freq2 sep p <* sep --- Parser Binary Operators-infixl 3 <|>-(<|>) :: Parser a -> Parser a -> Parser a-(<|>) p1 p2 = anyOf [p1, p2]+manyEndBy :: forall a b. Parser a -> Parser b -> Parser [ b]+manyEndBy = endBy optional many +someEndBy :: forall a b. Parser a -> Parser b -> Parser [ b]+someEndBy = endBy (fmap Just) many++multipleEndBy :: forall a b. Parser a -> Parser b -> Parser [ b]+multipleEndBy = endBy (fmap Just) some+++-- Parser Binary Operators infixl 6 <#> (<#>) :: Parser a -> Int -> Parser [a] (<#>) = flip times  infixl 6 <?>-(<?>) :: Parser a -> String -> Parser a+(<?>) :: Parser a -> Text -> Parser a (<?>) = flip withError  infixl 6 ->>--(->>-) :: (ToString a, ToString b) => Parser a -> Parser b -> Parser String-(->>-) p1 p2 = (<>) <$> (toString <$> p1)-                 <*> (toString <$> p2)+(->>-) :: (ToText a, ToText b) => Parser a -> Parser b -> Parser Text+(->>-) p1 p2 = (<>) <$> fmap toText p1+                 <*> fmap toText p2 +-- Apply Binary Operators+infixl 6 </\>+(</\>) :: Applicative f => f a -> f b -> f (a, b)+(</\>) = liftA2 (,) +infixl 6 <:>+(<:>) :: Applicative f => f a -> f [a] -> f [a]+(<:>) = liftA2 (:)+ -- Parser Unary Operators (|?) :: Parser a -> Parser (Maybe a)-(|?) = maybeTimes+(|?) = optional  (|*) :: Parser a -> Parser [a]-(|*) = anyTimes+(|*) = many  (|+) :: Parser a -> Parser [a]-(|+) = someTimes+(|+) = some  (|++) :: Parser a -> Parser [a]-(|++) = multipleTimes+(|++) = multiple++(||?) :: Parser Char -> Parser Text+(||?) = fmap (maybe mempty Text.singleton) . optional++(||*) :: Parser Char -> Parser Text+(||*) = fmap pack . many++(||+) :: Parser Char -> Parser Text+(||+) = fmap pack . some++(||++) :: Parser Char -> Parser Text+(||++) = fmap pack . multiple
src/Bookhound/Parsers/Char.hs view
@@ -1,28 +1,34 @@-module Bookhound.Parsers.Char where--import Bookhound.ParserCombinators (IsMatch (..), (<|>))+module Bookhound.Parsers.Char (module AnyChar, digit, hexDigit, octDigit, upper, lower, alpha, alphaNum, space, tab, newLine, spaceOrTab, whiteSpace, comma, dot, colon, quote, doubleQuote, dash, plus, equal, underscore, hashTag, question, openParens, closeParens, openSquare, closeSquare, openCurly, closeCurly, openAngle, closeAngle)  where -import Bookhound.Parser (Parser)+import qualified Bookhound.Parser            as AnyChar (anyChar)+import qualified Bookhound.Parser            as Parser+import           Bookhound.ParserCombinators (IsMatch (..)) +import Bookhound.Parser    (Parser, anyChar)+import Control.Applicative+import Data.Char           (isAsciiLower, isAsciiUpper, isDigit, isHexDigit,+                            isOctDigit)  digit :: Parser Char-digit = oneOf ['0' .. '9']+digit = satisfy isDigit +hexDigit :: Parser Char+hexDigit = satisfy isHexDigit++octDigit :: Parser Char+octDigit = satisfy isOctDigit+ upper :: Parser Char-upper = oneOf ['A' .. 'Z']+upper = satisfy isAsciiUpper  lower :: Parser Char-lower = oneOf ['a' .. 'z']--letter :: Parser Char-letter = upper <|> lower+lower = satisfy isAsciiLower  alpha :: Parser Char-alpha = letter+alpha = satisfy isAlpha  alphaNum :: Parser Char-alphaNum = alpha <|> digit-+alphaNum = satisfy isAlphaNum   space :: Parser Char@@ -98,3 +104,13 @@  closeAngle :: Parser Char closeAngle = is '>'+++isAlpha :: Char -> Bool+isAlpha x = isAsciiLower x || isAsciiUpper x++isAlphaNum :: Char -> Bool+isAlphaNum x = isAlpha x || isDigit x++satisfy :: (Char -> Bool) -> Parser Char+satisfy = flip Parser.satisfy anyChar
src/Bookhound/Parsers/Collections.hs view
@@ -1,21 +1,21 @@ module Bookhound.Parsers.Collections (collOf, listOf, tupleOf, mapOf) where -import Bookhound.Parser            (Parser, withErrorN)-import Bookhound.ParserCombinators (anySepBy, maybeWithin, satisfies)+import Bookhound.Parser            (Parser, satisfy, withErrorN)+import Bookhound.ParserCombinators (manySepBy) import Bookhound.Parsers.Char      (closeCurly, closeParens, closeSquare, comma,                                     openCurly, openParens, openSquare)-import Bookhound.Parsers.String    (spacing)+import Bookhound.Parsers.Text      (maybeBetweenSpacing) -import           Bookhound.Utils.Foldable (hasMultiple)-import           Data.Map                 (Map)-import qualified Data.Map                 as Map+import           Bookhound.Utils.List (hasMultiple)+import           Data.Map             (Map)+import qualified Data.Map             as Map   collOf :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d] collOf start end sep elemParser =   start *> elemsParser <* end     where-      elemsParser = anySepBy sep $ maybeWithin spacing elemParser+      elemsParser = manySepBy sep $ maybeBetweenSpacing elemParser   listOf :: Parser a -> Parser [a]@@ -25,7 +25,7 @@  tupleOf :: Parser a -> Parser [a] tupleOf = withErrorN (-1) "Tuple"-  . satisfies hasMultiple+  . satisfy hasMultiple   . collOf openParens closeParens comma  @@ -33,4 +33,4 @@ mapOf sep p1 p2 = withErrorN (-1) "Map" $   Map.fromList <$> collOf openCurly closeCurly comma mapEntry     where-      mapEntry = (,) <$> p1 <* maybeWithin spacing sep <*> p2+      mapEntry = (,) <$> p1 <* maybeBetweenSpacing sep <*> p2
src/Bookhound/Parsers/DateTime.hs view
@@ -1,19 +1,19 @@ module Bookhound.Parsers.DateTime (date, time, timeZoneOffset, localDateTime, offsetDateTime, dateTime, year, day, month, hour, minute, second) where -import Bookhound.Parser            (Parser, check, withErrorN)-import Bookhound.ParserCombinators (IsMatch (..), within, (<#>), (<|>), (|+),+import Bookhound.Parser            (Parser, satisfy, withErrorN)+import Bookhound.ParserCombinators (IsMatch (..), surroundedBy, (<#>), (|+),                                     (|?)) import Bookhound.Parsers.Char      (colon, dash, digit, dot, plus)+import Control.Applicative  import Data.Maybe (fromMaybe) import Data.Time  (Day, LocalTime (..), TimeOfDay (..), TimeZone,                    ZonedTime (..), fromGregorian, minutesToTimeZone)  - date :: Parser Day date = withErrorN (-1) "Date" $-  fromGregorian <$> year <*> within dash month <*> day+  fromGregorian <$> year <*> surroundedBy dash month <*> day   time :: Parser TimeOfDay@@ -54,22 +54,22 @@ year = read <$> digit <#> 4  day :: Parser Int-day = check "Day" (range 1 31) $ read <$> digit <#> 2+day = withErrorN (-1) "Day" $ satisfy (range 1 31) $ read <$> digit <#> 2  month :: Parser Int-month = check "Month" (range 1 12) $ read <$> digit <#> 2+month = withErrorN (-1) "Month" $ satisfy (range 1 12) $ read <$> digit <#> 2  hour :: Parser Int-hour = check "Hour" (range 0 23) $ read <$> digit <#> 2+hour = withErrorN (-1) "Hour" $ satisfy (range 0 23) $ read <$> digit <#> 2  minute :: Parser Int-minute = check "Minute" (range 0 59) $ read <$> digit <#> 2+minute = withErrorN (-1) "Minute" $ satisfy (range 0 59) $ read <$> digit <#> 2  second :: Parser Int-second = check "Second" (range 0 59) $ read <$> digit <#> 2+second = withErrorN (-1) "Second" $ satisfy (range 0 59) $ read <$> digit <#> 2  secondDecimals :: Parser String-secondDecimals = check "Pico Seconds" ((<= 12) . length) (digit |+)+secondDecimals = withErrorN (-1) "Pico Seconds" $ satisfy ((<= 12) . length) (digit |+)   
src/Bookhound/Parsers/Number.hs view
@@ -1,52 +1,45 @@-module Bookhound.Parsers.Number (int, double, posInt, negInt, unsignedInt, hexInt, octInt, intLike) where+module Bookhound.Parsers.Number (int, double, posInt, negInt, unsignedInt, hexInt, octInt) where -import Bookhound.Parser            (ParseError (..), Parser, errorParser,-                                    withErrorN)-import Bookhound.ParserCombinators (IsMatch (..), (->>-), (<|>), (|+), (|?))+import Bookhound.Parser            (Parser, withErrorN)+import Bookhound.ParserCombinators (IsMatch (..), string, (->>-), (|?), (||+),+                                    (||?)) import Bookhound.Parsers.Char      (dash, digit, dot, plus)+import Control.Applicative+import Data.Text                   (Text, unpack)  -hexInt :: Parser Integer-hexInt = withErrorN (-1) "Hex Int"- $ read <$> (is "0x" ->>--             ((digit <|> oneOf ['A' .. 'F'] <|> oneOf ['a' .. 'f']) |+))+hexInt :: Parser Int+hexInt = withErrorN (-1) "Hex Int" $ readInt+  <$> (string "0x" ->>- ((digit <|> oneOf ['A' .. 'F'] <|> oneOf ['a' .. 'f']) ||+)) -octInt :: Parser Integer-octInt = withErrorN (-1) "Oct Int"-  $ read <$> (is "0o" ->>- (oneOf ['0' .. '7'] |+))+octInt :: Parser Int+octInt = withErrorN (-1) "Oct Int" $ readInt+  <$> (string "0o" ->>- (oneOf ['0' .. '7'] ||+)) -unsignedInt :: Parser Integer-unsignedInt = withErrorN (-1) "Unsigned Int"-  $ read <$> (digit |+)+unsignedInt :: Parser Int+unsignedInt = withErrorN (-1) "Unsigned Int" $ readInt+  <$> (digit ||+) -posInt :: Parser Integer-posInt = withErrorN (-1) "Positive Int"-  $ read <$> ((plus |?) *> (digit |+))+posInt :: Parser Int+posInt = withErrorN (-1) "Positive Int" $ readInt+  <$> ((plus ||?) *> (digit ||+)) -negInt :: Parser Integer-negInt = withErrorN (-1) "Negative Int"-  $ read <$> dash ->>- (digit |+)+negInt :: Parser Int+negInt = withErrorN (-1) "Negative Int" $ readInt+  <$> dash ->>- (digit ||+) -int :: Parser Integer-int = withErrorN (-1) "Int"-  $ negInt <|> posInt+int :: Parser Int+int = withErrorN (-1) "Int" $ negInt <|> posInt -intLike :: Parser Integer-intLike = parser <|> int+double :: Parser Double+double = withErrorN (-1) "Double" $ readDouble+  <$> int ->>- (decimals ->>- (expn |?) <|> expn)   where-    parser = do n1      <- show <$> int-                n2      <- show <$> (dot *> unsignedInt)-                expNum  <- oneOf ['e', 'E'] *> int--                if length n1 + length n2 <= fromInteger expNum then-                  pure . read $ n1 <> "." <> n2 <> "E" <> show expNum-                else-                  errorParser $ NoMatch "Int Like"-+  decimals = dot ->>- (digit ||+)+  expn      = oneOf ['e', 'E'] ->>- int -double :: Parser Double-double = withErrorN (-1) "Double"-  $ read <$> (dash |?) ->>- posInt ->>- (decimals |?) ->>- (expn |?) where+readInt :: Text -> Int+readInt = read . unpack -  decimals = dot ->>- (digit |+)-  expn      = oneOf ['e', 'E'] ->>- int+readDouble :: Text -> Double+readDouble = read . unpack
− src/Bookhound/Parsers/String.hs
@@ -1,100 +0,0 @@-module Bookhound.Parsers.String where--import Bookhound.Parser            (Parser, char)-import Bookhound.ParserCombinators (IsMatch (..), maybeWithin, maybeWithinBoth,-                                    within, withinBoth, (->>-), (|*), (|+),-                                    (|?))-import Bookhound.Parsers.Char      (alpha, alphaNum, closeAngle, closeCurly,-                                    closeParens, closeSquare, digit,-                                    doubleQuote, letter, lower, newLine,-                                    openAngle, openCurly, openParens,-                                    openSquare, quote, space, spaceOrTab, tab,-                                    upper, whiteSpace)---string :: Parser String-string = (char |*)--word :: Parser String-word = (inverse whiteSpace |+)--digits :: Parser String-digits = (digit |+)--uppers :: Parser String-uppers = (upper |+)--lowers :: Parser String-lowers = (lower |+)--letters :: Parser String-letters = (letter |+)--alphas :: Parser String-alphas = (alpha |+)--alphaNums :: Parser String-alphaNums = (alphaNum |+)----spaces :: Parser String-spaces = (space |+)--tabs :: Parser String-tabs = (tab |+)--newLines :: Parser String-newLines = (newLine |+)--spacesOrTabs :: Parser String-spacesOrTabs = (spaceOrTab |+)--spacing :: Parser String-spacing = (whiteSpace |+)--blankLine :: Parser String-blankLine = (spacesOrTabs |?) ->>- newLine--blankLines :: Parser String-blankLines = mconcat <$> (blankLine |+)----withinQuotes :: Parser b -> Parser b-withinQuotes = within quote--withinDoubleQuotes :: Parser b -> Parser b-withinDoubleQuotes = within doubleQuote--withinParens :: Parser b -> Parser b-withinParens = withinBoth openParens closeParens--withinSquareBrackets :: Parser b -> Parser b-withinSquareBrackets = withinBoth openSquare closeSquare--withinCurlyBrackets :: Parser b -> Parser b-withinCurlyBrackets = withinBoth openCurly closeCurly--withinAngleBrackets :: Parser b -> Parser b-withinAngleBrackets = withinBoth openAngle closeAngle----maybeWithinQuotes :: Parser b -> Parser b-maybeWithinQuotes = maybeWithin quote--maybeWithinDoubleQuotes :: Parser b -> Parser b-maybeWithinDoubleQuotes = maybeWithin doubleQuote--maybeWithinParens :: Parser b -> Parser b-maybeWithinParens = maybeWithinBoth openParens closeParens--maybeWithinSquareBrackets :: Parser b -> Parser b-maybeWithinSquareBrackets = maybeWithinBoth openSquare closeSquare--maybeWithinCurlyBrackets :: Parser b -> Parser b-maybeWithinCurlyBrackets = maybeWithinBoth openCurly closeCurly--maybeWithinAngleBrackets :: Parser b -> Parser b-maybeWithinAngleBrackets = maybeWithinBoth openAngle closeAngle
+ src/Bookhound/Parsers/Text.hs view
@@ -0,0 +1,107 @@+module Bookhound.Parsers.Text where++import           Bookhound.Parser            (Parser, anyChar)+import           Bookhound.ParserCombinators (IsMatch (..), between,+                                              maybeBetween, maybeSurroundedBy,+                                              surroundedBy, (->>-), (|+), (|?),+                                              (||*), (||+))+import           Bookhound.Parsers.Char      (alpha, alphaNum, closeAngle,+                                              closeCurly, closeParens,+                                              closeSquare, digit, doubleQuote,+                                              lower, newLine, openAngle,+                                              openCurly, openParens, openSquare,+                                              quote, space, spaceOrTab, tab,+                                              upper, whiteSpace)+import           Data.Text                   (Text)+import qualified Data.Text                   as Text+++string :: Parser Text+string = (anyChar ||*)++word :: Parser Text+word = (inverse whiteSpace ||+)++digits :: Parser Text+digits = (digit ||+)++uppers :: Parser Text+uppers = (upper ||+)++lowers :: Parser Text+lowers = (lower ||+)++alphas :: Parser Text+alphas = (alpha ||+)++alphaNums :: Parser Text+alphaNums = (alphaNum ||+)++++spaces :: Parser Text+spaces = (space ||+)++tabs :: Parser Text+tabs = (tab ||+)++newLines :: Parser Text+newLines = (newLine ||+)++spacesOrTabs :: Parser Text+spacesOrTabs = (spaceOrTab ||+)++spacing :: Parser Text+spacing = (whiteSpace ||+)++blankLine :: Parser Text+blankLine = (spacesOrTabs |?) ->>- newLine++blankLines :: Parser Text+blankLines = fmap Text.concat (blankLine |+)++++betweenQuotes :: Parser b -> Parser b+betweenQuotes = surroundedBy quote++betweenDoubleQuotes :: Parser b -> Parser b+betweenDoubleQuotes = surroundedBy doubleQuote++betweenSpacing :: Parser b -> Parser b+betweenSpacing = surroundedBy spacing++betweenParens :: Parser b -> Parser b+betweenParens = between openParens closeParens++betweenSquare :: Parser b -> Parser b+betweenSquare = between openSquare closeSquare++betweenCurlyBrackets :: Parser b -> Parser b+betweenCurlyBrackets = between openCurly closeCurly++betweenAngleBrackets :: Parser b -> Parser b+betweenAngleBrackets = between openAngle closeAngle++++maybeBetweenQuotes :: Parser b -> Parser b+maybeBetweenQuotes = maybeSurroundedBy quote++maybeBetweenDoubleQuotes :: Parser b -> Parser b+maybeBetweenDoubleQuotes = maybeSurroundedBy doubleQuote++maybeBetweenSpacing :: Parser b -> Parser b+maybeBetweenSpacing = maybeSurroundedBy spacing++maybeBetweenParens :: Parser b -> Parser b+maybeBetweenParens = maybeBetween openParens closeParens++maybeBetweenSquareBrackets :: Parser b -> Parser b+maybeBetweenSquareBrackets = maybeBetween openSquare closeSquare++maybeBetweenCurlyBrackets :: Parser b -> Parser b+maybeBetweenCurlyBrackets = maybeBetween openCurly closeCurly++maybeBetweenAngleBrackets :: Parser b -> Parser b+maybeBetweenAngleBrackets = maybeBetween openAngle closeAngle
− src/Bookhound/Utils/Applicative.hs
@@ -1,5 +0,0 @@-module Bookhound.Utils.Applicative where---extract :: Applicative m => m a1 -> m a2 -> m b -> m b-extract start end inner = start *> inner <* end
src/Bookhound/Utils/Foldable.hs view
@@ -1,20 +1,10 @@ module Bookhound.Utils.Foldable where -import Bookhound.Utils.String (indent)-import Control.Monad          (join)-import Data.Foldable          as Foldable (Foldable (toList), find)-import Data.List              (intercalate)-import Data.Maybe             (isJust)---hasNone :: Foldable m => m a -> Bool-hasNone = null--hasSome :: Foldable m => m a -> Bool-hasSome = not . hasNone--hasMultiple :: Foldable m => m a -> Bool-hasMultiple xs = all hasSome $ [id, tail] <*> [toList xs]+import Bookhound.Utils.Text (indent)+import Control.Monad        (join)+import Data.Foldable        as Foldable (Foldable (toList), find)+import Data.List            (intercalate)+import Data.Maybe           (isJust)   stringify :: Foldable m => String -> String -> String -> Int -> m String -> String
src/Bookhound/Utils/List.hs view
@@ -1,5 +1,16 @@ module Bookhound.Utils.List where +hasNone ::  [a] -> Bool+hasNone (_ : _) = False+hasNone _       = True++hasSome :: [a] -> Bool+hasSome (_ : _) = True+hasSome _       = False++hasMultiple :: [a] -> Bool+hasMultiple (_ : _ : _) = True+hasMultiple _           = False  headSafe :: [a] -> Maybe a headSafe (x: _) = Just x
− src/Bookhound/Utils/String.hs
@@ -1,36 +0,0 @@-module Bookhound.Utils.String where--import Data.List (intercalate)-import Data.Text (Text, unpack)---class ToString a where-  toString :: a -> String--instance ToString Char where-  toString = pure--instance ToString Int where-  toString = show--instance ToString Text where-  toString = unpack--instance ToString Integer where-  toString = show--instance ToString Float where-  toString = show--instance ToString Double where-  toString = show--instance (ToString a, Foldable m) => ToString (m a) where-  toString = concatMap toString----indent :: Int -> String -> String-indent n str = intercalate "\n" $ indentLine <$> lines str-  where-    indentLine = (concat (replicate n " ") <>)
+ src/Bookhound/Utils/Text.hs view
@@ -0,0 +1,40 @@+module Bookhound.Utils.Text where++import qualified Data.Foldable as Foldable+import           Data.List     (intercalate)+import           Data.Text     (Text, pack)+import qualified Data.Text     as Text+++class ToText a where+  toText :: a -> Text++instance ToText Char where+  toText = Text.singleton++instance ToText Int where+  toText = pack . show++instance ToText Text where+  toText = id++instance ToText Integer where+  toText = pack . show++instance ToText Float where+  toText = pack .show++instance ToText Double where+  toText = pack . show++instance ToText a => ToText [a] where+  toText = Text.concat . fmap toText++instance (ToText a, Foldable f, Functor f) => ToText (f a) where+  toText = Text.concat . Foldable.toList . fmap toText+++indent :: Int -> String -> String+indent n str = intercalate "\n" $ indentLine <$> lines str+  where+    indentLine = (concat (replicate n " ") <>)
test/Bookhound/ParserCombinatorsSpec.hs view
@@ -7,9 +7,11 @@ import           Bookhound.Parser import           Bookhound.ParserCombinators import           Bookhound.Utils.List        (headSafe)+import           Control.Applicative         (optional) import qualified Data.Foldable               as Foldable-import           Data.Text                   (Text, unpack)+import           Data.Text                   (Text, pack, unpack) import qualified Data.Text                   as Text+import           Test.QuickCheck.Property    ((===))  spec :: Spec spec = do@@ -17,114 +19,108 @@   describe "times" $      prop "applies a parser n times sequentially" $-      \x n -> parse (times n char) x-          `shouldBe`-            if length (unpack x) >= n then+      \x n -> parse (times n anyChar) x+           ===+            if Text.length x >= n then                Result (Text.drop n x) (unpack $ Text.take n x)             else               Error UnexpectedEof -  describe "maybeTimes" $+  describe "optional" $      prop "applies a parser 1 or 0 times" $-      \x -> parse (maybeTimes char) x-          `shouldBe`-           headSafe <$> parseTimes char [0, 1] x+      \x -> parse (optional anyChar) x+           ===+           (headSafe <$> parseTimes anyChar [0, 1] x) -  describe "anyTimes" $+  describe "many" $      prop "applies a parser any number of times" $-      \x -> parse (anyTimes char) x-          `shouldBe`-           parseTimes char [0 .. Text.length x] x+      \x -> parse (many anyChar) x+           ===+           parseTimes anyChar [0 .. Text.length x + 10] x  -  describe "someTimes" $+  describe "some" $      prop "applies a parser at least once" $-      \x -> parse (someTimes char) x-          `shouldBe`-           replaceError "someTimes"-                        (parseTimes char [1 .. Text.length x] x)+      \x -> parse (some anyChar) x+           ===+           parseTimes anyChar [1 .. Text.length x + 10] x -  describe "multipleTimes" $+  describe "multiple" $      prop "applies a parser at least twice" $-      \x -> parse (multipleTimes char) x-          `shouldBe`-           replaceError "multipleTimes"-                        (parseTimes char [2 .. Text.length x] x)+      \x -> parse (multiple anyChar) x+           ===+           parseTimes anyChar [2 .. Text.length x + 10] x -  describe "withinBoth" $+  describe "between" $      prop "applies a parser surrounded by 2 parsers" $       \x (y :: Char) (z :: Char) ->-        parse (withinBoth (is y) (is z) char) x-       `shouldBe`-        parse (is y *> char <* is z) x+        parse (between (is y) (is z) anyChar) x+        ===+        parse (is y *> anyChar <* is z) x -  describe "maybeWithinBoth" $+  describe "maybeBetween" $      prop "applies a parser surrounded by 2 optional parsers" $       \x (y :: Char) (z :: Char) ->-        parse (maybeWithinBoth (is y) (is z) char) x-       `shouldBe`-        parse ((is y |?) *> char <* (is z |?)) x+        parse (maybeBetween (is y) (is z) anyChar) x+        ===+        parse ((is y |?) *> anyChar <* (is z |?)) x -  describe "within" $+  describe "surroundedBy" $      prop "applies a parser surrounded by a parser" $       \x (y :: Char) ->-        parse (within (is y) char) x-       `shouldBe`-        parse (is y *> char <* is y) x+        parse (surroundedBy (is y) anyChar) x+        ===+        parse (is y *> anyChar <* is y) x -  describe "maybeWithin" $+  describe "maybeSurroundedBy" $      prop "applies a parser surrounded by a optional parsers" $       \x (y :: Char) ->-        parse (maybeWithin (is y) char) x-       `shouldBe`-        parse ((is y |?) *> char <* (is y |?)) x+        parse (maybeSurroundedBy (is y) anyChar) x+        ===+        parse ((is y |?) *> anyChar <* (is y |?)) x -  describe "anySepBy" $+  describe "manySepBy" $      prop "applies a parser separated by a parser any number of times" $       \x (y :: Char) ->-        parse (anySepBy (is y) char) x-       `shouldBe`-        parse ((<>) <$> (Foldable.toList <$> (char |?))-                    <*> ((is y *> char) |*)) x+        parse (manySepBy (is y) anyChar) x+        ===+        parse ((<>) <$> (Foldable.toList <$> (anyChar |?))+                    <*> ((is y *> anyChar) |*)) x    describe "someSepBy" $      prop "applies a parser separated by a parser at least once" $       \x (y :: Char) ->-        parse (someSepBy (is y) char) x-       `shouldBe`-        parse ((:) <$> char <*> ((is y *> char) |*)) x+        parse (someSepBy (is y) anyChar) x+        ===+        parse ((:) <$> anyChar <*> ((is y *> anyChar) |*)) x    describe "multipleSepBy" $      prop "applies a parser separated by a parser at least twice" $       \x (y :: Char) ->-        parse (multipleSepBy (is y) char) x-       `shouldBe`-        parse ((:) <$> char <*> ((is y *> char) |+)) x+        parse (multipleSepBy (is y) anyChar) x+        ===+        parse ((:) <$> anyChar <*> ((is y *> anyChar) |+)) x    describe "->>-" $ -    prop "concats results of 2 parsers that can be converted to Strings" $+    prop "concats results of 2 parsers that can be converted to Texts" $       \x (y :: Char) (z :: Char) ->         parse (is y ->>- is z) x-       `shouldBe`-        parse (is [y, z]) x+        ===+        parse (is $ pack [y, z]) x   parseTimes :: Parser a -> [Int] -> Text -> ParseResult [a] parseTimes p ns = parse $ anyOf ((`times` p) <$> reverse ns) --replaceError :: String -> ParseResult a -> ParseResult a-replaceError err (Error (NoMatch _)) = Error $ NoMatch err-replaceError _ result                = result
test/Bookhound/ParserSpec.hs view
@@ -4,9 +4,11 @@ import Test.Hspec.QuickCheck import Test.QuickCheck.Instances.Text () +import Bookhound.Utils.List  import Bookhound.Parser import Data.Char-import Data.Text        (pack, unpack)+import Data.Text                (pack, unpack)+import Test.QuickCheck.Property ((===))   @@ -16,57 +18,57 @@   describe "Functor laws" $ do      prop "Identity" $-      \x -> parse (id <$> char) x-          `shouldBe`-           parse char x+      \x -> parse (id <$> anyChar) x+           ===+           parse anyChar x      prop "Composition" $-      \x -> parse ((isLower . toUpper) <$> char) x-          `shouldBe`-           parse ((isLower <$>) . (toUpper <$>) $ char) x+      \x -> parse ((isLower . toUpper) <$> anyChar) x+           ===+           parse ((isLower <$>) . (toUpper <$>) $ anyChar) x     describe "Applicative laws" $ do      prop "Identity" $-      \x -> parse (pure id <*> char) x-          `shouldBe`-           parse char x+      \x -> parse (pure id <*> anyChar) x+           ===+           parse anyChar x      prop "Homomorphism" $       \x (y :: [Int]) -> parse (pure sum <*> pure y) x-          `shouldBe`+           ===            parse (pure (sum y)) x      prop "Interchange" $       \x (y :: [Int])  -> parse (pure length <*> pure y) x-          `shouldBe`+           ===            parse (pure ($ y) <*> pure length) x     describe "Monad laws" $ do      prop "Left identity" $-      \x -> parse (pure 'a' >>= isMatch (==) char) x-          `shouldBe`-           parse (isMatch (==) char 'a') x+      \x -> parse (pure 'a' >>= isMatch (==) anyChar) x+           ===+           parse (isMatch (==) anyChar 'a') x      prop "Right identity" $-      \x -> parse (char >>= pure) x-          `shouldBe`-           parse char x+      \x -> parse (anyChar >>= pure) x+           ===+           parse anyChar x      prop "Associativity" $       \x -> parse-           (char >>= (\y -> isMatch (<) char y >>= isMatch (>) char)) x-          `shouldBe`-           parse ((char >>= isMatch (<) char) >>= isMatch (>) char) x+           (anyChar >>= (\y -> isMatch (<) anyChar y >>= isMatch (>) anyChar)) x+           ===+           parse ((anyChar >>= isMatch (<) anyChar) >>= isMatch (>) anyChar) x -  describe "char" $+  describe "anyChar" $ -    prop "parses a single char" $-      \x -> parse char x-          `shouldBe`+    prop "parses a single anyChar" $+      \x -> parse anyChar x+           ===            case unpack x of              (ch : rest) -> Result (pack rest) ch              []          -> Error UnexpectedEof@@ -74,54 +76,54 @@   describe "isMatch" $ do      prop "works for ==" $-      \x y -> parse (isMatch (==) char y) x-            `shouldBe`+      \x y -> parse (isMatch (==) anyChar y) x+             ===              case unpack x of                (ch : rest)                  | ch == y    -> Result (pack rest) ch-                 | otherwise -> Error $ UnexpectedChar ch-               []            -> Error UnexpectedEof+                 | hasSome rest -> Error $ ExpectedEof $ pack rest+               _            -> Error UnexpectedEof      prop "works for /=" $-      \x y -> parse (isMatch (/=) char y) x-            `shouldBe`+      \x y -> parse (isMatch (/=) anyChar y) x+             ===              case unpack x of                (ch : rest)                  | ch /= y    -> Result (pack rest) ch-                 | otherwise -> Error $ UnexpectedChar ch-               []            -> Error UnexpectedEof+                 | hasSome rest -> Error $ ExpectedEof $ pack rest+               _            -> Error UnexpectedEof -  describe "check" $+  describe "satisfy" $      prop "performs a check on the parse result" $-      \x -> parse (check "digit" isDigit char) x-          `shouldBe`+      \x -> parse (satisfy isDigit anyChar) x+           ===            case unpack x of              (ch : rest)                | isDigit ch -> Result (pack rest) ch-               | otherwise  -> Error $ NoMatch "digit"-             []             -> Error UnexpectedEof+               | hasSome rest -> Error $ ExpectedEof $ pack rest+             _             -> Error UnexpectedEof    describe "except" $      context "when the second parser fails" $       prop "the first parser then runs" $-        \x -> parse (except char (char *> char)) x-            `shouldBe`+        \x -> parse (except anyChar (anyChar *> anyChar)) x+             ===              case unpack x of                [ch]    -> Result (pack "") ch-               (_ : _) -> Error $ NoMatch "except"+               (_ : _) -> Error $ ExpectedEof x                []      -> Error UnexpectedEof    describe "anyOf" $      prop "returns first parser success or last parser error if all fail" $-      \x -> parse (anyOf [errorParser $ ErrorAt "firstError",-                         "firstSuccess"  <$ char,-                         "secondSuccess" <$ char,-                         errorParser $ ErrorAt "secondError",-                         errorParser $ ErrorAt "lastError"]) x-          `shouldBe`+      \x -> parse (anyOf [throwError $ ErrorAt "firstError",+                         "firstSuccess"  <$ anyChar,+                         "secondSuccess" <$ anyChar,+                         throwError $ ErrorAt "secondError",+                         throwError $ ErrorAt "lastError"]) x+           ===            case unpack x of              (_ : rest) -> Result (pack rest) "firstSuccess"              []         -> Error $ ErrorAt "lastError"@@ -130,20 +132,20 @@      context "when any parser fails" $       prop "returns first parser error" $-        \x -> parse (allOf ["firstSuccess"  <$ char,-                           "secondSuccess" <$ char,-                           errorParser $ ErrorAt "firstError"]) x-            `shouldBe`+        \x -> parse (allOf ["firstSuccess"  <$ anyChar,+                           "secondSuccess" <$ anyChar,+                           throwError $ ErrorAt "firstError"]) x+             ===              case unpack x of                (_ : _) -> Error $ ErrorAt "firstError"                []      -> Error UnexpectedEof      context "when all parsers succeed" $       prop "returns last parser success" $-        \x -> parse (allOf ["firstSuccess"  <$ char,-                           "secondSuccess" <$ char,-                           "thirdSuccess"  <$ char]) x-            `shouldBe`+        \x -> parse (allOf ["firstSuccess"  <$ anyChar,+                           "secondSuccess" <$ anyChar,+                           "thirdSuccess"  <$ anyChar]) x+             ===              case unpack x of                (_ : rest) -> Result (pack rest) "thirdSuccess"                []         -> Error UnexpectedEof@@ -151,8 +153,8 @@   describe "exactly" $      prop "returns an error when some chars remain after parsing" $-      \x -> parse (exactly char) x-          `shouldBe`+      \x -> parse (exactly anyChar) x+           ===            case unpack x of              [ch]       -> Result (pack []) ch              (_ : rest) -> Error $ ExpectedEof (pack rest)@@ -161,35 +163,36 @@   describe "runParser" $      prop "parses exactly and wraps the result into an either" $-      \x -> runParser char x-          `shouldBe`-           toEither (parse (exactly char) x)+      \x -> runParser anyChar x+           ===+           toEither (parse (exactly anyChar) x)     describe "withError" $      prop "includes error labels in order when running the parser" $-      \x -> runParser ((,) <$> withErrorN 2 "firstErr" char-                          <*> withErrorN 1 "secondErr" char) x-          `shouldBe`-             case unpack x of-               [ch1, ch2] -> Right (ch1, ch2)-               (_ : _ : rest)   -> Left [ErrorAt "firstErr",-                                        ErrorAt "secondErr",-                                        ExpectedEof (pack rest)]-               _                -> Left [ErrorAt "firstErr",-                                        ErrorAt "secondErr",-                                        UnexpectedEof]+      \x -> runParser ((,) <$> withErrorN 2 "firstErr" anyChar+                          <*> withErrorN 1 "secondErr" anyChar) x+           ===+           case unpack x of+             [ch1, ch2] -> Right (ch1, ch2)+             (_ : _ : rest)   -> Left [ErrorAt "firstErr",+                                      ErrorAt "secondErr",+                                      ExpectedEof (pack rest)]+             _                -> Left [ErrorAt "firstErr",+                                      ErrorAt "secondErr",+                                      UnexpectedEof]    describe "withTransform" $      prop "transforms current parser with provided fn" $-      \x -> parse (withTransform (\p -> char *> p <* char) char) x-          `shouldBe`-           parse (char *> char <* char) x-+      \x -> parse (withTransform (\p -> anyChar *> p <* anyChar) anyChar) x+           ===+           parse (anyChar *> anyChar <* anyChar) x  +isMatch :: (a -> a -> Bool) -> Parser a -> a -> Parser a+isMatch cond ma c1 = satisfy (cond c1) ma  toEither :: ParseResult a -> Either [ParseError] a toEither = \case
test/Bookhound/Parsers/CollectionsSpec.hs view
@@ -11,8 +11,9 @@ import           Data.Char                     (isAlpha, isAscii) import           Data.List                     (intercalate) import qualified Data.Map                      as Map-import           Data.Text                     (pack)+import           Data.Text                     ( pack) import           Test.QuickCheck               ((==>))+import           Test.QuickCheck.Property      ((===))   @@ -27,7 +28,7 @@         (pack ("[" <>                intercalate ", " (pure <$> filter isAlpha' x)                <> "]"))-       `shouldBe`+        ===         Right (filter isAlpha' x)    describe "tupleOf" $@@ -38,24 +39,24 @@         (pack ("(" <>                intercalate ", " (pure <$> filter isAlpha' x)                <> ")"))-       `shouldBe`+        ===         Right (filter isAlpha' x)    describe "mapOf" $      prop "parses a map provided the key and value parsers" $       \(x :: [(Char, Char)]) ->-        runParser (mapOf (is "->") alpha alpha)+        runParser (mapOf (is (":" :: String)) alpha alpha)         (pack ("{" <>                intercalate ", " (showMapEntry <$> filter areAlpha' x)                <> "}"))-       `shouldBe`-        Right (Map.fromList $ filter areAlpha' x)+        ===+        Right ( Map.fromList $ filter areAlpha' x)    showMapEntry :: (Char, Char) -> String-showMapEntry (x, y) = pure x <> " -> " <> pure y+showMapEntry (x, y) = pure x <> ": " <> pure y  areAlpha' :: (Char, Char) -> Bool areAlpha' (x, y) = isAlpha' x && isAlpha' y
test/Bookhound/Parsers/DateTimeSpec.hs view
@@ -9,8 +9,9 @@ import Bookhound.Parsers.DateTime import Data.Text                  (pack) -import Data.Time (Day, LocalTime, TimeOfDay, TimeZone (..), ZonedTime (..),-                  zonedTimeToUTC)+import Data.Time                (Day, LocalTime, TimeOfDay, TimeZone (..),+                                 ZonedTime (..), zonedTimeToUTC)+import Test.QuickCheck.Property ((===))   spec :: Spec@@ -21,7 +22,7 @@     prop "parses a date" $       \(x :: Day) ->         runParser date (pack $ show x)-       `shouldBe`+        ===         Right x    describe "time" $@@ -29,7 +30,7 @@     prop "parses a time" $       \(x :: TimeOfDay) ->         runParser time (pack $ show x)-       `shouldBe`+        ===         Right x    describe "timeZoneOffset" $@@ -37,7 +38,7 @@     prop "parses a timezone offset" $       \(x :: TimeZone) ->         runParser timeZoneOffset (pack $ show $ normalizeTimeZone x)-       `shouldBe`+        ===         Right (normalizeTimeZone x)    describe "localDateTime" $@@ -45,7 +46,7 @@     prop "parses a local datetime" $       \(x :: LocalTime) ->         runParser localDateTime (pack $ show x)-       `shouldBe`+        ===         Right x    describe "DateTime" $@@ -54,7 +55,7 @@       \(x :: ZonedTime) ->         (zonedTimeToUTC <$> runParser dateTime          (pack $ show $ normalizeZonedTime x))-       `shouldBe`+        ===         Right (zonedTimeToUTC $ normalizeZonedTime x)  
test/Bookhound/Parsers/NumberSpec.hs view
@@ -9,6 +9,7 @@ import Bookhound.Parser import Bookhound.Parsers.Number import Data.Text                (pack)+import Test.QuickCheck.Property ((===))   @@ -18,32 +19,24 @@   describe "posInt" $      prop "parses a positive Int" $-      \(x :: Integer) -> x > 0 ==>+      \(x :: Int) -> x > 0 ==>         runParser posInt (pack $ show x)-       `shouldBe`+        ===         Right x    describe "negInt" $      prop "parses a negative Int" $-      \(x :: Integer) -> x < 0 ==>+      \(x :: Int) -> x < 0 ==>         runParser negInt (pack $ show x)-       `shouldBe`+        ===         Right x    describe "int" $      prop "parses an Int" $-      \(x :: Integer) ->+      \(x :: Int) ->         runParser int (pack $ show x)-       `shouldBe`+        ===         Right x --  describe "double" $--    prop "parses a Double" $-      \(x :: Double) ->-        runParser double (pack $ show x)-       `shouldBe`-        Right x