packages feed

simple-parser 0.8.4 → 0.9

raw patch · 9 files changed

+100/−34 lines, 9 filesdep +exceptionsPVP ok

version bump matches the API change (PVP)

Dependencies added: exceptions

API changes (from Hackage documentation)

+ SimpleParser.Result: ParseErrorBundle :: NESeq (ParseError l s e) -> ParseErrorBundle l s e
+ SimpleParser.Result: [unParseErrorBundle] :: ParseErrorBundle l s e -> NESeq (ParseError l s e)
+ SimpleParser.Result: instance (Data.Typeable.Internal.Typeable l, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable (SimpleParser.Stream.Token s), Data.Typeable.Internal.Typeable (SimpleParser.Stream.Chunk s), Data.Typeable.Internal.Typeable e, GHC.Show.Show l, GHC.Show.Show s, GHC.Show.Show (SimpleParser.Stream.Token s), GHC.Show.Show (SimpleParser.Stream.Chunk s), GHC.Show.Show e) => GHC.Exception.Type.Exception (SimpleParser.Result.ParseError l s e)
+ SimpleParser.Result: instance (Data.Typeable.Internal.Typeable l, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable (SimpleParser.Stream.Token s), Data.Typeable.Internal.Typeable (SimpleParser.Stream.Chunk s), Data.Typeable.Internal.Typeable e, GHC.Show.Show l, GHC.Show.Show s, GHC.Show.Show (SimpleParser.Stream.Token s), GHC.Show.Show (SimpleParser.Stream.Chunk s), GHC.Show.Show e) => GHC.Exception.Type.Exception (SimpleParser.Result.ParseErrorBundle l s e)
+ SimpleParser.Result: instance (GHC.Classes.Eq l, GHC.Classes.Eq s, GHC.Classes.Eq (SimpleParser.Stream.Token s), GHC.Classes.Eq (SimpleParser.Stream.Chunk s), GHC.Classes.Eq e) => GHC.Classes.Eq (SimpleParser.Result.ParseErrorBundle l s e)
+ SimpleParser.Result: instance (GHC.Show.Show l, GHC.Show.Show s, GHC.Show.Show (SimpleParser.Stream.Token s), GHC.Show.Show (SimpleParser.Stream.Chunk s), GHC.Show.Show e) => GHC.Show.Show (SimpleParser.Result.ParseErrorBundle l s e)
+ SimpleParser.Result: listParseErrors :: ParseErrorBundle l s e -> [ParseError l s e]
+ SimpleParser.Result: newtype ParseErrorBundle l s e
+ SimpleParser.Throw: EmptyParseError :: EmptyParseError
+ SimpleParser.Throw: data EmptyParseError
+ SimpleParser.Throw: instance GHC.Classes.Eq SimpleParser.Throw.EmptyParseError
+ SimpleParser.Throw: instance GHC.Exception.Type.Exception SimpleParser.Throw.EmptyParseError
+ SimpleParser.Throw: instance GHC.Show.Show SimpleParser.Throw.EmptyParseError
+ SimpleParser.Throw: runParserEnd :: (Typeable l, Typeable s, Typeable e, Typeable (Token s), Typeable (Chunk s), Show l, Show s, Show e, Show (Token s), Show (Chunk s), Stream s, MonadThrow m) => Parser l s e a -> s -> m a
+ SimpleParser.Throw: runParserThrow :: (Typeable l, Typeable s, Typeable e, Typeable (Token s), Typeable (Chunk s), Show l, Show s, Show e, Show (Token s), Show (Chunk s), MonadThrow m) => Parser l s e a -> s -> m (ParseSuccess s a)
- SimpleParser.Result: ParseResultError :: !NESeq (ParseError l s e) -> ParseResult l s e a
+ SimpleParser.Result: ParseResultError :: !ParseErrorBundle l s e -> ParseResult l s e a
- SimpleParser.Result: matchSoleParseError :: NESeq (ParseError l s e) -> Maybe (ParseError l s e)
+ SimpleParser.Result: matchSoleParseError :: ParseErrorBundle l s e -> Maybe (ParseError l s e)

Files

