packages feed

megaparsec 6.4.0 → 6.4.1

raw patch · 18 files changed

+204/−191 lines, 18 filesdep ~criterionPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: criterion

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+## Megaparsec 6.4.1++* `scientific` now correctly backtracks after attempting to parse fractional+  and exponent parts of a number. `float` correctly backtracks after+  attempting to parse optional exponent part (when it comes after fractional+  part, otherwise it's obligatory).+ ## Megaparsec 6.4.0  * `Text.Megaparsec` now re-exports `Control.Monad.Combinators` instead of
LICENSE.md view
@@ -1,4 +1,4 @@-Copyright © 2015–2017 Megaparsec contributors<br>+Copyright © 2015–2018 Megaparsec contributors<br> Copyright © 2007 Paolo Martini<br> Copyright © 1999–2000 Daan Leijen 
README.md view
@@ -11,8 +11,7 @@     * [Core features](#core-features)     * [Error messages](#error-messages)     * [Alex support](#alex-support)-    * [Character parsing](#character-parsing)-    * [Binary parsing](#binary-parsing)+    * [Character and binary parsing](#character-and-binary-parsing)     * [Permutation parsing](#permutation-parsing)     * [Expression parsing](#expression-parsing)     * [Lexer](#lexer)@@ -24,7 +23,6 @@     * [Megaparsec vs Parsec](#megaparsec-vs-parsec)     * [Megaparsec vs Trifecta](#megaparsec-vs-trifecta)     * [Megaparsec vs Earley](#megaparsec-vs-earley)-    * [Megaparsec vs Parsers](#megaparsec-vs-parsers) * [Related packages](#related-packages) * [Prominent projects that use Megaparsec](#prominent-projects-that-use-megaparsec) * [Links to announcements and blog posts](#links-to-announcements-and-blog-posts)@@ -38,19 +36,19 @@  ## Features -This project provides flexible solutions to satisfy common parsing needs.-The section describes them shortly. If you're looking for comprehensive+The project provides flexible solutions to satisfy common parsing needs. The+section describes them shortly. If you're looking for comprehensive documentation, see the [section about documentation](#documentation).  ### Core features  The package is built around `MonadParsec`, an MTL-style monad transformer. All tools and features work with all instances of `MonadParsec`. You can-achieve various effects combining monad transformers, i.e. building monad-stack. Since the standard common monad transformers like `WriterT`,-`StateT`, `ReaderT` and others are instances of the `MonadParsec` type-class, you can wrap `ParsecT` *in* these monads, achieving, for example,-backtracking state.+achieve various effects combining monad transformers, i.e. building a+monadic stack. Since the common monad transformers like `WriterT`, `StateT`,+`ReaderT` and others are instances of the `MonadParsec` type class, you can+wrap `ParsecT` *in* these monads, achieving, for example, backtracking+state.  On the other hand `ParsecT` is an instance of many type classes as well. The most useful ones are `Monad`, `Applicative`, `Alternative`, and@@ -61,13 +59,10 @@  * `failure` allows to fail reporting a parse error with unexpected and   expected items.- * `fancyFailure` allows to fail reporting custom error messages.- * `withRecovery` allows to recover from parse errors “on-the-fly” and   continue parsing. Once parsing is finished, several parse errors may be   reported or ignored altogether.- * `observing` allows to “observe” parse errors without ending parsing (they   are returned in `Left`, while normal results are wrapped in `Right`). @@ -79,16 +74,14 @@   faster than matching a string token by token. `tokens` returns “chunk” of   original input, meaning that if you parse `Text`, it'll return `Text`   without any repacking.- * `takeWhile` and `takeWhile1` are about 150 times faster than approaches   involving `many`, `manyTill` and other similar combinators.- * `takeP` allows to grab n tokens from the stream and returns them as a   “chunk” of the stream.  So now that we have matched the main “performance boosters” of Attoparsec, Megaparsec 6 is not significantly slower than Attoparsec if you write your-parser carefully.+parser carefully (see also [the section about performance](#performance)).  Megaparsec can currently work with the following types of input stream out-of-the-box:@@ -98,13 +91,13 @@ * `Text` (strict and lazy)  It's also simple to make it work with custom token streams, and Megaparsec-users have done so many times with great success.+users have done so many times.  ### Error messages -Megaparsec 5 introduces well-typed error messages and the ability to use+Megaparsec 5 introduced well-typed error messages and the ability to use custom data types to adjust the library to specific domain of interest. No-need to use a shapeless bunch of strings anymore.+need to use a shapeless bunch of strings.  The design of parse errors has been revised in version 6 significantly, but custom errors are still easy (probably even easier now).@@ -116,48 +109,28 @@ version 6, but user can still work with custom streams of tokens without problems. -### Character parsing+### Character and binary parsing  Megaparsec has decent support for Unicode-aware character parsing. Functions for character parsing live in the-[`Text.Megaparsec.Char`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Char.html) module.-The functions can be divided into several categories:--* *Simple parsers*—parsers that parse certain character or several-  characters of the same kind. This includes `newline`, `crlf`, `eol`,-  `tab`, and `space`.--* *Parsers corresponding to categories of characters* parse single character-  that belongs to certain category of characters, for example:-  `controlChar`, `spaceChar`, `upperChar`, `lowerChar`, `printChar`,-  `digitChar`, and others.--* *General parsers* that allow you to parse a single character you specify-  or one of the given characters, or any character except for the given-  ones, or character satisfying given predicate. Case-insensitive versions-  of the parsers are available.--* *Parsers for sequences of characters* parse strings. Case-sensitive-  `string` parser is available as well as case-insensitive `string'`.--### Binary parsing--Similarly, there is-[`Text.Megaparsec.Byte`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Byte.html) module-for parsing streams of bytes.+[`Text.Megaparsec.Char`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Char.html)+module. Similarly, there is+[`Text.Megaparsec.Byte`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Byte.html)+module for parsing streams of bytes.  ### Permutation parsing -For those who are interested in parsing of permutation phrases, there-is [`Text.Megaparsec.Perm`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Perm.html).+For those who are interested in parsing of permutation phrases, there is+[`Text.Megaparsec.Perm`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Perm.html). You have to import the module explicitly, it's not included in the `Text.Megaparsec` module.  ### Expression parsing  Megaparsec has a solution for parsing of expressions. Take a look at-[`Text.Megaparsec.Expr`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Expr.html). You have to import the module explicitly, it's not-included in the `Text.Megaparsec`.+[`Text.Megaparsec.Expr`](https://hackage.haskell.org/package/megaparsec/docs/Text-Megaparsec-Expr.html).+You have to import the module explicitly, it's not included in the+`Text.Megaparsec`.  Given a table of operators that describes their fixity and precedence, you can construct a parser that will parse any expression involving the@@ -170,7 +143,7 @@ in the past, this module “fixes” its particularly inflexible `Text.Parsec.Token`. -`Text.Megaparsec.Char.Lexer` is intended to be imported via a qualified+`Text.Megaparsec.Char.Lexer` is intended to be imported using a qualified import, it's not included in `Text.Megaparsec`. The module doesn't impose how you should write your parser, but certain approaches may be more elegant than others. An especially important theme is parsing of white space,@@ -188,15 +161,12 @@  ## Documentation -Megaparsec is well-documented. All functions and data-types are thoroughly-described. We pay attention to avoid outdated info or unclear phrases in our-documentation. See the [current version of Megaparsec documentation on-Hackage](https://hackage.haskell.org/package/megaparsec) for yourself.+Megaparsec is well-documented. See the [current version of Megaparsec+documentation on Hackage](https://hackage.haskell.org/package/megaparsec).  ## Tutorials -You can find Megaparsec-tutorials+You can find Megaparsec tutorials [here](https://markkarpov.com/learn-haskell.html#megaparsec-tutorials). They should provide sufficient guidance to help you to start with your parsing tasks. The site also has instructions and tips for Parsec users who decide@@ -204,19 +174,26 @@  ## Performance -Despite being quite flexible, Megaparsec is also faster than Parsec. The-repository includes benchmarks that can be easily used to compare Megaparsec-and Parsec. In most cases Megaparsec is faster, sometimes dramatically-faster. If you happen to have some other benchmarks, I would appreciate if-you add Megaparsec to them and let me know how it performs.+Despite being flexible, Megaparsec is also quite fast. Here is how+Megaparsec 6.4.0 compares to Attoparsec 0.13.2.0 (the fastest widely used+parsing library in the Haskell ecosystem): -Additional benchmarks created to guide development of Megaparsec 6 can be-found [here](https://github.com/mrkkrp/parsers-bench). These compare 3 pairs-of parsers written using Attoparsec and Megaparsec.+Test case         | Execution time | Allocated | Max residency+------------------|---------------:|----------:|-------------:+CSV (Attoparsec)  |       57.14 μs |   397,912 |        10,560+CSV (Megaparsec)  |       76.27 μs |   557,272 |         9,120+Log (Attoparsec)  |       244.2 μs | 1,181,120 |        11,144+Log (Megaparsec)  |       315.2 μs | 1,485,776 |        11,392+JSON (Attoparsec) |       14.39 μs |   132,496 |         9,048+JSON (Megaparsec) |       26.70 μs |   233,336 |         9,424 -If you think your Megaparsec parser is not efficient enough, take a look-at [these instructions](https://markkarpov.com/megaparsec/writing-a-fast-parser.html).+The benchmarks were created to guide development of Megaparsec 6 and can be+found [here](https://github.com/mrkkrp/parsers-bench). +If you think your Megaparsec parser is not efficient enough, take a look at+[these+instructions](https://markkarpov.com/megaparsec/writing-a-fast-parser.html).+ ## Comparison with other solutions  There are quite a few libraries that can be used for parsing in Haskell,@@ -228,9 +205,9 @@ library for parsing. Although the both libraries deal with parsing, it's usually easy to decide which you will need in particular project: -* *Attoparsec* is much faster but not that feature-rich. It should be used-  when you want to process large amounts of data where performance matters-  more than quality of error messages.+* *Attoparsec* is faster but not that feature-rich. It should be used when+  you want to process large amounts of data where performance matters more+  than quality of error messages.  * *Megaparsec* is good for parsing of source code or other human-readable   texts. It has better error messages and it's implemented as monad@@ -250,13 +227,15 @@ Since Megaparsec is a fork of Parsec, we are bound to list the main differences between the two libraries: -* Better error messages. We test our error messages using dense QuickCheck-  tests. Good error messages are just as important for us as correct return-  values of our parsers. Megaparsec will be especially useful if you write a-  compiler or an interpreter for some language.+* Better error messages. We test our error messages using numerous+  QuickCheck (generative) tests. Good error messages are just as important+  for us as correct return values of our parsers. Megaparsec will be+  especially useful if you write a compiler or an interpreter for some+  language. -* Megaparsec 6 can show line on which parse error happened as part of parse-  error. This makes it a lot easier to figure out where the error happened.+* Megaparsec 6 can show the line on which parse error happened as part of+  parse error. This makes it a lot easier to figure out where the error+  happened.  * Some quirks and “buggy features” (as well as plain bugs) of original   Parsec are fixed. There is no undocumented surprising stuff in Megaparsec.@@ -264,9 +243,10 @@ * Better support for Unicode parsing in `Text.Megaparsec.Char`.  * Megaparsec has more powerful combinators and can parse languages where-  indentation matters.+  indentation matters out-of-the-box. -* Comprehensive QuickCheck test suite covering nearly 100% of our code.+* Comprehensive test suite covering nearly 100% of our code. Compare that to+  absence  * We have benchmarks to detect performance regressions. @@ -289,25 +269,19 @@   foo”, “in expression x”, etc. This is not possible with Parsec.  * Megaparsec is faster and supports efficient operations on top of `tokens`,-  `takeWhileP`, `takeWhile1P`, `takeP` just like Attoparsec.+  `takeWhileP`, `takeWhile1P`, `takeP` like Attoparsec.  If you want to see a detailed change log, `CHANGELOG.md` may be helpful. Also see [this original announcement](https://notehub.org/w7037) for another comparison. -Parsec is old and somewhat famous in the Haskell community, so we understand-there will be some kind of inertia, but we advise you use Megaparsec from-now on because it solves many problems of the original Parsec project. If-you think you still have a reason to use original Parsec, open an issue.- ### Megaparsec vs Trifecta  [Trifecta](https://hackage.haskell.org/package/trifecta) is another Haskell library featuring good error messages. It's probably good, but also-under-documented, and has-unfixed [bugs and flaws](https://github.com/ekmett/trifecta/issues) that-Edward is too busy to fix (simply a fact, no offense intended). Other-reasons one may question choice of Trifecta is his/her parsing library:+under-documented, and has unfixed [bugs and+flaws](https://github.com/ekmett/trifecta/issues). Other reasons one may+question choice of Trifecta is his/her parsing library:  * Complicated, doesn't have any tutorials available, and documentation   doesn't help at all.@@ -322,6 +296,10 @@   dependencies. Also if you're not into `lens` and would like to keep your   code “vanilla”, you may not like the API. +[Idris](https://www.idris-lang.org/) has recently switched from Trifecta to+Megaparsec which allowed it to [have better error messages and fewer+dependencies](https://twitter.com/edwinbrady/status/950084043282010117?s=09).+ ### Megaparsec vs Earley  [Earley](https://hackage.haskell.org/package/Earley) is a newer library that@@ -347,50 +325,33 @@  IOW, Megaparsec is less safe but also more powerful. -### Megaparsec vs Parsers--There is [Parsers](https://hackage.haskell.org/package/parsers) package,-which is great. You can use it with Megaparsec or Parsec, but consider the-following:--* It depends on both Attoparsec and Parsec. This is ridiculous, by the way,-  because this package is supposed to be useful for parser builders, so they-  can write basic core functionality and get the rest “for free”.--* It currently has a ~~bug~~ feature in definition of `lookAhead` for-  various monad transformers like `StateT`, etc. which is visible when you-  create backtracking state via monad stack, not via built-in features. The-  feature makes it so `lookAhead` will backtrack your parser state but not-  your custom state added via `StateT`. Kmett thinks this behavior is-  better.--We intended to use Parsers library in Megaparsec at some point, but aside-from already mentioned flaws the library has different conventions for-naming of things, different set of “core” functions, etc., different-approach to lexing. So it didn't happen, Megaparsec has minimal-dependencies, it is feature-rich and self-contained.- ## Related packages -The following packages are designed to be used with Megaparsec:+The following packages are designed to be used with Megaparsec (open a PR if+you want to add something to the list):  * [`hspec-megaparsec`](https://hackage.haskell.org/package/hspec-megaparsec)—utilities-  for testing Megaparsec parsers with-  with [Hspec](https://hackage.haskell.org/package/hspec).+  for testing Megaparsec parsers with with+  [Hspec](https://hackage.haskell.org/package/hspec). * [`cassava-megaparsec`](https://hackage.haskell.org/package/cassava-megaparsec)—Megaparsec-  parser of CSV files that plays nicely-  with [Cassava](https://hackage.haskell.org/package/cassava).+  parser of CSV files that plays nicely with+  [Cassava](https://hackage.haskell.org/package/cassava). * [`tagsoup-megaparsec`](https://hackage.haskell.org/package/tagsoup-megaparsec)—a-  library for easily-  using [TagSoup](https://hackage.haskell.org/package/tagsoup) as a token-  type in Megaparsec.+  library for easily using+  [TagSoup](https://hackage.haskell.org/package/tagsoup) as a token type in+  Megaparsec.  ## Prominent projects that use Megaparsec +The following are some prominent projects that use Megaparsec:+ * [Idris](https://github.com/idris-lang/Idris-dev)—a general-purpose   functional programming language with dependent types * [Hledger](https://github.com/simonmichael/hledger)—an accounting tool-* [Stache](https://github.com/stackbuilders/stache)—Mustache templates for Haskell+* [MMark](https://github.com/mmark-md/mmark)—strict markdown processor for+  writers+* [Stache](https://github.com/stackbuilders/stache)—Mustache templates for+  Haskell * [Language Puppet](https://github.com/bartavelle/language-puppet)—library   for manipulating Puppet manifests @@ -424,8 +385,8 @@  ## License -Copyright © 2015–2017 Megaparsec contributors<br>-Copyright © 2007 Paolo Martini<br>+Copyright © 2015–2018 Megaparsec contributors\+Copyright © 2007 Paolo Martini\ Copyright © 1999–2000 Daan Leijen  Distributed under FreeBSD license.
Text/Megaparsec.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors --                © 2007 Paolo Martini --                © 1999–2001 Daan Leijen -- License     :  FreeBSD@@ -127,7 +127,6 @@ import Control.Monad.Reader.Class import Control.Monad.State.Class hiding (state) import Control.Monad.Trans-import Control.Monad.Trans.Identity import Data.Data (Data) import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe (fromJust)@@ -155,6 +154,10 @@  #if !MIN_VERSION_base(4,8,0) import Control.Applicative+#endif++#if !MIN_VERSION_mtl(2,2,2)+import Control.Monad.Trans.Identity #endif  -- $reexports
Text/Megaparsec/Byte.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Byte--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
Text/Megaparsec/Byte/Lexer.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Byte.Lexer--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -180,8 +180,8 @@   => m Scientific scientific = do   c'      <- decimal_-  SP c e' <- option (SP c' 0) (dotDecimal_ (Proxy :: Proxy s) c')-  e       <- option e' (exponent_ e')+  SP c e' <- option (SP c' 0) (try $ dotDecimal_ (Proxy :: Proxy s) c')+  e       <- option e' (try $ exponent_ e')   return (Sci.scientific c e) {-# INLINEABLE scientific #-} @@ -200,7 +200,7 @@   c' <- decimal_   Sci.toRealFloat <$>     ((do SP c e' <- dotDecimal_ (Proxy :: Proxy s) c'-         e       <- option e' (exponent_ e')+         e       <- option e' (try $ exponent_ e')          return (Sci.scientific c e))      <|> (Sci.scientific c' <$> exponent_ 0)) {-# INLINEABLE float #-}
Text/Megaparsec/Char.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Char--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors --                © 2007 Paolo Martini --                © 1999–2001 Daan Leijen -- License     :  FreeBSD
Text/Megaparsec/Char/Lexer.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Char.Lexer--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors --                © 2007 Paolo Martini --                © 1999–2001 Daan Leijen -- License     :  FreeBSD@@ -496,8 +496,8 @@   => m Scientific scientific = do   c'      <- decimal_-  SP c e' <- option (SP c' 0) (dotDecimal_ (Proxy :: Proxy s) c')-  e       <- option e' (exponent_ e')+  SP c e' <- option (SP c' 0) (try $ dotDecimal_ (Proxy :: Proxy s) c')+  e       <- option e' (try $ exponent_ e')   return (Sci.scientific c e) {-# INLINEABLE scientific #-} @@ -519,7 +519,7 @@   c' <- decimal_   Sci.toRealFloat <$>     ((do SP c e' <- dotDecimal_ (Proxy :: Proxy s) c'-         e       <- option e' (exponent_ e')+         e       <- option e' (try $ exponent_ e')          return (Sci.scientific c e))      <|> (Sci.scientific c' <$> exponent_ 0)) {-# INLINEABLE float #-}
Text/Megaparsec/Error.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Error--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
Text/Megaparsec/Error/Builder.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Error.Builder--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
Text/Megaparsec/Expr.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Expr--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors --                © 2007 Paolo Martini --                © 1999–2001 Daan Leijen -- License     :  FreeBSD
Text/Megaparsec/Perm.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Perm--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors --                © 2007 Paolo Martini --                © 1999–2001 Daan Leijen -- License     :  FreeBSD
Text/Megaparsec/Pos.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Pos--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
Text/Megaparsec/Stream.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Text.Megaparsec.Stream--- Copyright   :  © 2015–2017 Megaparsec contributors+-- Copyright   :  © 2015–2018 Megaparsec contributors -- License     :  FreeBSD -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
megaparsec.cabal view
@@ -1,5 +1,5 @@ name:                 megaparsec-version:              6.4.0+version:              6.4.1 cabal-version:        >= 1.18 tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.2 license:              BSD2@@ -110,7 +110,7 @@   hs-source-dirs:     bench/speed   type:               exitcode-stdio-1.0   build-depends:      base         >= 4.7  && < 5.0-                    , criterion    >= 0.6.2.1 && < 1.3+                    , criterion    >= 0.6.2.1 && < 1.4                     , deepseq      >= 1.3  && < 1.5                     , megaparsec                     , text         >= 0.2  && < 1.3
tests/Text/Megaparsec/Byte/LexerSpec.hs view
@@ -123,6 +123,44 @@         prs (hexadecimal :: Parser Integer) "" `shouldFailWith`           err posI (ueof <> elabel "hexadecimal integer") +  describe "scientific" $ do+    context "when stream begins with a number" $+      it "parses it" $+        property $ \n' -> do+          let p = scientific :: Parser Scientific+              s = B8.pack $ either (show . getNonNegative) (show . getNonNegative)+                (n' :: Either (NonNegative Integer) (NonNegative Double))+          prs p s `shouldParse` case n' of+            Left  x -> fromIntegral    (getNonNegative x)+            Right x -> fromFloatDigits (getNonNegative x)+          prs' p s `succeedsLeaving` ""+    context "when fractional part is interrupted" $+      it "signals correct parse error" $+        property $ \(NonNegative n) -> do+          let p = scientific <* empty :: Parser Scientific+              s = B8.pack (showFFloatAlt Nothing (n :: Double) "")+          prs p s `shouldFailWith` err (posN (B.length s) s)+            (etok 69 <> etok 101 <> elabel "digit")+          prs' p s `failsLeaving` ""+    context "when whole part is followed by a dot without valid fractional part" $+      it "parsing of fractional part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = scientific :: Parser Scientific+              s = B8.pack $ showInt (n :: Integer) ".err"+          prs  p s `shouldParse` fromIntegral n+          prs' p s `succeedsLeaving` ".err"+    context "when number is followed by something starting with 'e'" $+      it "parsing of exponent part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = scientific :: Parser Scientific+              s = B8.pack $ showFFloatAlt Nothing (n :: Double) "err!"+          prs  p s `shouldParse` fromFloatDigits n+          prs' p s `succeedsLeaving` "err!"+    context "when stream is empty" $+      it "signals correct parse error" $+        prs (scientific :: Parser Scientific) "" `shouldFailWith`+          err posI (ueof <> elabel "digit")+   describe "float" $ do     context "when stream begins with a float" $       it "parses it" $@@ -149,6 +187,13 @@           prs  p s `shouldFailWith` err (posN (B.length s) s)             (ueof <> etok 46 <> etok 69 <> etok 101 <> elabel "digit")           prs' p s `failsLeaving` ""+    context "when number is followed by something starting with 'e'" $+      it "parsing of exponent part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = float :: Parser Double+              s = B8.pack $ showFFloatAlt Nothing (n :: Double) "err!"+          prs  p s `shouldParse` n+          prs' p s `succeedsLeaving` "err!"     context "when stream is empty" $       it "signals correct parse error" $         prs (float :: Parser Double) "" `shouldFailWith`@@ -162,30 +207,6 @@         prs' p "123e+3" `succeedsLeaving` ""         prs  p "123e-3" `shouldParse` 123e-3         prs' p "123e-3" `succeedsLeaving` ""--  describe "scientific" $ do-    context "when stream begins with a number" $-      it "parses it" $-        property $ \n' -> do-          let p = scientific :: Parser Scientific-              s = B8.pack $ either (show . getNonNegative) (show . getNonNegative)-                (n' :: Either (NonNegative Integer) (NonNegative Double))-          prs p s `shouldParse` case n' of-            Left  x -> fromIntegral    (getNonNegative x)-            Right x -> fromFloatDigits (getNonNegative x)-          prs' p s `succeedsLeaving` ""-    context "when fractional part is interrupted" $-      it "signals correct parse error" $-        property $ \(NonNegative n) -> do-          let p = scientific <* empty :: Parser Scientific-              s = B8.pack (showFFloatAlt Nothing (n :: Double) "")-          prs p s `shouldFailWith` err (posN (B.length s) s)-            (etok 69 <> etok 101 <> elabel "digit")-          prs' p s `failsLeaving` ""-    context "when stream is empty" $-      it "signals correct parse error" $-        prs (scientific :: Parser Scientific) "" `shouldFailWith`-          err posI (ueof <> elabel "digit")    describe "signed" $ do     context "with integer" $
tests/Text/Megaparsec/Char/LexerSpec.hs view
@@ -330,6 +330,44 @@         prs (hexadecimal :: Parser Integer) "" `shouldFailWith`           err posI (ueof <> elabel "hexadecimal integer") +  describe "scientific" $ do+    context "when stream begins with a number" $+      it "parses it" $+        property $ \n' -> do+          let p = scientific :: Parser Scientific+              s = either (show . getNonNegative) (show . getNonNegative)+                (n' :: Either (NonNegative Integer) (NonNegative Double))+          prs p s `shouldParse` case n' of+            Left  x -> fromIntegral    (getNonNegative x)+            Right x -> fromFloatDigits (getNonNegative x)+          prs' p s `succeedsLeaving` ""+    context "when fractional part is interrupted" $+      it "signals correct parse error" $+        property $ \(NonNegative n) -> do+          let p = scientific <* empty :: Parser Scientific+              s = showFFloatAlt Nothing (n :: Double) ""+          prs p s `shouldFailWith` err (posN (length s) s)+            (etok 'E' <> etok 'e' <> elabel "digit")+          prs' p s `failsLeaving` ""+    context "when whole part is followed by a dot without valid fractional part" $+      it "parsing of fractional part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = scientific :: Parser Scientific+              s = showInt (n :: Integer) ".err"+          prs  p s `shouldParse` fromIntegral n+          prs' p s `succeedsLeaving` ".err"+    context "when number is followed by something starting with 'e'" $+      it "parsing of exponent part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = scientific :: Parser Scientific+              s = showFFloatAlt Nothing (n :: Double) "err!"+          prs  p s `shouldParse` fromFloatDigits n+          prs' p s `succeedsLeaving` "err!"+    context "when stream is empty" $+      it "signals correct parse error" $+        prs (scientific :: Parser Scientific) "" `shouldFailWith`+          err posI (ueof <> elabel "digit")+   describe "float" $ do     context "when stream begins with a float" $       it "parses it" $@@ -356,6 +394,13 @@           prs  p s `shouldFailWith` err (posN (length s) s)             (ueof <> etok '.' <> etok 'E' <> etok 'e' <> elabel "digit")           prs' p s `failsLeaving` ""+    context "when number is followed by something starting with 'e'" $+      it "parsing of exponent part is backtracked correctly" $+        property $ \(NonNegative n) -> do+          let p = float :: Parser Double+              s = showFFloatAlt Nothing (n :: Double) "err!"+          prs  p s `shouldParse` n+          prs' p s `succeedsLeaving` "err!"     context "when stream is empty" $       it "signals correct parse error" $         prs (float :: Parser Double) "" `shouldFailWith`@@ -369,30 +414,6 @@         prs' p "123e+3" `succeedsLeaving` ""         prs  p "123e-3" `shouldParse` 123e-3         prs' p "123e-3" `succeedsLeaving` ""--  describe "scientific" $ do-    context "when stream begins with a number" $-      it "parses it" $-        property $ \n' -> do-          let p = scientific :: Parser Scientific-              s = either (show . getNonNegative) (show . getNonNegative)-                (n' :: Either (NonNegative Integer) (NonNegative Double))-          prs p s `shouldParse` case n' of-            Left  x -> fromIntegral    (getNonNegative x)-            Right x -> fromFloatDigits (getNonNegative x)-          prs' p s `succeedsLeaving` ""-    context "when fractional part is interrupted" $-      it "signals correct parse error" $-        property $ \(NonNegative n) -> do-          let p = scientific <* empty :: Parser Scientific-              s = showFFloatAlt Nothing (n :: Double) ""-          prs p s `shouldFailWith` err (posN (length s) s)-            (etok 'E' <> etok 'e' <> elabel "digit")-          prs' p s `failsLeaving` ""-    context "when stream is empty" $-      it "signals correct parse error" $-        prs (scientific :: Parser Scientific) "" `shouldFailWith`-          err posI (ueof <> elabel "digit")    describe "signed" $ do     context "with integer" $
tests/Text/Megaparsec/CharSpec.hs view
@@ -225,7 +225,7 @@           prs' (char' ch) s' `failsLeaving`   s'     context "when stream is empty" $       it "signals correct parse error" $-        property $ \ch -> do+        property $ \ch -> goodChar ch ==> do           let ms = ueof <> etok (toLower ch) <> etok (toUpper ch)           prs  (char' ch) "" `shouldFailWith` err posI ms