bookhound 0.1.17.0 → 0.1.18.0
raw patch · 5 files changed
+86/−66 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Bookhound.Parser: instance GHC.Classes.Ord Bookhound.Parser.ParseError
+ Bookhound.Parser: withErrorFrom :: (a -> String) -> Parser a -> Parser a
+ Bookhound.Parser: withErrorN :: Int -> String -> Parser a -> Parser a
- Bookhound.Parser: runParser :: Parser a -> Input -> Either ParseError a
+ Bookhound.Parser: runParser :: Parser a -> Input -> Either [ParseError] a
Files
- bookhound.cabal +1/−1
- src/Bookhound/Parser.hs +43/−29
- src/Bookhound/Parsers/Collections.hs +10/−7
- src/Bookhound/Parsers/DateTime.hs +24/−21
- src/Bookhound/Parsers/Number.hs +8/−8
bookhound.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: bookhound-version: 0.1.17.0+version: 0.1.18.0 synopsis: Simple Parser Combinators description: Please see the README on GitHub at <https://github.com/albertprz/bookhound#readme> category: Parser Combinators
src/Bookhound/Parser.hs view
@@ -1,12 +1,13 @@ module Bookhound.Parser (Parser, ParseResult, ParseError(..), runParser, errorParser, andThen, exactly, isMatch, check, anyOf, allOf, char,- withTransform, withError, except) where+ withTransform, withError, withErrorN, withErrorFrom, except) where -import Bookhound.Utils.Foldable (findJust)-import Control.Applicative (liftA2)-import Data.Either (fromRight)-import Data.Maybe (fromMaybe)-import Data.Text (Text, pack, uncons, unpack)+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) type Input = Text @@ -14,7 +15,7 @@ = P { parse :: Input -> ParseResult a , transform :: forall b. Maybe (Parser b -> Parser b)- , error :: Maybe ParseError+ , errors :: Set (Int, ParseError) } data ParseResult a@@ -29,7 +30,7 @@ | UnexpectedString String | NoMatch String | ErrorAt String- deriving (Eq)+ deriving (Eq, Ord) instance Show a => Show (ParseResult a) where@@ -63,25 +64,25 @@ liftA2 f (P p t e) mb@(P _ t' e') = applyTransformsErrors [t, t'] [e, e'] $ mkParser (\x -> case p x of- Error pe -> Error $ fromMaybe pe e Result i a -> parse ((f a) <$> mb) i+ Error pe -> Error pe ) instance Monad Parser where (>>=) (P p t e) f = applyTransform t $ mkParser (\x -> case p x of- Error pe -> Error $ fromMaybe pe e- Result i a -> parse (applyError e' p2) i+ Error pe -> Error pe+ Result i a -> parse (applyError (e <> e') p2) i where p2@(P _ _ e') = f a ) -runParser :: Parser a -> Input -> Either ParseError a+runParser :: Parser a -> Input -> Either [ParseError] a runParser p@(P _ _ e) i = toEither $ parse (exactly p) i where toEither = \case- Error pe -> Left $ fromMaybe pe e Result _ a -> Right a+ Error pe -> Left $ (snd <$> reverse (Set.toList e)) <> [pe] errorParser :: ParseError -> Parser a errorParser = mkParser . const . Error@@ -105,15 +106,15 @@ ) anyOf :: [Parser a] -> Parser a-anyOf ps = anyOfHelper ps Nothing Nothing+anyOf ps = anyOfHelper ps Nothing mempty allOf :: [Parser a] -> Parser a-allOf ps = allOfHelper ps Nothing Nothing+allOf ps = allOfHelper ps Nothing mempty anyOfHelper :: [Parser a] -> (forall b. Maybe (Parser b -> Parser b))- -> Maybe ParseError+ -> Set (Int, ParseError) -> Parser a anyOfHelper [] _ _ = errorParser $ NoMatch "anyOf" anyOfHelper [p] _ _ = p@@ -129,7 +130,7 @@ allOfHelper :: [Parser a] -> (forall b. Maybe (Parser b -> Parser b))- -> Maybe ParseError+ -> Set (Int, ParseError) -> Parser a allOfHelper [] _ _ = errorParser $ NoMatch "allOf" allOfHelper [p] _ _ = p@@ -166,32 +167,45 @@ ) withError :: String -> Parser a -> Parser a-withError = applyError . pure . ErrorAt+withError = withErrorN 0 +withErrorN :: Int -> String -> Parser a -> Parser a+withErrorN n str = applyError . Set.singleton $ (n, ErrorAt str)++withErrorFrom :: (a -> String) -> Parser a -> Parser a+withErrorFrom = withErrorNFrom 0++withErrorNFrom :: Int -> (a -> String) -> Parser a -> Parser a+withErrorNFrom n errFn p =+ do value <- p+ withErrorN n (errFn value) $ pure $ value+ withTransform :: (forall b. Parser b -> Parser b) -> Parser a -> Parser a withTransform t = applyTransform $ Just t -applyTransformError :: (forall b. Maybe (Parser b -> Parser b))- -> Maybe ParseError- -> Parser a- -> Parser a-applyTransformError t e = applyTransform t . applyError e - applyTransformsErrors :: (forall b. [Maybe (Parser b -> Parser b)])- -> [Maybe ParseError]+ -> [Set (Int, ParseError)] -> Parser a -> Parser a applyTransformsErrors ts es =- applyTransformError (findJust ts) (findJust es)+ applyTransformError (findJust ts) (mconcat es) +applyTransformError :: (forall b. Maybe (Parser b -> Parser b))+ -> Set (Int, ParseError)+ -> Parser a+ -> Parser a+applyTransformError t e = applyTransform t . applyError e+++ applyTransform :: (forall b. Maybe (Parser b -> Parser b)) -> Parser a -> Parser a applyTransform f p = maybe p (\f' -> (f' p) {transform = f}) f -applyError :: Maybe ParseError -> Parser a -> Parser a-applyError e p = maybe p (\_ -> p {error = e}) e+applyError :: Set (Int, ParseError) -> Parser a -> Parser a+applyError e p@(P _ _ e') = p {errors = e <> e'} mkParser :: (Input -> ParseResult a) -> Parser a-mkParser p = P {parse = p, transform = Nothing, error = Nothing}+mkParser p = P {parse = p, transform = Nothing, errors = Set.empty}
src/Bookhound/Parsers/Collections.hs view
@@ -1,6 +1,6 @@ module Bookhound.Parsers.Collections (collOf, listOf, tupleOf, mapOf) where -import Bookhound.Parser (Parser, withError)+import Bookhound.Parser (Parser, withErrorN) import Bookhound.ParserCombinators (anySepBy, maybeWithin, satisfies) import Bookhound.Parsers.Char (closeCurly, closeParens, closeSquare, comma, openCurly, openParens, openSquare)@@ -11,22 +11,25 @@ collOf :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]-collOf start end sep elemParser = withError "Collection"- $ start *> elemsParser <* end+collOf start end sep elemParser = withErrorN (-1) "Collection" $+ start *> elemsParser <* end where elemsParser = anySepBy sep $ maybeWithin spacing elemParser + listOf :: Parser a -> Parser [a]-listOf = withError "List"+listOf = withErrorN (-1) "List" . collOf openSquare closeSquare comma + tupleOf :: Parser a -> Parser [a]-tupleOf = withError "Tuple"+tupleOf = withErrorN (-1) "Tuple" . satisfies ((>= 2) . length) . collOf openParens closeParens comma + mapOf :: Ord b => Parser a -> Parser b -> Parser c -> Parser (Map b c)-mapOf sep p1 p2 = withError "Map"- $ Map.fromList <$> collOf openCurly closeCurly comma mapEntry+mapOf sep p1 p2 = withErrorN (-1) "Map" $+ Map.fromList <$> collOf openCurly closeCurly comma mapEntry where mapEntry = (,) <$> p1 <* maybeWithin spacing sep <*> p2
src/Bookhound/Parsers/DateTime.hs view
@@ -1,6 +1,6 @@ module Bookhound.Parsers.DateTime (date, time, timeZoneOffset, localDateTime, offsetDateTime, dateTime, year, day, month, hour, minute, second) where -import Bookhound.Parser (Parser, check, withError)+import Bookhound.Parser (Parser, check, withErrorN) import Bookhound.ParserCombinators (IsMatch (..), within, (<#>), (<|>), (|+), (|?)) import Bookhound.Parsers.Char (colon, dash, digit, plus)@@ -11,38 +11,41 @@ date :: Parser Day-date = withError "Date"- $ fromGregorian <$> year <*> within dash month <*> day+date = withErrorN (-1) "Date" $+ fromGregorian <$> year <*> within dash month <*> day time :: Parser TimeOfDay-time = withError "Time"- $ do h <- hour- m <- colon *> minute- s <- colon *> second- decimals <- fromMaybe 0 <$> ((colon *> secondDecimals) |?)- pure $ TimeOfDay h m $ read (show s <> "." <> show decimals)+time = withErrorN (-1) "Time" $+ do h <- hour+ m <- colon *> minute+ s <- colon *> second+ decimals <- fromMaybe 0 <$> ((colon *> secondDecimals) |?)+ pure $ TimeOfDay h m $ read (show s <> "." <> show decimals) timeZoneOffset :: Parser TimeZone-timeZoneOffset = withError "Timezone Offset"- $ do pos <- (True <$ plus) <|> (False <$ dash)- h <- hour- m <- fromMaybe 0 <$> ((colon *> minute) |?)- pure $ minutesToTimeZone $ (if pos then 1 else (-1)) * (h * 60 + m)+timeZoneOffset = withErrorN (-1) "Timezone Offset" $+ do pos <- (True <$ plus) <|> (False <$ dash)+ h <- hour+ m <- fromMaybe 0 <$> ((colon *> minute) |?)+ pure $ minutesToTimeZone $ (if pos then 1 else (-1)) * (h * 60 + m) + localDateTime :: Parser LocalTime-localDateTime = withError "Local DateTime"- $ LocalTime <$> (date <* oneOf ['T', 't']) <*> time+localDateTime = withErrorN (-1) "Local DateTime" $+ LocalTime <$> (date <* oneOf ['T', 't']) <*> time + offsetDateTime :: Parser ZonedTime-offsetDateTime = withError "Offset DateTime"- $ ZonedTime <$> localDateTime <*> timeZoneOffset+offsetDateTime = withErrorN (-1) "Offset DateTime" $+ ZonedTime <$> localDateTime <*> timeZoneOffset + dateTime :: Parser ZonedTime-dateTime = withError "DateTime"- $ ((`ZonedTime` minutesToTimeZone 0) <$> localDateTime <* is 'Z') <|>- offsetDateTime+dateTime = withErrorN (-1) "DateTime" $+ ((`ZonedTime` minutesToTimeZone 0) <$> localDateTime <* is 'Z')+ <|> offsetDateTime
src/Bookhound/Parsers/Number.hs view
@@ -1,34 +1,34 @@ module Bookhound.Parsers.Number (int, double, posInt, negInt, unsignedInt, hexInt, octInt, intLike) where import Bookhound.Parser (ParseError (..), Parser, errorParser,- withError)+ withErrorN) import Bookhound.ParserCombinators (IsMatch (..), (->>-), (<|>), (|+), (|?)) import Bookhound.Parsers.Char (dash, digit, dot, plus) hexInt :: Parser Integer-hexInt = withError "Hex Int"+hexInt = withErrorN (-1) "Hex Int" $ read <$> (is "0x" ->>- ((digit <|> oneOf ['A' .. 'F'] <|> oneOf ['a' .. 'f']) |+)) octInt :: Parser Integer-octInt = withError "Oct Int"+octInt = withErrorN (-1) "Oct Int" $ read <$> (is "0o" ->>- (oneOf ['0' .. '7'] |+)) unsignedInt :: Parser Integer-unsignedInt = withError "Unsigned Int"+unsignedInt = withErrorN (-1) "Unsigned Int" $ read <$> (digit |+) posInt :: Parser Integer-posInt = withError "Positive Int"+posInt = withErrorN (-1) "Positive Int" $ read <$> (plus |?) ->>- (digit |+) negInt :: Parser Integer-negInt = withError "Negative Int"+negInt = withErrorN (-1) "Negative Int" $ read <$> dash ->>- (digit |+) int :: Parser Integer-int = withError "Int" $ negInt <|> posInt+int = withErrorN (-1) "Int" $ negInt <|> posInt intLike :: Parser Integer intLike = parser <|> int@@ -44,7 +44,7 @@ double :: Parser Double-double = withError "Double"+double = withErrorN (-1) "Double" $ read <$> int ->>- (decimals |?) ->>- (expn |?) where decimals = dot ->>- unsignedInt