packages feed

paripari 0.3.0.0 → 0.4.0.0

raw patch · 10 files changed

+109/−65 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.PariPari: asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8
- Text.PariPari.Internal.Acceptor: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Monoid a) => GHC.Base.Monoid (Text.PariPari.Internal.Acceptor.Acceptor k a)
- Text.PariPari.Internal.CharCombinators: scanCharsWhile :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
- Text.PariPari.Internal.CharCombinators: scanCharsWhile1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
- Text.PariPari.Internal.Class: asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8
- Text.PariPari.Internal.ElementCombinators: scanElementsWhile :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
- Text.PariPari.Internal.ElementCombinators: scanElementsWhile1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
- Text.PariPari.Internal.Reporter: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Monoid a) => GHC.Base.Monoid (Text.PariPari.Internal.Reporter.Reporter k a)
+ Text.PariPari: asciiScan :: CharParser k p => (Word8 -> Maybe a) -> p a
+ Text.PariPari.Internal.Acceptor: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Text.PariPari.Internal.Acceptor.Acceptor k a)
+ Text.PariPari.Internal.CharCombinators: asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8
+ Text.PariPari.Internal.CharCombinators: scanChars :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.CharCombinators: scanChars1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.Class: asciiScan :: CharParser k p => (Word8 -> Maybe a) -> p a
+ Text.PariPari.Internal.ElementCombinators: scanElements :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.ElementCombinators: scanElements1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.Reporter: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Text.PariPari.Internal.Reporter.Reporter k a)

Files

