packages feed

parsec 3.1.16.1 → 3.1.17.0

raw patch · 8 files changed

+112/−25 lines, 8 filesdep +deepseqdep ~basedep ~bytestringdep ~tasty

Dependencies added: deepseq

Dependency ranges changed: base, bytestring, tasty, tasty-hunit, text

Files

ChangeLog.md view
@@ -1,3 +1,12 @@+### 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.
parsec.cabal view
@@ -1,6 +1,6 @@ cabal-version:  1.12 name:           parsec-version:        3.1.16.1+version:        3.1.17.0  synopsis:       Monadic parser combinators description:    Parsec is designed from scratch as an industrial-strength parser@@ -26,7 +26,7 @@ category:       Parsing  build-type:     Simple-tested-with:    GHC ==9.2.2 || ==9.0.2 || ==8.10.7 || ==8.8.4 || ==8.6.5 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2+tested-with:    GHC ==9.8.1 || ==9.6.2 || ==9.4.7 || ==9.2.8 || ==9.0.2 || ==8.10.7 || ==8.8.4 || ==8.6.5 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2  extra-source-files: ChangeLog.md, README.md @@ -64,11 +64,11 @@         Text.ParserCombinators.Parsec.Token      build-depends:-        base       >= 4.5.1.0 && < 4.19,+        base       >= 4.5.1.0 && < 4.20,         mtl        >= 2.1.3.1 && < 2.4,-        bytestring >= 0.9.2.1 && < 0.12,+        bytestring >= 0.9.2.1 && < 0.13,         text      (>= 1.2.3.0  && < 1.3)-               || (>= 2.0 && < 2.1)+               || (>= 2.0 && < 2.2)      default-language: Haskell2010     other-extensions:@@ -124,7 +124,7 @@         mtl,         parsec,         -- dependencies whose version bounds are not inherited via lib:parsec-        tasty >= 1.4 && < 1.5,+        tasty >= 1.4 && < 1.6,         tasty-hunit >= 0.10 && < 0.11      default-language: Haskell2010@@ -141,3 +141,17 @@     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, tasty, tasty-hunit, deepseq, parsec++test-suite parsec-issue175+    default-language: Haskell2010+    type: exitcode-stdio-1.0+    main-is: issue175.hs+    hs-source-dirs: test+    build-depends: base, tasty, tasty-hunit, parsec
src/Text/Parsec/Combinator.hs view
@@ -106,24 +106,6 @@                       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]-{-# INLINABLE many1 #-}-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@. --
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) ++ ":" ++@@ -163,6 +170,9 @@         = errorPos l == errorPos r && messageStrs l == messageStrs r         where           messageStrs = map messageString . errorMessages++-- | @since 3.1.17.0+instance Exception ParseError  -- Language independent show function 
src/Text/Parsec/Prim.hs view
@@ -61,6 +61,7 @@     , many     , skipMany     , manyAccum+    , many1     , runPT     , runP     , runParserT@@ -270,6 +271,12 @@     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@@ -714,6 +721,15 @@ many p   = 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.
test/issue127.hs view
@@ -1,3 +1,4 @@+-- this should run in constant memory module Main (main) where    import Text.Parsec
+ 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'