parsec 3.1.13.0 → 3.1.18.0
raw patch · 29 files changed
Files
- ChangeLog.md +32/−1
- README.md +2/−2
- parsec.cabal +162/−110
- src/Text/Parsec/ByteString.hs +4/−4
- src/Text/Parsec/ByteString/Lazy.hs +5/−4
- src/Text/Parsec/Char.hs +46/−10
- src/Text/Parsec/Combinator.hs +26/−19
- src/Text/Parsec/Error.hs +17/−7
- src/Text/Parsec/Expr.hs +1/−3
- src/Text/Parsec/Language.hs +2/−2
- src/Text/Parsec/Perm.hs +8/−17
- src/Text/Parsec/Prim.hs +77/−18
- src/Text/Parsec/String.hs +1/−1
- src/Text/Parsec/Text.hs +22/−2
- src/Text/Parsec/Text/Lazy.hs +21/−1
- src/Text/Parsec/Token.hs +10/−16
- src/Text/ParserCombinators/Parsec/Expr.hs +1/−1
- test/Bugs.hs +2/−2
- test/Bugs/Bug2.hs +3/−4
- test/Bugs/Bug35.hs +3/−4
- test/Bugs/Bug6.hs +3/−4
- test/Bugs/Bug9.hs +4/−5
- test/Features.hs +7/−5
- test/Features/Feature150.hs +46/−0
- test/Features/Feature80.hs +3/−4
- test/Main.hs +2/−2
- test/issue127.hs +14/−0
- test/issue171.hs +29/−0
- test/issue175.hs +26/−0
ChangeLog.md view
@@ -1,3 +1,34 @@+### 3.1.18.0++- Drop support for GHCs prior 8.6.5++### 3.1.17.0++- Move `many1 :: ParsecT s u m a -> ParsecT s u m [a]` to `Text.Parsec.Prim`.+ Drop `Stream` constraint requirement.+- Change the position comparison in `mergeError` to not compare source names.+ This doesn't alter reported error positions when only a single source is parsed.+ This fixes performance issue caused by long source names.+- Add `Exception ParseError` instance++### 3.1.16.0++- Add `tokens'` and `string'` combinators which don't consume the prefix.++### 3.1.15.0++- Add `INLINABLE` pragmas to most overloaded combinators+- Support recent versions of dependencies+- Fix memory leak in `>>=` https://github.com/haskell/parsec/issues/127++### 3.1.14.0++- Add `parseFromFile` to `Text.Parsec.Text.Lazy` and `Text.Parsec.Text` (#103, #104).++- Clarify Haddock documentation in various places (#105,#101,#102).++- Add support for `base-4.13`.+ ### 3.1.13.0 - Add official support for [`SafeHaskell`](http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/safe_haskell.html)@@ -45,7 +76,7 @@ ### 3.1.9 -- Many and various updates to documentation and package description (inlcuding+- Many and various updates to documentation and package description (including the homepage links). - Add an `Eq` instance for `ParseError` - Fixed a regression from 3.1.6: `runP` is again exported from module
README.md view
@@ -19,9 +19,9 @@ thanks to Microsoft Research). * [Using Parsec](http://book.realworldhaskell.org/read/using-parsec.html), chapter 16 of [Real World Haskell](http://book.realworldhaskell.org/).-* [An introduction to the Parsec library](http://kunigami.wordpress.com/2014/01/21/an-introduction-to-the-parsec-library)+* [An introduction to the Parsec library](https://www.kuniga.me/blog/2014/01/21/an-introduction-to-the-parsec-library.html) on Kunigami's blog.-* [An introduction to parsing text in Haskell with Parsec](http://unbui.lt/#!/post/haskell-parsec-basics) on Wilson's blog.+* [An introduction to parsing text in Haskell with Parsec](https://jsdw.me/posts/haskell-parsec-basics/) on Wilson's blog. * Differences between Parsec and [Attoparsec](http://hackage.haskell.org/package/attoparsec) (Haskell's other prominent parser library) as explained in
parsec.cabal view
@@ -1,127 +1,179 @@-cabal-version: 1.12-name: parsec-version: 3.1.13.0+cabal-version: 1.12+name: parsec+version: 3.1.18.0+synopsis: Monadic parser combinators+description:+ Parsec is designed from scratch as an industrial-strength parser+ library. It is simple, safe, well documented (on the package+ homepage), has extensive libraries, good error messages,+ and is fast. It is defined as a monad transformer that can be+ stacked on arbitrary monads, and it is also parametric in the+ input stream type.+ .+ The main entry point is the "Text.Parsec" module which provides+ defaults for parsing 'Char'acter data.+ .+ The "Text.ParserCombinators.Parsec" module hierarchy contains+ the legacy @parsec-2@ API and may be removed at some point in+ the future. -synopsis: Monadic parser combinators-description: Parsec is designed from scratch as an industrial-strength parser- library. It is simple, safe, well documented (on the package- homepage), has extensive libraries, good error messages,- and is fast. It is defined as a monad transformer that can be- stacked on arbitrary monads, and it is also parametric in the- input stream type.- .- The main entry point is the "Text.Parsec" module which provides- defaults for parsing 'Char'acter data.- .- The "Text.ParserCombinators.Parsec" module hierarchy contains- the legacy @parsec-2@ API and may be removed at some point in- the future.+license: BSD2+license-file: LICENSE+author:+ Daan Leijen <daan@microsoft.com>, Paolo Martini <paolo@nemail.it>, Antoine Latter <aslatter@gmail.com> -license: BSD3-license-file: LICENSE-author: Daan Leijen <daan@microsoft.com>, Paolo Martini <paolo@nemail.it>, Antoine Latter <aslatter@gmail.com>-maintainer: Herbert Valerio Riedel <hvr@gnu.org>-homepage: https://github.com/hvr/parsec-bug-reports: https://github.com/hvr/parsec/issues-category: Parsing+maintainer:+ Oleg Grenrus <oleg.grenrus@iki.fi>, Herbert Valerio Riedel <hvr@gnu.org> -build-type: Simple-tested-with: GHC ==8.4.1 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2+homepage: https://github.com/haskell/parsec+bug-reports: https://github.com/haskell/parsec/issues+category: Parsing+build-type: Simple+tested-with:+ GHC ==8.6.5+ || ==8.8.4+ || ==8.10.7+ || ==9.0.2+ || ==9.2.8+ || ==9.4.8+ || ==9.6.4+ || ==9.8.2+ || ==9.10.1+ || ==9.12.1 -extra-source-files: ChangeLog.md, README.md+extra-source-files:+ ChangeLog.md+ README.md source-repository head- type: git- location: https://github.com/hvr/parsec+ type: git+ location: https://github.com/haskell/parsec library- hs-source-dirs: src- exposed-modules:- Text.Parsec- Text.Parsec.String- Text.Parsec.ByteString- Text.Parsec.ByteString.Lazy- Text.Parsec.Text- Text.Parsec.Text.Lazy- Text.Parsec.Pos- Text.Parsec.Error- Text.Parsec.Prim- Text.Parsec.Char- Text.Parsec.Combinator- Text.Parsec.Token- Text.Parsec.Expr- Text.Parsec.Language- Text.Parsec.Perm- Text.ParserCombinators.Parsec- Text.ParserCombinators.Parsec.Char- Text.ParserCombinators.Parsec.Combinator- Text.ParserCombinators.Parsec.Error- Text.ParserCombinators.Parsec.Expr- Text.ParserCombinators.Parsec.Language- Text.ParserCombinators.Parsec.Perm- Text.ParserCombinators.Parsec.Pos- Text.ParserCombinators.Parsec.Prim- Text.ParserCombinators.Parsec.Token+ hs-source-dirs: src+ exposed-modules:+ Text.Parsec+ Text.Parsec.ByteString+ Text.Parsec.ByteString.Lazy+ Text.Parsec.Char+ Text.Parsec.Combinator+ Text.Parsec.Error+ Text.Parsec.Expr+ Text.Parsec.Language+ Text.Parsec.Perm+ Text.Parsec.Pos+ Text.Parsec.Prim+ Text.Parsec.String+ Text.Parsec.Text+ Text.Parsec.Text.Lazy+ Text.Parsec.Token+ Text.ParserCombinators.Parsec+ Text.ParserCombinators.Parsec.Char+ Text.ParserCombinators.Parsec.Combinator+ Text.ParserCombinators.Parsec.Error+ Text.ParserCombinators.Parsec.Expr+ Text.ParserCombinators.Parsec.Language+ Text.ParserCombinators.Parsec.Perm+ Text.ParserCombinators.Parsec.Pos+ Text.ParserCombinators.Parsec.Prim+ Text.ParserCombinators.Parsec.Token - build-depends:- base >= 4.5.1 && < 4.12,- mtl >= 1.1.1 && < 2.3,- bytestring >= 0.9.2.1 && < 0.11,- text >= 0.11.3 && < 1.3+ build-depends:+ base >=4.12.0.0 && <4.22+ , bytestring >=0.10.8.2 && <0.13+ , mtl >=2.2.2 && <2.4+ , text >=1.2.3.0 && <1.3 || >=2.0 && <2.2 - default-language: Haskell2010- other-extensions:- CPP- DeriveDataTypeable- ExistentialQuantification- FlexibleContexts- FlexibleInstances- FunctionalDependencies- MultiParamTypeClasses- PolymorphicComponents- StandaloneDeriving- Safe- Trustworthy- UndecidableInstances+ default-language: Haskell2010+ other-extensions:+ CPP+ DeriveDataTypeable+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ MultiParamTypeClasses+ PolymorphicComponents+ Safe+ StandaloneDeriving+ Trustworthy+ UndecidableInstances - ghc-options: -Wall- if impl(ghc >= 8.0)- ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -Wno-trustworthy-safe- else- -- provide/emulate `Control.Monad.Fail` and `Semigroup` API for pre-GHC8- build-depends: fail == 4.9.*, semigroups == 0.18.*+ ghc-options: -Wall+ ghc-options:+ -Wcompat -Wnoncanonical-monad-instances -Wno-trustworthy-safe - if impl(ghc >= 7.10)- ghc-options: -fno-warn-trustworthy-safe+ if impl(ghc <8.8)+ ghc-options: -Wnoncanonical-monadfail-instances -test-suite parsec.- type: exitcode-stdio-1.0+-- these flags may abort compilation with GHC-8.10+-- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3295+-- https://gitlab.haskell.org/ghc/ghc/-/issues/22728+-- if impl(ghc >= 9.0)+-- -- ghc-options: -Winferred-safe-imports -Wmissing-safe-haskell-mode - hs-source-dirs: test- main-is: Main.hs- other-modules:- Bugs- Bugs.Bug2- Bugs.Bug6- Bugs.Bug9- Bugs.Bug35- Features- Features.Feature80- Util+test-suite parsec-tests+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ other-modules:+ Bugs+ Bugs.Bug2+ Bugs.Bug35+ Bugs.Bug6+ Bugs.Bug9+ Features+ Features.Feature150+ Features.Feature80+ Util - build-depends:- base,- mtl,- parsec,- -- dependencies whose version bounds are not inherited via lib:parsec- HUnit == 1.6.* || (>= 1.3.1.2 && < 1.4),- test-framework == 0.8.*,- test-framework-hunit == 0.3.*+ build-depends:+ base+ , mtl+ , parsec+ , tasty >=1.4 && <1.6+ , tasty-hunit >=0.10 && <0.11 - default-language: Haskell2010+ -- dependencies whose version bounds are not inherited via lib:parsec+ default-language: Haskell2010+ ghc-options: -Wall - ghc-options: -Wall- if impl(ghc >= 8.0)- ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances- else- build-depends: semigroups == 0.18.*+ if impl(ghc >=8.0)+ ghc-options:+ -Wcompat -Wnoncanonical-monad-instances+ -Wnoncanonical-monadfail-instances++ else+ build-depends: semigroups++test-suite parsec-issue127+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: issue127.hs+ hs-source-dirs: test+ build-depends:+ base+ , parsec++test-suite parsec-issue171+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: issue171.hs+ hs-source-dirs: test+ build-depends:+ base+ , deepseq+ , parsec+ , tasty+ , tasty-hunit++test-suite parsec-issue175+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: issue175.hs+ hs-source-dirs: test+ build-depends:+ base+ , parsec+ , tasty+ , tasty-hunit
src/Text/Parsec/ByteString.hs view
@@ -10,7 +10,7 @@ -- Stability : provisional -- Portability : portable ----- Convinience definitions for working with 'C.ByteString's.+-- Convenience definitions for working with 'C.ByteString's. -- ----------------------------------------------------------------------------- @@ -18,11 +18,11 @@ ( Parser, GenParser, parseFromFile ) where +import qualified Data.ByteString.Char8 as C+ import Text.Parsec.Error import Text.Parsec.Prim -import qualified Data.ByteString.Char8 as C- type Parser = Parsec C.ByteString () type GenParser t st = Parsec C.ByteString st @@ -36,7 +36,7 @@ -- > Right xs -> print (sum xs) -- > } -parseFromFile :: Parser a -> String -> IO (Either ParseError a)+parseFromFile :: Parser a -> FilePath -> IO (Either ParseError a) parseFromFile p fname = do input <- C.readFile fname return (runP p () fname input)
src/Text/Parsec/ByteString/Lazy.hs view
@@ -10,7 +10,7 @@ -- Stability : provisional -- Portability : portable ----- Convinience definitions for working with lazy 'C.ByteString's.+-- Convenience definitions for working with lazy 'C.ByteString's. -- ----------------------------------------------------------------------------- @@ -18,11 +18,11 @@ ( Parser, GenParser, parseFromFile ) where +import qualified Data.ByteString.Lazy.Char8 as C+ import Text.Parsec.Error import Text.Parsec.Prim -import qualified Data.ByteString.Lazy.Char8 as C- type Parser = Parsec C.ByteString () type GenParser t st = Parsec C.ByteString st @@ -35,7 +35,8 @@ -- > Left err -> print err -- > Right xs -> print (sum xs) -- > }-parseFromFile :: Parser a -> String -> IO (Either ParseError a)++parseFromFile :: Parser a -> FilePath -> IO (Either ParseError a) parseFromFile p fname = do input <- C.readFile fname return (runP p () fname input)
src/Text/Parsec/Char.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, FlexibleContexts, Safe #-}+{-# LANGUAGE FlexibleContexts, Safe #-} ----------------------------------------------------------------------------- -- |@@ -16,12 +16,10 @@ module Text.Parsec.Char where -import Data.Char+import Data.Char (isSpace, isUpper, isLower, isAlphaNum, isAlpha, isDigit, isHexDigit, isOctDigit)+ import Text.Parsec.Pos import Text.Parsec.Prim-#if !(MIN_VERSION_base(4,8,0))-import Control.Applicative ((*>))-#endif -- | @oneOf cs@ succeeds if the current character is in the supplied -- list of characters @cs@. Returns the parsed character. See also@@ -30,6 +28,7 @@ -- > vowel = oneOf "aeiou" oneOf :: (Stream s m Char) => [Char] -> ParsecT s u m Char+{-# INLINABLE oneOf #-} oneOf cs = satisfy (\c -> elem c cs) -- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current@@ -39,28 +38,33 @@ -- > consonant = noneOf "aeiou" noneOf :: (Stream s m Char) => [Char] -> ParsecT s u m Char+{-# INLINABLE noneOf #-} noneOf cs = satisfy (\c -> not (elem c cs)) -- | Skips /zero/ or more white space characters. See also 'skipMany'. spaces :: (Stream s m Char) => ParsecT s u m ()+{-# INLINABLE spaces #-} spaces = skipMany space <?> "white space" -- | Parses a white space character (any character which satisfies 'isSpace') -- Returns the parsed character. space :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE space #-} space = satisfy isSpace <?> "space" -- | Parses a newline character (\'\\n\'). Returns a newline character. newline :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE newline #-} newline = char '\n' <?> "lf new-line" -- | Parses a carriage return character (\'\\r\') followed by a newline character (\'\\n\'). -- Returns a newline character. crlf :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE crlf #-} crlf = char '\r' *> char '\n' <?> "crlf new-line" -- | Parses a CRLF (see 'crlf') or LF (see 'newline') end-of-line.@@ -70,52 +74,66 @@ -- endOfLine :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE endOfLine #-} endOfLine = newline <|> crlf <?> "new-line" -- | Parses a tab character (\'\\t\'). Returns a tab character. tab :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE tab #-} tab = char '\t' <?> "tab" -- | Parses an upper case letter (according to 'isUpper'). -- Returns the parsed character. upper :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE upper #-} upper = satisfy isUpper <?> "uppercase letter" -- | Parses a lower case character (according to 'isLower'). -- Returns the parsed character. lower :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE lower #-} lower = satisfy isLower <?> "lowercase letter" --- | Parses a letter or digit (a character between \'0\' and \'9\')+-- | Parses a alphabetic or numeric Unicode characters -- according to 'isAlphaNum'. Returns the parsed character.+--+-- Note that numeric digits outside the ASCII range (such as arabic-indic digits like e.g. \"٤\" or @U+0664@),+-- as well as numeric characters which aren't digits, are parsed by this function+-- but not by 'digit'. alphaNum :: (Stream s m Char => ParsecT s u m Char)+{-# INLINABLE alphaNum #-} alphaNum = satisfy isAlphaNum <?> "letter or digit" --- | Parses a letter (an upper case or lower case character according--- to 'isAlpha'). Returns the parsed character.+-- | Parses an alphabetic Unicode characters (lower-case, upper-case and title-case letters,+-- plus letters of caseless scripts and modifiers letters according to 'isAlpha').+-- Returns the parsed character. letter :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE letter #-} letter = satisfy isAlpha <?> "letter" --- | Parses a digit. Returns the parsed character.+-- | Parses an ASCII digit. Returns the parsed character. digit :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE digit #-} digit = satisfy isDigit <?> "digit" -- | Parses a hexadecimal digit (a digit or a letter between \'a\' and -- \'f\' or \'A\' and \'F\'). Returns the parsed character. hexDigit :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE hexDigit #-} hexDigit = satisfy isHexDigit <?> "hexadecimal digit" -- | Parses an octal digit (a character between \'0\' and \'7\'). Returns -- the parsed character. octDigit :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE octDigit #-} octDigit = satisfy isOctDigit <?> "octal digit" -- | @char c@ parses a single character @c@. Returns the parsed@@ -124,11 +142,13 @@ -- > semiColon = char ';' char :: (Stream s m Char) => Char -> ParsecT s u m Char+{-# INLINABLE char #-} char c = satisfy (==c) <?> show [c] -- | This parser succeeds for any character. Returns the parsed character. anyChar :: (Stream s m Char) => ParsecT s u m Char+{-# INLINABLE anyChar #-} anyChar = satisfy (const True) -- | The parser @satisfy f@ succeeds for any character for which the@@ -139,15 +159,31 @@ -- > oneOf cs = satisfy (\c -> c `elem` cs) satisfy :: (Stream s m Char) => (Char -> Bool) -> ParsecT s u m Char+{-# INLINABLE satisfy #-} satisfy f = tokenPrim (\c -> show [c]) (\pos c _cs -> updatePosChar pos c) (\c -> if f c then Just c else Nothing) --- | @string s@ parses a sequence of characters given by @s@. Returns+-- | @'string' s@ parses a sequence of characters given by @s@. Returns -- the parsed string (i.e. @s@). -- -- > divOrMod = string "div" -- > <|> string "mod"+--+-- Consider using 'string''. string :: (Stream s m Char) => String -> ParsecT s u m String+{-# INLINABLE string #-} string s = tokens show updatePosString s++-- | @'string'' s@ parses a sequence of characters given by @s@.+-- Doesn't consume matching prefix.+--+-- > carOrCdr = string' "car"+-- > <|> string' "cdr"+--+-- @since 3.1.16.0++string' :: (Stream s m Char) => String -> ParsecT s u m String+{-# INLINABLE string' #-}+string' s = tokens' show updatePosString s
src/Text/Parsec/Combinator.hs view
@@ -42,15 +42,17 @@ , parserTrace, parserTraced ) where -import Control.Monad-import Text.Parsec.Prim+import Control.Monad (mzero, liftM) import Debug.Trace (trace) +import Text.Parsec.Prim+ -- | @choice ps@ tries to apply the parsers in the list @ps@ in order, -- until one of them succeeds. Returns the value of the succeeding -- parser. choice :: (Stream s m t) => [ParsecT s u m a] -> ParsecT s u m a+{-# INLINABLE choice #-} choice ps = foldr (<|>) mzero ps -- | @option x p@ tries to apply parser @p@. If @p@ fails without@@ -62,6 +64,7 @@ -- > }) option :: (Stream s m t) => a -> ParsecT s u m a -> ParsecT s u m a+{-# INLINABLE option #-} option x p = p <|> return x -- | @optionMaybe p@ tries to apply parser @p@. If @p@ fails without@@ -69,6 +72,7 @@ -- 'Just' the value returned by @p@. optionMaybe :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m (Maybe a)+{-# INLINABLE optionMaybe #-} optionMaybe p = option Nothing (liftM Just p) -- | @optional p@ tries to apply parser @p@. It will parse @p@ or nothing.@@ -76,6 +80,7 @@ -- of @p@. optional :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m ()+{-# INLINABLE optional #-} optional p = do{ _ <- p; return ()} <|> return () -- | @between open close p@ parses @open@, followed by @p@ and @close@.@@ -85,6 +90,7 @@ between :: (Stream s m t) => ParsecT s u m open -> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a+{-# INLINABLE between #-} between open close p = do{ _ <- open; x <- p; _ <- close; return x } @@ -92,6 +98,7 @@ -- its result. skipMany1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m ()+{-# INLINABLE skipMany1 #-} skipMany1 p = do{ _ <- p; skipMany p } {- skipMany p = scan@@ -99,35 +106,20 @@ scan = do{ p; scan } <|> return () -} --- | @many1 p@ applies the parser @p@ /one/ or more times. Returns a--- list of the returned values of @p@.------ > word = many1 letter--many1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m [a]-many1 p = do{ x <- p; xs <- many p; return (x:xs) }-{--many p = scan id- where- scan f = do{ x <- p- ; scan (\tail -> f (x:tail))- }- <|> return (f [])--}-- -- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated -- by @sep@. Returns a list of values returned by @p@. -- -- > commaSep p = p `sepBy` (symbol ",") sepBy :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE sepBy #-} sepBy p sep = sepBy1 p sep <|> return [] -- | @sepBy1 p sep@ parses /one/ or more occurrences of @p@, separated -- by @sep@. Returns a list of values returned by @p@. sepBy1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE sepBy1 #-} sepBy1 p sep = do{ x <- p ; xs <- many (sep >> p) ; return (x:xs)@@ -139,6 +131,7 @@ -- returned by @p@. sepEndBy1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE sepEndBy1 #-} sepEndBy1 p sep = do{ x <- p ; do{ _ <- sep ; xs <- sepEndBy p sep@@ -154,6 +147,7 @@ -- > haskellStatements = haskellStatement `sepEndBy` semi sepEndBy :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE sepEndBy #-} sepEndBy p sep = sepEndBy1 p sep <|> return [] @@ -161,6 +155,7 @@ -- and ended by @sep@. Returns a list of values returned by @p@. endBy1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE endBy1 #-} endBy1 p sep = many1 (do{ x <- p; _ <- sep; return x }) -- | @endBy p sep@ parses /zero/ or more occurrences of @p@, separated@@ -169,6 +164,7 @@ -- > cStatements = cStatement `endBy` semi endBy :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]+{-# INLINABLE endBy #-} endBy p sep = many (do{ x <- p; _ <- sep; return x }) -- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or@@ -176,6 +172,7 @@ -- @n@ values returned by @p@. count :: (Stream s m t) => Int -> ParsecT s u m a -> ParsecT s u m [a]+{-# INLINABLE count #-} count n p | n <= 0 = return [] | otherwise = sequence (replicate n p) @@ -186,6 +183,7 @@ -- returned. chainr :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> a -> ParsecT s u m a+{-# INLINABLE chainr #-} chainr p op x = chainr1 p op <|> return x -- | @chainl p op x@ parses /zero/ or more occurrences of @p@,@@ -195,6 +193,7 @@ -- returned. chainl :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> a -> ParsecT s u m a+{-# INLINABLE chainl #-} chainl p op x = chainl1 p op <|> return x -- | @chainl1 p op@ parses /one/ or more occurrences of @p@,@@ -214,6 +213,7 @@ -- > <|> do{ symbol "-"; return (-) } chainl1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a+{-# INLINABLE chainl1 #-} chainl1 p op = do{ x <- p; rest x } where rest x = do{ f <- op@@ -228,6 +228,7 @@ -- by @p@. chainr1 :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a+{-# INLINABLE chainr1 #-} chainr1 p op = scan where scan = do{ x <- p; rest x }@@ -245,6 +246,7 @@ -- used to implement 'eof'. Returns the accepted token. anyToken :: (Stream s m t, Show t) => ParsecT s u m t+{-# INLINABLE anyToken #-} anyToken = tokenPrim show (\pos _tok _toks -> pos) Just -- | This parser only succeeds at the end of the input. This is not a@@ -253,6 +255,7 @@ -- > eof = notFollowedBy anyToken <?> "end of input" eof :: (Stream s m t, Show t) => ParsecT s u m ()+{-# INLINABLE eof #-} eof = notFollowedBy anyToken <?> "end of input" -- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser@@ -279,6 +282,7 @@ -- for more details. notFollowedBy :: (Stream s m t, Show a) => ParsecT s u m a -> ParsecT s u m ()+{-# INLINABLE notFollowedBy #-} notFollowedBy p = try (do{ c <- try p; unexpected (show c) } <|> return () )@@ -295,6 +299,7 @@ -- therefore the use of the 'try' combinator. manyTill :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]+{-# INLINABLE manyTill #-} manyTill p end = scan where scan = do{ _ <- end; return [] }@@ -311,6 +316,7 @@ -- -- @since 3.1.12.0 parserTrace :: (Show t, Stream s m t) => String -> ParsecT s u m ()+{-# INLINABLE parserTrace #-} parserTrace s = pt <|> return () where pt = try $ do@@ -332,6 +338,7 @@ -- -- @since 3.1.12.0 parserTraced :: (Stream s m t, Show t) => String -> ParsecT s u m b -> ParsecT s u m b+{-# INLINABLE parserTraced #-} parserTraced s p = do parserTrace s p <|> trace (s ++ " backtracked") (fail s)
src/Text/Parsec/Error.hs view
@@ -25,8 +25,10 @@ , mergeError ) where +import Control.Exception ( Exception ) import Data.List ( nub, sort ) import Data.Typeable ( Typeable )+import qualified Data.Monoid as Mon import Text.Parsec.Pos @@ -145,12 +147,17 @@ | null msgs2 && not (null msgs1) = e1 | null msgs1 && not (null msgs2) = e2 | otherwise- = case pos1 `compare` pos2 of+ -- perfectly we'd compare the consumed token count+ -- https://github.com/haskell/parsec/issues/175+ = case compareErrorPos pos1 pos2 of -- select the longest match EQ -> ParseError pos1 (msgs1 ++ msgs2) GT -> e1 LT -> e2 +compareErrorPos :: SourcePos -> SourcePos -> Ordering+compareErrorPos x y = Mon.mappend (compare (sourceLine x) (sourceLine y)) (compare (sourceColumn x) (sourceColumn y))+ instance Show ParseError where show err = show (errorPos err) ++ ":" ++@@ -164,6 +171,9 @@ where messageStrs = map messageString . errorMessages +-- | @since 3.1.17.0+instance Exception ParseError+ -- Language independent show function -- TODO@@ -189,12 +199,12 @@ showExpect = showMany msgExpecting expect showUnExpect = showMany msgUnExpected unExpect- showSysUnExpect | not (null unExpect) ||- null sysUnExpect = ""- | null firstMsg = msgUnExpected ++ " " ++ msgEndOfInput- | otherwise = msgUnExpected ++ " " ++ firstMsg- where- firstMsg = messageString (head sysUnExpect)+ showSysUnExpect+ | not (null unExpect) = ""+ | [] <- sysUnExpect = ""+ | msg : _ <- sysUnExpect+ , null (messageString msg) = msgUnExpected ++ " " ++ msgEndOfInput+ | msg : _ <- sysUnExpect = msgUnExpected ++ " " ++ messageString msg showMessages = showMany "" messages
src/Text/Parsec/Expr.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE Safe #-} @@ -46,9 +45,7 @@ data Operator s u m a = Infix (ParsecT s u m (a -> a -> a)) Assoc | Prefix (ParsecT s u m (a -> a)) | Postfix (ParsecT s u m (a -> a))-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )-#endif -- | An @OperatorTable s u m a@ is a list of @Operator s u m a@ -- lists. The list is ordered in descending@@ -96,6 +93,7 @@ => OperatorTable s u m a -> ParsecT s u m a -> ParsecT s u m a+{-# INLINABLE buildExpressionParser #-} buildExpressionParser operators simpleExpr = foldl (makeParser) simpleExpr operators where
src/Text/Parsec/Language.hs view
@@ -98,7 +98,7 @@ -- Haskell ----------------------------------------------------------- --- | A lexer for the haskell language.+-- | A lexer for the Haskell language. haskell :: TokenParser st haskell = makeTokenParser haskellDef@@ -135,7 +135,7 @@ -- Mondrian ----------------------------------------------------------- --- | A lexer for the mondrian language.+-- | A lexer for the Mondrian language. mondrian :: TokenParser st mondrian = makeTokenParser mondrianDef
src/Text/Parsec/Perm.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-}@@ -23,6 +22,12 @@ -- by Arthur Baars, Andres Loh and Doaitse Swierstra. -- Published as a functional pearl at the Haskell Workshop 2001. --+-- From the abstract: +--+-- A permutation phrase is a sequence of elements (possibly of different types) +-- in which each element occurs exactly once and the order is irrelevant. +-- Some of the permutable elements may be optional.+-- ----------------------------------------------------------------------------- @@ -35,15 +40,9 @@ , (<|?>), (<$?>) ) where -import Text.Parsec--import Control.Monad.Identity-#if MIN_VERSION_base(4,7,0)+import Control.Monad.Identity ( Identity ) import Data.Typeable ( Typeable )-#else--- For GHC 7.6-import Data.Typeable ( Typeable3 )-#endif+import Text.Parsec infixl 1 <||>, <|?> infixl 2 <$$>, <$?>@@ -131,20 +130,12 @@ -- using 'permute'. data StreamPermParser s st a = Perm (Maybe a) [StreamBranch s st a]-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )-#else-deriving instance Typeable3 StreamPermParser-#endif -- type Branch st a = StreamBranch String st a data StreamBranch s st a = forall b. Branch (StreamPermParser s st (b -> a)) (Parsec s st b)-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )-#else-deriving instance Typeable3 StreamBranch-#endif -- | The parser @permute perm@ parses a permutation of parser described -- by @perm@. For example, suppose we want to parse a permutation of:
src/Text/Parsec/Prim.hs view
@@ -53,6 +53,7 @@ , lookAhead , Stream(..) , tokens+ , tokens' , try , token , tokenPrim@@ -60,6 +61,7 @@ , many , skipMany , manyAccum+ , many1 , runPT , runP , runParserT@@ -99,15 +101,15 @@ import qualified Data.Monoid as Monoid ( Monoid(..) ) import qualified Control.Applicative as Applicative ( Applicative(..), Alternative(..), liftA2 )-import Control.Monad hiding (sequence)-import Control.Monad.Trans-import Control.Monad.Identity hiding (sequence)+import Control.Monad (MonadPlus (..), ap, void, liftM)+import Control.Monad.Trans (MonadTrans (lift), MonadIO (liftIO))+import Control.Monad.Identity (Identity, runIdentity) import qualified Control.Monad.Fail as Fail -import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Cont.Class-import Control.Monad.Error.Class+import Control.Monad.Reader.Class (MonadReader (..))+import Control.Monad.State.Class (MonadState (..))+import Control.Monad.Cont.Class (MonadCont (..))+import Control.Monad.Error.Class (MonadError (..)) import Text.Parsec.Pos import Text.Parsec.Error@@ -147,15 +149,12 @@ -> (ParseError -> m b) -- empty err -> m b }-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )- -- GHC 7.6 doesn't like deriving instances of Typeabl1 for types with- -- non-* type-arguments.-#endif -- | Low-level unpacking of the ParsecT type. To run your parser, please look to -- runPT, runP, runParserT, runParser and other such functions. runParsecT :: Monad m => ParsecT s u m a -> State s u -> m (Consumed (m (Reply s u a)))+{-# INLINABLE runParsecT #-} runParsecT p s = unParser p s cok cerr eok eerr where cok a s' err = return . Consumed . return $ Ok a s' err cerr err = return . Consumed . return $ Error err@@ -164,6 +163,7 @@ -- | Low-level creation of the ParsecT type. You really shouldn't have to do this. mkPT :: Monad m => (State s u -> m (Consumed (m (Reply s u a)))) -> ParsecT s u m a+{-# INLINABLE mkPT #-} mkPT k = ParsecT $ \s cok cerr eok eerr -> do cons <- k s case cons of@@ -218,11 +218,7 @@ -- discarding the first. (<>) = Applicative.liftA2 (Semigroup.<>) -#if MIN_VERSION_base(4,8,0) sconcat = fmap Semigroup.sconcat . sequence-#else- sconcat = fmap (Semigroup.sconcat . NE.fromList) . sequence . NE.toList-#endif stimes b = Semigroup.sconcat . NE.fromList . genericReplicate b -- | The 'Monoid' instance for 'ParsecT' is used for the same purposes as@@ -267,11 +263,19 @@ empty = mzero (<|>) = mplus + -- TODO: https://github.com/haskell/parsec/issues/179+ -- investigate what's wrong with haddock+ --+ -- many = many+ -- some = many1+ instance Monad (ParsecT s u m) where return = Applicative.pure p >>= f = parserBind p f (>>) = (Applicative.*>)+#if !MIN_VERSION_base(4,13,0) fail = Fail.fail+#endif -- | @since 3.1.12.0 instance Fail.MonadFail (ParsecT s u m) where@@ -314,9 +318,11 @@ = ParsecT $ \s cok cerr eok eerr -> let -- consumed-okay case for m- mcok x s err =+ mcok x s err+ | errorIsUnknown err = unParser (k x) s cok cerr cok cerr+ | otherwise = let- -- if (k x) consumes, those go straigt up+ -- if (k x) consumes, those go straight up pcok = cok pcerr = cerr @@ -331,7 +337,9 @@ in unParser (k x) s pcok pcerr peok peerr -- empty-ok case for m- meok x s err =+ meok x s err+ | errorIsUnknown err = unParser (k x) s cok cerr eok eerr+ | otherwise = let -- in these cases, (k x) can return as empty pcok = cok@@ -515,6 +523,46 @@ | tok == x -> walk toks xs | otherwise -> eerr $ errExpect x +-- | Like 'tokens', but doesn't consume matching prefix.+--+-- @since 3.1.16.0+tokens' :: (Stream s m t, Eq t)+ => ([t] -> String) -- Pretty print a list of tokens+ -> (SourcePos -> [t] -> SourcePos)+ -> [t] -- List of tokens to parse+ -> ParsecT s u m [t]+{-# INLINE tokens' #-}+tokens' _ _ []+ = ParsecT $ \s _ _ eok _ ->+ eok [] s $ unknownError s+tokens' showTokens nextposs tts@(tok:toks)+ = ParsecT $ \(State input pos u) cok _cerr _eok eerr ->+ let+ errEof = (setErrorMessage (Expect (showTokens tts))+ (newErrorMessage (SysUnExpect "") pos))++ errExpect x = (setErrorMessage (Expect (showTokens tts))+ (newErrorMessage (SysUnExpect (showTokens [x])) pos))++ walk [] rs = ok rs+ walk (t:ts) rs = do+ sr <- uncons rs+ case sr of+ Nothing -> eerr $ errEof+ Just (x,xs) | t == x -> walk ts xs+ | otherwise -> eerr $ errExpect x++ ok rs = let pos' = nextposs pos tts+ s' = State rs pos' u+ in cok tts s' (newErrorUnknown pos')+ in do+ sr <- uncons input+ case sr of+ Nothing -> eerr $ errEof+ Just (x,xs)+ | tok == x -> walk toks xs+ | otherwise -> eerr $ errExpect x+ -- | The parser @try p@ behaves like parser @p@, except that it -- pretends that it hasn't consumed any input when an error occurs. --@@ -584,6 +632,7 @@ -> (t -> SourcePos) -- ^ Computes the position of a token. -> (t -> Maybe a) -- ^ Matching function for the token to parse. -> Parsec s u a+{-# INLINABLE token #-} token showToken tokpos test = tokenPrim showToken nextpos test where nextpos _ tok ts = case runIdentity (uncons ts) of@@ -665,6 +714,15 @@ = do xs <- manyAccum (:) p return (reverse xs) +-- | @many1 p@ applies the parser @p@ /one/ or more times. Returns a+-- list of the returned values of @p@.+--+-- > word = many1 letter++many1 :: ParsecT s u m a -> ParsecT s u m [a]+{-# INLINABLE many1 #-}+many1 p = do{ x <- p; xs <- many p; return (x:xs) }+ -- | @skipMany p@ applies the parser @p@ /zero/ or more times, skipping -- its result. --@@ -696,6 +754,7 @@ runPT :: (Stream s m t) => ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)+{-# INLINABLE runPT #-} runPT p u name s = do res <- runParsecT p (State s (initialPos name) u) r <- parserReply res
src/Text/Parsec/String.hs view
@@ -33,7 +33,7 @@ -- > Left err -> print err -- > Right xs -> print (sum xs) -- > }-parseFromFile :: Parser a -> String -> IO (Either ParseError a)+parseFromFile :: Parser a -> FilePath -> IO (Either ParseError a) parseFromFile p fname = do input <- readFile fname return (runP p () fname input)
src/Text/Parsec/Text.hs view
@@ -10,16 +10,36 @@ -- Stability : provisional -- Portability : portable ----- Convinience definitions for working with 'Text.Text'.+-- Convenience definitions for working with 'Text.Text'. -- ----------------------------------------------------------------------------- module Text.Parsec.Text- ( Parser, GenParser+ ( Parser, GenParser, parseFromFile ) where import qualified Data.Text as Text+import qualified Data.Text.IO as T+ import Text.Parsec.Prim+import Text.Parsec.Error type Parser = Parsec Text.Text () type GenParser st = Parsec Text.Text st++-- | @parseFromFile p filePath@ runs a strict text parser @p@ on the+-- input read from @filePath@ using 'Data.Text.IO.readFile'. Returns either a 'ParseError'+-- ('Left') or a value of type @a@ ('Right').+--+-- > main = do{ result <- parseFromFile numbers "digits.txt"+-- > ; case result of+-- > Left err -> print err+-- > Right xs -> print (sum xs)+-- > }+--+-- @since 3.1.14.0++parseFromFile :: Parser a -> FilePath -> IO (Either ParseError a)+parseFromFile p fname+ = do input <- T.readFile fname+ return (runP p () fname input)
src/Text/Parsec/Text/Lazy.hs view
@@ -15,11 +15,31 @@ ----------------------------------------------------------------------------- module Text.Parsec.Text.Lazy- ( Parser, GenParser+ ( Parser, GenParser, parseFromFile ) where import qualified Data.Text.Lazy as Text+import qualified Data.Text.Lazy.IO as TL+ import Text.Parsec.Prim+import Text.Parsec.Error type Parser = Parsec Text.Text () type GenParser st = Parsec Text.Text st++-- | @parseFromFile p filePath@ runs a strict text parser @p@ on the+-- input read from @filePath@ using 'Data.Text.Lazy.IO.readFile'. Returns either a 'ParseError'+-- ('Left') or a value of type @a@ ('Right').+--+-- > main = do{ result <- parseFromFile numbers "digits.txt"+-- > ; case result of+-- > Left err -> print err+-- > Right xs -> print (sum xs)+-- > }+--+-- @since 3.1.14.0++parseFromFile :: Parser a -> FilePath -> IO (Either ParseError a)+parseFromFile p fname+ = do input <- TL.readFile fname+ return (runP p () fname input)
src/Text/Parsec/Token.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE PolymorphicComponents #-} {-# LANGUAGE Safe #-}@@ -30,11 +28,10 @@ ) where import Data.Char ( isAlpha, toLower, toUpper, isSpace, digitToInt )-#if MIN_VERSION_base(4,7,0) import Data.Typeable ( Typeable )-#endif import Data.List ( nub, sort )-import Control.Monad.Identity+import Control.Monad.Identity (Identity)+ import Text.Parsec.Prim import Text.Parsec.Char import Text.Parsec.Combinator@@ -106,9 +103,7 @@ caseSensitive :: Bool }-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )-#endif ----------------------------------------------------------- -- A first class module: TokenParser@@ -171,7 +166,7 @@ stringLiteral :: ParsecT s u m String, - -- | This lexeme parser parses a natural number (a positive whole+ -- | This lexeme parser parses a natural number (a non-negative whole -- number). Returns the value of the number. The number can be -- specified in 'decimal', 'hexadecimal' or -- 'octal'. The number is parsed according to the grammar@@ -201,19 +196,19 @@ naturalOrFloat :: ParsecT s u m (Either Integer Double), - -- | Parses a positive whole number in the decimal system. Returns the+ -- | Parses a non-negative whole number in the decimal system. Returns the -- value of the number. decimal :: ParsecT s u m Integer, - -- | Parses a positive whole number in the hexadecimal system. The number- -- should be prefixed with \"0x\" or \"0X\". Returns the value of the+ -- | Parses a non-negative whole number in the hexadecimal system. The+ -- number should be prefixed with \"x\" or \"X\". Returns the value of the -- number. hexadecimal :: ParsecT s u m Integer, - -- | Parses a positive whole number in the octal system. The number- -- should be prefixed with \"0o\" or \"0O\". Returns the value of the+ -- | Parses a non-negative whole number in the octal system. The number+ -- should be prefixed with \"o\" or \"O\". Returns the value of the -- number. octal :: ParsecT s u m Integer,@@ -316,9 +311,7 @@ commaSep1 :: forall a . ParsecT s u m a -> ParsecT s u m [a] }-#if MIN_VERSION_base(4,7,0) deriving ( Typeable )-#endif ----------------------------------------------------------- -- Given a LanguageDef, create a token parser.@@ -329,7 +322,7 @@ -- defined using the definitions in the @language@ record. -- -- The use of this function is quite stylized - one imports the--- appropiate language definition and selects the lexical parsers that+-- appropriate language definition and selects the lexical parsers that -- are needed from the resulting 'GenTokenParser'. -- -- > module Main where@@ -357,6 +350,7 @@ makeTokenParser :: (Stream s m Char) => GenLanguageDef s u m -> GenTokenParser s u m+{-# INLINABLE makeTokenParser #-} makeTokenParser languageDef = TokenParser{ identifier = identifier , reserved = reserved
src/Text/ParserCombinators/Parsec/Expr.hs view
@@ -25,7 +25,7 @@ import qualified Text.Parsec.Expr as N import Text.ParserCombinators.Parsec(GenParser) -import Control.Monad.Identity+import Control.Monad.Identity (Identity) data Operator tok st a = Infix (GenParser tok st (a -> a -> a)) Assoc | Prefix (GenParser tok st (a -> a))
test/Bugs.hs view
@@ -3,14 +3,14 @@ ( bugs ) where -import Test.Framework+import Test.Tasty import qualified Bugs.Bug2 import qualified Bugs.Bug6 import qualified Bugs.Bug9 import qualified Bugs.Bug35 -bugs :: [Test]+bugs :: [TestTree] bugs = [ Bugs.Bug2.main , Bugs.Bug6.main , Bugs.Bug9.main
test/Bugs/Bug2.hs view
@@ -3,16 +3,15 @@ ( main ) where -import Test.HUnit hiding ( Test )-import Test.Framework-import Test.Framework.Providers.HUnit+import Test.Tasty+import Test.Tasty.HUnit import Text.Parsec import Text.Parsec.String import qualified Text.Parsec.Token as P import Text.Parsec.Language (haskellDef) -main :: Test+main :: TestTree main = testCase "Control Char Parsing (#2)" $ parseString "\"test\\^Bstring\"" @?= "test\^Bstring"
test/Bugs/Bug35.hs view
@@ -6,9 +6,8 @@ import Text.Parsec.String import qualified Text.Parsec.Token as Token -import Test.HUnit hiding (Test)-import Test.Framework-import Test.Framework.Providers.HUnit+import Test.Tasty+import Test.Tasty.HUnit trickyFloats :: [String] trickyFloats =@@ -36,5 +35,5 @@ testBatch = mapM_ testFloat trickyFloats where testFloat x = parse float "" x @?= Right (read x :: Double) -main :: Test+main :: TestTree main = testCase "Quality of output of Text.Parsec.Token.float (#35)" testBatch
test/Bugs/Bug6.hs view
@@ -3,16 +3,15 @@ ( main ) where -import Test.HUnit hiding ( Test )-import Test.Framework-import Test.Framework.Providers.HUnit+import Test.Tasty+import Test.Tasty.HUnit import Text.Parsec import Text.Parsec.String import Util -main :: Test+main :: TestTree main = testCase "Look-ahead preserving error location (#6)" $ parseErrors variable "return" @?= ["'return' is a reserved keyword"]
test/Bugs/Bug9.hs view
@@ -7,16 +7,15 @@ import Text.Parsec.String (Parser) import qualified Text.Parsec.Token as P -import Test.Framework-import Test.Framework.Providers.HUnit-import Test.HUnit hiding (Test)+import Test.Tasty+import Test.Tasty.HUnit import Util data Expr = Const Integer | Op Expr Expr deriving Show -main :: Test+main :: TestTree main = testCase "Tracing of current position in error message (#9)" $ result @?= ["unexpected '>'","expecting operator or end of input"]@@ -25,7 +24,7 @@ result :: [String] result = parseErrors parseTopLevel "4 >> 5" --- Syntax analaysis+-- Syntax analysis parseTopLevel :: Parser Expr parseTopLevel = parseExpr <* eof
test/Features.hs view
@@ -2,11 +2,13 @@ ( features ) where -import Test.Framework+import Test.Tasty import qualified Features.Feature80+import qualified Features.Feature150 -features :: [Test]-features = [- Features.Feature80.main- ]+features :: [TestTree]+features =+ [ Features.Feature80.main+ , Features.Feature150.main+ ]
+ test/Features/Feature150.hs view
@@ -0,0 +1,46 @@+module Features.Feature150 ( main ) where++import Control.Applicative ((*>))+import Control.Monad.Identity+import Test.Tasty+import Test.Tasty.HUnit++import Text.Parsec++main :: TestTree+main =+ testCase "string' (#150)" $ do+ parseString (boot <|> bool) "boot" @?= "boot"+ parseFail (boot <|> bool) "bool" @?= "no parse"+ parseFail (boot <|> bool) "booz" @?= "no parse"++ parseString (boot' <|> bool') "boot" @?= "boot"+ parseString (boot' <|> bool') "bool" @?= "bool"+ parseFail (boot' <|> bool') "booz" @?= "no parse"++ parseString (boot' <|> bool' <|> char 'b' *> many anyChar) "boomerang" @?= "oomerang"++ where+ boot :: ParsecT String () Identity String+ boot = string "boot"++ bool :: ParsecT String () Identity String+ bool = string "bool"++ boot' :: ParsecT String () Identity String+ boot' = string' "boot"++ bool' :: ParsecT String () Identity String+ bool' = string' "bool"++ parseString :: ParsecT String () Identity String -> String -> String+ parseString p input =+ case parse p "Example" input of+ Left{} -> error "Parse failure"+ Right str -> str++ parseFail :: ParsecT String () Identity String -> String -> String+ parseFail p input =+ case parse p "Example" input of+ Left{} -> "no parse"+ Right _ -> error "Parsed but shouldn't"
test/Features/Feature80.hs view
@@ -4,13 +4,12 @@ import Control.Monad.Identity import Data.List.NonEmpty import Data.Semigroup-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.HUnit hiding (Test)+import Test.Tasty+import Test.Tasty.HUnit import Text.Parsec -main :: Test+main :: TestTree main = testCase "Monoid instance (#80)" $ do parseString (as <> bs) "aabbb" @?= "aabbb"
test/Main.hs view
@@ -1,12 +1,12 @@ -import Test.Framework+import Test.Tasty import Bugs ( bugs ) import Features ( features ) main :: IO () main = do- defaultMain+ defaultMain $ testGroup "All" [ testGroup "Bugs" bugs , testGroup "Features" features ]
+ test/issue127.hs view
@@ -0,0 +1,14 @@+-- this should run in constant memory+module Main (main) where+ +import Text.Parsec+import System.Environment (getArgs)+import Control.Monad (replicateM_)++main :: IO ()+main = do+ n <- getArgs >>= \args -> return $ case args of+ arg : _ -> read arg+ _ -> 1000000++ print $ runParser (replicateM_ n $ return ()) () "test" ""
+ test/issue171.hs view
@@ -0,0 +1,29 @@+-- this should be fast+module Main (main) where++import Control.DeepSeq (NFData (..))+import System.CPUTime (getCPUTime)+import Text.Printf (printf)+import Test.Tasty (defaultMain)+import Test.Tasty.HUnit (testCaseSteps, assertBool)++import Text.Parsec+import Text.Parsec.String (Parser)++main :: IO ()+main = defaultMain $ testCaseSteps "issue-171" $ \info -> do+ time0 <- getCPUTime+ check $ concat $ replicate 100000 "a "+ time1 <- getCPUTime+ let diff = (time1 - time0) `div` 1000000000+ info $ printf "%d milliseconds\n" diff+ assertBool "" (diff < 200)++parser :: Parser [String]+parser = many (char 'a' <|> char 'b') `sepBy` char ' '++check :: String -> IO ()+check s = putStrLn $ either onError (const "") $ parse parser {- important: pass input as SourceName -} s s++onError :: ParseError -> String+onError err = rnf (show err) `seq` "error"
+ test/issue175.hs view
@@ -0,0 +1,26 @@+module Main (main) where++import Text.Parsec+import Text.Parsec.Error+import Text.Parsec.String (Parser)+import Text.Parsec.Pos (newPos)++import Test.Tasty (defaultMain)+import Test.Tasty.HUnit (assertFailure, testCaseSteps, (@?=))++main :: IO ()+main = defaultMain $ testCaseSteps "issue175" $ \info -> do+ case parse p "" "x" of+ Right _ -> assertFailure "Unexpected success"+ -- with setPosition the "longest match" is arbitrary+ -- megaparsec tracks consumed tokens separately, but we don't.+ -- so our position is arbitrary.+ Left err -> do+ info $ show err+ errorPos err @?= newPos "aaa" 9 1 -- can be arbitrary+ length (errorMessages err) @?= 2++p :: Parser Char+p = p1 <|> p2 where+ p1 = setPosition (newPos "aaa" 9 1) >> char 'a'+ p2 = setPosition (newPos "zzz" 1 1) >> char 'b'