paripari.cabal view
@@ -2,12 +2,12 @@ -- -- see: https://github.com/sol/hpack ----- hash: 78092995723d296e73be8c5403a8bf6c7b46bece1826eb1e0841683e3252071d+-- hash: 9f4767161c726109fa8849cc08f350e49f03eeef59675e9c770da1f6bd959ab8  name:           paripari-version:        0.3.0.0+version:        0.4.0.0 synopsis:       Parser combinators with fast-path and slower fallback for error reporting-description:    PariPari offers two parsing strategies. There is a fast Acceptor and a slower Reporter which are evaluated in parallel. If the Acceptor fails, the Reporter returns a report about the parsing errors. Unlike Parsec and like Attoparsec, the parser combinators backtrack by default.+description:    PariPari offers two parsing strategies. There is a fast Acceptor and a slower Reporter which are evaluated in parallel. If the Acceptor fails, the Reporter returns a report about the parsing errors. Like Attoparsec, the parser combinators backtrack by default. category:       Text stability:      experimental homepage:       https://github.com/minad/paripari#readme@@ -17,7 +17,7 @@ copyright:      2018 Daniel Mendler license:        MIT license-file:   LICENSE-tested-with:    GHC == 8.4.3, GHC == 8.6.1+tested-with:    GHC == 8.0.1, GHC == 8.2.1, GHC == 8.4.3, GHC == 8.6.1 build-type:     Simple cabal-version:  >= 1.10 @@ -40,7 +40,7 @@       Paths_paripari   hs-source-dirs:       src-  ghc-options: -Wall -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11@@ -52,7 +52,7 @@   main-is: example.hs   other-modules:       Paths_paripari-  ghc-options: -Wall -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11@@ -65,7 +65,7 @@   main-is: specialise-all.hs   other-modules:       Paths_paripari-  ghc-options: -Wall -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11@@ -81,7 +81,7 @@       Paths_paripari   hs-source-dirs:       test-  ghc-options: -Wall -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11
specialise-all.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE Rank2Types #-}  import System.Environment (getArgs)+import Data.Semigroup ((<>)) import Text.PariPari import qualified Data.Char as C import qualified Data.List.NonEmpty as NE
src/Text/PariPari/Internal/Acceptor.hs view
@@ -15,6 +15,7 @@ ) where  import Control.Monad (void)+import Data.Semigroup as Sem import Data.String (IsString(..)) import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class@@ -43,14 +44,17 @@                -> b   } -instance (Chunk k, Semigroup a) => Semigroup (Acceptor k a) where+instance (Chunk k, Semigroup a) => Sem.Semigroup (Acceptor k a) where   p1 <> p2 = (<>) <$> p1 <*> p2   {-# INLINE (<>) #-} -instance (Chunk k, Monoid a) => Monoid (Acceptor k a) where+instance (Chunk k, Semigroup a, Monoid a) => Monoid (Acceptor k a) where   mempty = pure mempty   {-# INLINE mempty #-} +  mappend = (<>)+  {-# INLINE mappend #-}+ instance Functor (Acceptor k) where   fmap f p = Acceptor $ \env st ok err ->     unAcceptor p env st (ok . f) err@@ -212,19 +216,19 @@           err $ ECombinator "char"   {-# INLINE char #-} -  asciiSatisfy f = Acceptor $ \env st@State{_stOff, _stLine, _stCol} ok err ->+  asciiScan f = Acceptor $ \env st@State{_stOff, _stLine, _stCol} ok err ->     if | b <- byteAt @k (_envBuf env) _stOff,          b /= 0,          b < 128,-         f b ->-           ok b st+         Just x <- f b ->+           ok x st            { _stOff = _stOff + 1            , _stLine = if b == asc_newline then _stLine + 1 else _stLine            , _stCol = if b == asc_newline then 1 else _stCol + 1            }        | otherwise ->-           err $ ECombinator "asciiSatisfy"-  {-# INLINE asciiSatisfy #-}+           err $ ECombinator "asciiScan"+  {-# INLINE asciiScan #-}    asciiByte 0 = error "Character '\\0' cannot be parsed because it is used as sentinel"   asciiByte b
src/Text/PariPari/Internal/CharCombinators.hs view
@@ -27,14 +27,15 @@   , spaceChar   , asciiChar   , satisfy+  , asciiSatisfy   , skipChars   , takeChars   , skipCharsWhile   , takeCharsWhile   , skipCharsWhile1   , takeCharsWhile1-  , scanCharsWhile-  , scanCharsWhile1+  , scanChars+  , scanChars1   , string ) where @@ -42,6 +43,7 @@ import Control.Monad.Combinators (option, skipCount, skipMany) import Data.Functor (void) import Data.Maybe (fromMaybe)+import Data.Semigroup ((<>)) import Data.Word (Word8) import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class@@ -303,11 +305,16 @@ satisfy f = scan $ \c -> if f c then Just c else Nothing {-# INLINE satisfy #-} -scanCharsWhile :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s-scanCharsWhile f = go+-- | Parse a single character within the ASCII charset with the given predicate+asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8+asciiSatisfy f = asciiScan $ \b -> if f b then Just b else Nothing+{-# INLINE asciiSatisfy #-}++scanChars :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s+scanChars f = go   where go s = (scan (f s) >>= go) <|> pure s-{-# INLINE scanCharsWhile #-}+{-# INLINE scanChars #-} -scanCharsWhile1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s-scanCharsWhile1 f s = scan (f s) >>= scanCharsWhile f-{-# INLINE scanCharsWhile1 #-}+scanChars1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s+scanChars1 f s = scan (f s) >>= scanChars f+{-# INLINE scanChars1 #-}
src/Text/PariPari/Internal/Chunk.hs view
@@ -16,6 +16,7 @@ import Data.Bits (unsafeShiftL, (.|.), (.&.)) import Data.ByteString (ByteString) import Data.Foldable (foldl')+import Data.Semigroup ((<>)) import Data.String (fromString) import Data.Text (Text) import Data.Word (Word8)
src/Text/PariPari/Internal/Class.hs view
@@ -17,6 +17,7 @@ import Control.Monad (MonadPlus(..)) import Control.Monad.Fail (MonadFail(..)) import Data.List (intercalate)+import Data.Semigroup ((<>)) import Data.String (IsString) import Data.Word (Word8) import GHC.Generics (Generic)@@ -89,7 +90,7 @@   -- | Parse a single element   element :: Element k -> p (Element k) -  -- | Scan a single byte+  -- | Scan a single element   elementScan :: (Element k -> Maybe a) -> p a    -- | Parse a chunk of elements. The chunk must not@@ -120,11 +121,11 @@   -- since it is used as decoding sentinel. Use 'element' instead.   asciiByte :: Word8 -> p Word8 -  -- | Parse a single character within the ASCII charset with the given predicate+  -- | Scan a single character within the ASCII charset   --   -- __Note__: The character '\0' cannot be parsed using this combinator-  -- since it is used as decoding sentinel. Use 'elementSatisfy' instead.-  asciiSatisfy :: (Word8 -> Bool) -> p Word8+  -- since it is used as decoding sentinel. Use 'elementScan' instead.+  asciiScan :: (Word8 -> Maybe a) -> p a  -- | Pretty string representation of 'Error' showError :: Error -> String
src/Text/PariPari/Internal/ElementCombinators.hs view
@@ -55,14 +55,15 @@   , takeElementsWhile   , skipElementsWhile1   , takeElementsWhile1-  , scanElementsWhile-  , scanElementsWhile1+  , scanElements+  , scanElements1 ) where  import Control.Applicative ((<|>), empty) import Control.Monad (when) import Control.Monad.Combinators (skipCount, skipMany) import Data.Functor (void)+import Data.Semigroup ((<>)) import Prelude hiding (getLine) import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class@@ -146,12 +147,12 @@ linefold = line <|> indented {-# INLINE linefold #-} --- | Parser a single byte different from the given one+-- | Parser a single element different from the given one notElement :: forall k p. ChunkParser k p => Element k -> p (Element k) notElement e = elementSatisfy @k (/= e) <?> "not " <> showElement @k e {-# INLINE notElement #-} --- | Parse an arbitrary byte+-- | Parse an arbitrary element anyElement :: ChunkP k (Element k) anyElement = elementSatisfy (const True) {-# INLINE anyElement #-}@@ -186,16 +187,16 @@ takeElementsWhile1 f = asChunk (skipElementsWhile1 f) {-# INLINE takeElementsWhile1 #-} --- | Parse a single byte with the given predicate+-- | Parse a single element with the given predicate elementSatisfy :: ChunkParser k p => (Element k -> Bool) -> p (Element k) elementSatisfy f = elementScan $ \e -> if f e then Just e else Nothing {-# INLINE elementSatisfy #-} -scanElementsWhile :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s-scanElementsWhile f = go+scanElements :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s+scanElements f = go   where go s = (elementScan (f s) >>= go) <|> pure s-{-# INLINE scanElementsWhile #-}+{-# INLINE scanElements #-} -scanElementsWhile1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s-scanElementsWhile1 f s = elementScan (f s) >>= scanElementsWhile f-{-# INLINE scanElementsWhile1 #-}+scanElements1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s+scanElements1 f s = elementScan (f s) >>= scanElements f+{-# INLINE scanElements1 #-}
src/Text/PariPari/Internal/Reporter.hs view
@@ -28,6 +28,7 @@ import Data.Function (on) import Data.List (intercalate, sort, group, sortOn) import Data.List.NonEmpty (NonEmpty(..))+import Data.Semigroup as Sem import Data.String (IsString(..)) import GHC.Generics (Generic) import Text.PariPari.Internal.Chunk@@ -86,14 +87,17 @@                -> b   } -instance (Chunk k, Semigroup a) => Semigroup (Reporter k a) where+instance (Chunk k, Semigroup a) => Sem.Semigroup (Reporter k a) where   p1 <> p2 = (<>) <$> p1 <*> p2   {-# INLINE (<>) #-} -instance (Chunk k, Monoid a) => Monoid (Reporter k a) where+instance (Chunk k, Semigroup a, Monoid a) => Monoid (Reporter k a) where   mempty = pure mempty   {-# INLINE mempty #-} +  mappend = (<>)+  {-# INLINE mappend #-}+ instance Chunk k => Functor (Reporter k) where   fmap f p = Reporter $ \env st ok err ->     unReporter p env st (ok . f) err@@ -262,12 +266,12 @@           raiseError env st err $ EExpected [show c]   {-# INLINE char #-} -  asciiSatisfy f = Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->+  asciiScan f = Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->     let b = byteAt @k (_envBuf env) _stOff     in if | b /= 0,             b < 128,-            f b ->-              ok b st+            Just x <- f b ->+              ok x st               { _stOff = _stOff + 1               , _stLine = if b == asc_newline then _stLine + 1 else _stLine               , _stCol = if b == asc_newline then 1 else _stCol + 1@@ -276,7 +280,7 @@               raiseError env st err unexpectedEnd           | otherwise ->               raiseError env st err $ EUnexpected $ showByte b-  {-# INLINE asciiSatisfy #-}+  {-# INLINE asciiScan #-}    asciiByte 0 = error "Character '\\0' cannot be parsed because it is used as sentinel"   asciiByte b
src/Text/PariPari/Internal/Tracer.hs view
@@ -9,6 +9,7 @@   , runTracer ) where +import Data.Semigroup as Sem import Data.String (IsString) import Debug.Trace (trace) import Text.PariPari.Internal.Chunk@@ -18,7 +19,7 @@  -- | Parser which prints trace messages, when backtracking occurs. newtype Tracer k a = Tracer { unTracer :: Reporter k a }-  deriving (Semigroup, Monoid, Functor, Applicative, MonadPlus, Monad, Fail.MonadFail)+  deriving (Sem.Semigroup, Monoid, Functor, Applicative, MonadPlus, Monad, Fail.MonadFail)  deriving instance CharChunk k => ChunkParser k (Tracer k) deriving instance CharChunk k => CharParser k (Tracer k)
test/test.hs view
@@ -82,20 +82,26 @@         s <- randomString         ok (traverse char s *> eof) s () -    , testCase "asciiSatisfy" $ do-        ok (asciiSatisfy (== asc_a)) "abc" asc_a-        ok (asciiSatisfy (== asc_a) <* eof) "a" asc_a-        err (asciiSatisfy (== asc_0)) "abc"-        err (asciiSatisfy (== asc_0)) ""+    , testCase "scan" $ do+        ok (scan (\c -> if c == 'a' then Just c else Nothing)) "abc" 'a'+        ok (scan (\c -> if c == 'a' then Just c else Nothing) <* eof) "a" 'a'+        err (scan (\c -> if c == 'b' then Just c else Nothing)) "abc"+        err (scan (\c -> if c == 'a' then Just c else Nothing)) ""          -- because of sentinel-        err (asciiSatisfy (== 0)) "\0"-        err (asciiSatisfy (== 0)) ""+        err (scan (\c -> if c == '\0' then Just c else Nothing)) "\0"+        err (scan (\c -> if c == '\0' then Just c else Nothing)) "" -    , testCase "asciiSatisfy-random" $ replicateM_ randomTries $ do-        s <- randomAsciiString-        ok (traverse (asciiSatisfy . (==) . fromIntegral . C.ord) s *> eof) s ()+    , testCase "asciiScan" $ do+        ok (asciiScan (\c -> if c == asc_a then Just c else Nothing)) "abc" asc_a+        ok (asciiScan (\c -> if c == asc_a then Just c else Nothing) <* eof) "a" asc_a+        err (asciiScan (\c -> if c == asc_0 then Just c else Nothing)) "abc"+        err (asciiScan (\c -> if c == asc_0 then Just c else Nothing)) "" +        -- because of sentinel+        err (asciiScan (\c -> if c == 0 then Just c else Nothing)) "\0"+        err (asciiScan (\c -> if c == 0 then Just c else Nothing)) ""+     , testCase "asciiByte" $ do         ok (asciiByte asc_a) "abc" asc_a         ok (asciiByte asc_a <* eof) "a" asc_a@@ -123,6 +129,20 @@         s <- randomString         ok (traverse (satisfy . (==)) s *> eof) s () +    , testCase "asciiSatisfy" $ do+        ok (asciiSatisfy (== asc_a)) "abc" asc_a+        ok (asciiSatisfy (== asc_a) <* eof) "a" asc_a+        err (asciiSatisfy (== asc_0)) "abc"+        err (asciiSatisfy (== asc_0)) ""++        -- because of sentinel+        err (asciiSatisfy (== 0)) "\0"+        err (asciiSatisfy (== 0)) ""++    , testCase "asciiSatisfy-random" $ replicateM_ randomTries $ do+        s <- randomAsciiString+        ok (traverse (asciiSatisfy . (==) . fromIntegral . C.ord) s *> eof) s ()+     , testCase "string" $ do         ok (string "ab") "abc" (stringToChunk "ab")         err (string "bc") "abc"@@ -458,6 +478,16 @@         ok (element '\0' <* eof) "\0" '\0'         err (element '\0') "" +    , testCase "elementScan" $ do+        ok (elementScan (\c -> if c == 'a' then Just c else Nothing)) "abc" 'a'+        ok (elementScan (\c -> if c == 'a' then Just c else Nothing) <* eof) "a" 'a'+        err (elementScan (\c -> if c == 'b' then Just c else Nothing)) "abc"+        err (elementScan Just) ""++        -- sentinel+        ok (elementScan (\c -> if c == '\0' then Just c else Nothing)) "\0" '\0'+        ok (elementScan (\c -> if c == '\0' then Just c else Nothing) <* eof) "\0" '\0'+     , testCase "chunk" $ do         ok (chunk "ab") "abc" "ab"         err (chunk "bc") "abc"@@ -653,17 +683,11 @@ fraction fractionHex -CharParser:-scan--ChunkParser:-elementScan- Element Combinators:-scanElementsWhile-scanElementsWhile1+scanElements+scanElements1  Char Combinators:-scanCharsWhile-scanCharsWhile1+scanChars+scanChars1 -}