simple-parser.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 4bbc9417c33617079e899a0ae2e27cc738c1e6b0f4ed0ada613ea049b5d36317+-- hash: 31d2be3a928dd5d492fb80583be7ad1ca75b40f617f793ad6a069146084b3702  name:           simple-parser-version:        0.8.4+version:        0.9 synopsis:       Simple parser combinators description:    Please see the README on GitHub at <https://github.com/ejconlon/simple-parser#readme> category:       Parsing@@ -43,6 +43,7 @@       SimpleParser.Result       SimpleParser.Stack       SimpleParser.Stream+      SimpleParser.Throw   other-modules:       Paths_simple_parser   hs-source-dirs:@@ -69,6 +70,7 @@     , bytestring ==0.10.*     , containers ==0.6.*     , errata ==0.3.*+    , exceptions ==0.10.*     , mmorph ==1.1.*     , mtl ==2.2.*     , nonempty-containers ==0.3.*@@ -106,6 +108,7 @@     , bytestring ==0.10.*     , containers ==0.6.*     , errata ==0.3.*+    , exceptions ==0.10.*     , mmorph ==1.1.*     , mtl ==2.2.*     , nonempty-containers ==0.3.*
src/SimpleParser.hs view
@@ -15,6 +15,7 @@   , module SimpleParser.Result   , module SimpleParser.Stack   , module SimpleParser.Stream+  , module SimpleParser.Throw   ) where  import SimpleParser.CharString@@ -28,3 +29,4 @@ import SimpleParser.Result import SimpleParser.Stack import SimpleParser.Stream+import SimpleParser.Throw
src/SimpleParser/Errata.hs view
@@ -12,7 +12,7 @@ import qualified Data.Text as T import Errata (Block, Style, blockMerged') import SimpleParser.Explain (ErrorExplanation (..), Explainable, ParseErrorExplanation (..), explainParseError)-import SimpleParser.Result (ParseError, ParseResult (..))+import SimpleParser.Result (ParseError, ParseErrorBundle (ParseErrorBundle), ParseResult (..)) import SimpleParser.Stream (Col (..), HasLinePos (..), Line (..), Pos, Span (..))  type LinePosExplainable l s e = (Explainable l s e, HasLinePos (Pos s))@@ -49,5 +49,5 @@ errataParseResult :: LinePosExplainable l s e => Style -> FilePath -> ParseResult l s e a -> [Block] errataParseResult style fp pr =   case pr of-    ParseResultError errs -> fmap (errataParseError style fp) (toList errs)+    ParseResultError (ParseErrorBundle errs) -> fmap (errataParseError style fp) (toList errs)     ParseResultSuccess _ -> []
src/SimpleParser/Input.hs view
@@ -27,12 +27,13 @@ import Data.Maybe (isNothing) import SimpleParser.Chunked (Chunked (..)) import SimpleParser.Parser (ParserT (..), markWithOptStateParser, markWithStateParser)-import SimpleParser.Result (CompoundError (..), ParseError (..), ParseResult (..), RawError (..), StreamError (..))+import SimpleParser.Result (CompoundError (..), ParseError (..), ParseErrorBundle (..), ParseResult (..), RawError (..),+                            StreamError (..)) import SimpleParser.Stack (emptyStack) import SimpleParser.Stream (Stream (..))  throwStreamError :: Monad m => RawError (Chunk s) (Token s) -> ParserT l s e m a-throwStreamError re = ParserT (\s -> pure (Just (ParseResultError (pure (ParseError emptyStack s (CompoundErrorStream (StreamError re)))))))+throwStreamError re = ParserT (\s -> pure (Just (ParseResultError (ParseErrorBundle (pure (ParseError emptyStack s (CompoundErrorStream (StreamError re))))))))  -- | Fetches the next token from the stream and runs the callback. withToken :: (Stream s, Monad m) => Maybe l -> (Maybe (Token s) -> ParserT l s e m a) -> ParserT l s e m a
src/SimpleParser/Interactive.hs view
@@ -16,7 +16,7 @@ import SimpleParser.Explain (Explainable, buildAllParseErrorExplanations, explainParseError) import SimpleParser.Input (matchEnd) import SimpleParser.Parser (Parser, runParser)-import SimpleParser.Result (ParseResult (..), ParseSuccess (..))+import SimpleParser.Result (ParseErrorBundle (..), ParseResult (..), ParseSuccess (..)) import SimpleParser.Stream (LinePosStream, newLinePosStream) import qualified Text.Builder as TB @@ -30,7 +30,7 @@   case runParser (parser <* matchEnd) (newLinePosStream (T.pack input)) of     Nothing ->       putStrLn "No result."-    Just (ParseResultError es) ->+    Just (ParseResultError (ParseErrorBundle es)) ->       case errStyle of         ErrorStyleErrata ->           let blocks = fmap (errataParseError fancyStyle "<interactive>") (toList es)
src/SimpleParser/Parser.hs view
@@ -46,8 +46,8 @@ import Data.Text (Text) import qualified Data.Text as T import SimpleParser.Chunked (Chunked (..))-import SimpleParser.Result (CompoundError (..), Mark (..), ParseError (..), ParseResult (..), ParseSuccess (..),-                            markParseError, parseErrorResume, unmarkParseError)+import SimpleParser.Result (CompoundError (..), Mark (..), ParseError (..), ParseErrorBundle (..), ParseResult (..),+                            ParseSuccess (..), markParseError, parseErrorResume, unmarkParseError) import SimpleParser.Stack (emptyStack)  -- | A 'ParserT' is a state/error/list transformer useful for parsing.@@ -100,15 +100,15 @@       Just res1 ->         case res1 of           ParseResultSuccess _ -> pure mres1-          ParseResultError es1 -> runParserT two s >>= go2 (NESeq.toSeq es1)+          ParseResultError (ParseErrorBundle es1) -> runParserT two s >>= go2 (NESeq.toSeq es1)    go2 es1 mres2 =     case mres2 of-      Nothing -> pure (fmap ParseResultError (NESeq.nonEmptySeq es1))+      Nothing -> pure (fmap (ParseResultError . ParseErrorBundle) (NESeq.nonEmptySeq es1))       Just res2 ->         case res2 of           ParseResultSuccess _ -> pure mres2-          ParseResultError es2 -> pure (Just (ParseResultError (es1 ><| es2)))+          ParseResultError (ParseErrorBundle es2) -> pure (Just (ParseResultError (ParseErrorBundle (es1 ><| es2))))  -- | Yields the LONGEST string of 0 or more successes of the given parser. -- Failures will be silenced.@@ -166,7 +166,7 @@             ParseResultSuccess _ ->               -- Nothing to catch, yield existing success               pure mres-            ParseResultError es ->+            ParseResultError (ParseErrorBundle es) ->               -- Find first custom error to handle               goSplit s0 Empty (NESeq.toSeq es) @@ -174,7 +174,7 @@       case seqPartition extractCustomError afterEs of         Nothing ->           -- No next custom error, finally yield all other errors-          pure (maybe empty (pure . ParseResultError) (NESeq.nonEmptySeq (beforeEs <> afterEs)))+          pure (maybe empty (pure . ParseResultError . ParseErrorBundle) (NESeq.nonEmptySeq (beforeEs <> afterEs)))         Just sep ->           -- Found custom error - handle it           goHandle s0 beforeEs sep@@ -195,13 +195,13 @@             Just res ->               case res of                 ParseResultSuccess _ -> pure mres-                ParseResultError es ->+                ParseResultError (ParseErrorBundle es) ->                   -- Add to list of errors and find next custom error                   goSplit s0 (beforeEs <> nextBeforeEs <> NESeq.toSeq es) afterEs  -- | Throws a custom error throwParser :: Monad m => e -> ParserT l s e m a-throwParser e = ParserT (\s -> pure (Just (ParseResultError (pure (ParseError emptyStack s (CompoundErrorCustom e))))))+throwParser e = ParserT (\s -> pure (Just (ParseResultError (ParseErrorBundle (pure (ParseError emptyStack s (CompoundErrorCustom e)))))))  -- | Catches a custom error catchParser :: Monad m => ParserT l s e m a -> (e -> ParserT l s e m a) -> ParserT l s e m a@@ -213,7 +213,7 @@  -- | A simple failing parser failParser :: Monad m => Text -> ParserT l s e m a-failParser msg = ParserT (\s -> pure (Just (ParseResultError (pure (ParseError emptyStack s (CompoundErrorFail msg))))))+failParser msg = ParserT (\s -> pure (Just (ParseResultError (ParseErrorBundle (pure (ParseError emptyStack s (CompoundErrorFail msg)))))))  instance Monad m => MonadFail (ParserT l s e m) where   fail = failParser . T.pack@@ -271,7 +271,7 @@ markParser ml parser = ParserT (\s -> fmap (fmap (go s)) (runParserT parser s)) where   go s res =     case res of-      ParseResultError es -> ParseResultError (fmap (markParseError (Mark ml s)) es)+      ParseResultError (ParseErrorBundle es) -> ParseResultError (ParseErrorBundle (fmap (markParseError (Mark ml s)) es))       ParseResultSuccess _ -> res  -- | Like 'markParser' but allows you to mutate state. See 'withToken' and 'withChunk'.@@ -288,7 +288,7 @@ unmarkParser parser = ParserT (fmap (fmap go) . runParserT parser) where   go res =     case res of-      ParseResultError es -> ParseResultError (fmap unmarkParseError es)+      ParseResultError (ParseErrorBundle es) -> ParseResultError (ParseErrorBundle (fmap unmarkParseError es))       ParseResultSuccess _ -> res  -- | If the first parser succeeds in the initial state, yield results from the second parser in the initial
src/SimpleParser/Result.hs view
@@ -13,15 +13,20 @@   , unmarkParseError   , parseErrorEnclosingLabels   , parseErrorNarrowestSpan+  , ParseErrorBundle (..)+  , listParseErrors+  , matchSoleParseError   , ParseSuccess (..)   , ParseResult (..)-  , matchSoleParseError   ) where +import Control.Exception (Exception)+import Data.Foldable (toList) import Data.Sequence (Seq (..)) import qualified Data.Sequence as Seq import Data.Sequence.NonEmpty (NESeq (..)) import Data.Text (Text)+import Data.Typeable (Typeable) import SimpleParser.Stack (Stack (..), bottomStack, bottomUpStack, emptyStack, pushStack, topStack) import SimpleParser.Stream (PosStream (..), Span (..), Stream (..)) @@ -74,6 +79,13 @@   , peError :: !(CompoundError s e)   } +deriving instance (Eq l, Eq s, Eq (Token s), Eq (Chunk s), Eq e) => Eq (ParseError l s e)+deriving instance (Show l, Show s, Show (Token s), Show (Chunk s), Show e) => Show (ParseError l s e)++instance (+  Typeable l, Typeable s, Typeable (Token s), Typeable (Chunk s), Typeable e,+  Show l, Show s, Show (Token s), Show (Chunk s), Show e) => Exception (ParseError l s e)+ -- | Returns the resumption point of the 'ParseError'. -- If it has been marked, we use that, otherwise we assume it starts at the exact error point. parseErrorResume :: ParseError l s e -> s@@ -105,27 +117,37 @@     Empty -> Empty     _ :<| s -> s >>= \(Mark ml _) -> maybe Seq.empty Seq.singleton ml -deriving instance (Eq l, Eq s, Eq (Token s), Eq (Chunk s), Eq e) => Eq (ParseError l s e)-deriving instance (Show l, Show s, Show (Token s), Show (Chunk s), Show e) => Show (ParseError l s e)- data ParseSuccess s a = ParseSuccess   { psEndState :: !s   , psValue :: !a   } deriving (Eq, Show, Functor, Foldable, Traversable) -data ParseResult l s e a =-    ParseResultError !(NESeq (ParseError l s e))-  | ParseResultSuccess !(ParseSuccess s a)-  deriving (Functor, Foldable, Traversable)+newtype ParseErrorBundle l s e = ParseErrorBundle { unParseErrorBundle :: NESeq (ParseError l s e) } -deriving instance (Eq l, Eq s, Eq (Token s), Eq (Chunk s), Eq e, Eq a) => Eq (ParseResult l s e a)-deriving instance (Show l, Show s, Show (Token s), Show (Chunk s), Show e, Show a) => Show (ParseResult l s e a)+deriving instance (Eq l, Eq s, Eq (Token s), Eq (Chunk s), Eq e) => Eq (ParseErrorBundle l s e)+deriving instance (Show l, Show s, Show (Token s), Show (Chunk s), Show e) => Show (ParseErrorBundle l s e) --- | If there is one parse error, return it, otherwise return nothing.+instance (+  Typeable l, Typeable s, Typeable (Token s), Typeable (Chunk s), Typeable e,+  Show l, Show s, Show (Token s), Show (Chunk s), Show e) => Exception (ParseErrorBundle l s e)++-- | Lists all errors in the bundle.+listParseErrors :: ParseErrorBundle l s e -> [ParseError l s e]+listParseErrors = toList . unParseErrorBundle++-- | If there is only one parse error in the bundle, return it, otherwise return nothing. -- Errors can accumulate if you use unrestricted branching (with 'orParser' or 'Alternative' '<|>') or manual 'Parser' constructor application. -- However, if you always branch with 'lookAheadMatch' then you will have singleton parse errors, and this will always return 'Just'.-matchSoleParseError :: NESeq (ParseError l s e) -> Maybe (ParseError l s e)-matchSoleParseError es =+matchSoleParseError :: ParseErrorBundle l s e -> Maybe (ParseError l s e)+matchSoleParseError (ParseErrorBundle es) =   case es of     e :<|| Empty -> Just e     _ -> Nothing++data ParseResult l s e a =+    ParseResultError !(ParseErrorBundle l s e)+  | ParseResultSuccess !(ParseSuccess s a)+  deriving (Functor, Foldable, Traversable)++deriving instance (Eq l, Eq s, Eq (Token s), Eq (Chunk s), Eq e, Eq a) => Eq (ParseResult l s e a)+deriving instance (Show l, Show s, Show (Token s), Show (Chunk s), Show e, Show a) => Show (ParseResult l s e a)
+ src/SimpleParser/Throw.hs view
@@ -0,0 +1,38 @@+module SimpleParser.Throw+  ( EmptyParseError (..)+  , runParserThrow+  , runParserEnd+  ) where++import Control.Exception (Exception)+import Control.Monad.Catch (MonadThrow (throwM))+import Data.Typeable (Typeable)+import SimpleParser.Input (matchEnd)+import SimpleParser.Parser (Parser, runParser)+import SimpleParser.Result (ParseResult (..), ParseSuccess (..))+import SimpleParser.Stream (Chunk, Stream, Token)++data EmptyParseError = EmptyParseError+  deriving stock (Eq, Show)++instance Exception EmptyParseError++-- | Runs a parser and throws bundled errors / no parse result errors as exceptions.+runParserThrow :: (+  Typeable l, Typeable s, Typeable e, Typeable (Token s), Typeable (Chunk s),+  Show l, Show s, Show e, Show (Token s), Show (Chunk s),+  MonadThrow m) => Parser l s e a -> s -> m (ParseSuccess s a)+runParserThrow parser s =+  case runParser parser s of+    Nothing -> throwM EmptyParseError+    Just res ->+      case res of+        ParseResultError errs -> throwM errs+        ParseResultSuccess success -> pure success++-- | The easiest way to fully consume input and throw errors.+runParserEnd :: (+  Typeable l, Typeable s, Typeable e, Typeable (Token s), Typeable (Chunk s),+  Show l, Show s, Show e, Show (Token s), Show (Chunk s),+  Stream s, MonadThrow m) => Parser l s e a -> s -> m a+runParserEnd parser s = fmap psValue (runParserThrow (parser <* matchEnd) s)
test/Main.hs view
@@ -49,7 +49,7 @@ sucRes st = Just . ParseResultSuccess . ParseSuccess st  errRes :: [TestParseError] -> Maybe (TestResult a)-errRes es = Just (ParseResultError (NESeq.unsafeFromSeq (Seq.fromList es)))+errRes es = Just (ParseResultError (ParseErrorBundle (NESeq.unsafeFromSeq (Seq.fromList es))))  custErr :: TestState -> Error -> TestParseError custErr endSt = ParseError emptyStack endSt . CompoundErrorCustom