packages feed

paripari 0.2.0.0 → 0.2.1.0

raw patch · 4 files changed

+141/−22 lines, 4 filesdep +randomPVP ok

version bump matches the API change (PVP)

Dependencies added: random

API changes (from Hackage documentation)

+ Text.PariPari: ErrorContext :: [Error] -> [String] -> ErrorContext
+ Text.PariPari: Report :: !FilePath -> !Int -> !Int -> [ErrorContext] -> Report
+ Text.PariPari: ReportOptions :: !Int -> !Int -> !Int -> ReportOptions
+ Text.PariPari: [_ecContext] :: ErrorContext -> [String]
+ Text.PariPari: [_ecErrors] :: ErrorContext -> [Error]
+ Text.PariPari: [_optMaxContexts] :: ReportOptions -> !Int
+ Text.PariPari: [_optMaxErrorsPerContext] :: ReportOptions -> !Int
+ Text.PariPari: [_optMaxLabelsPerContext] :: ReportOptions -> !Int
+ Text.PariPari: [_reportCol] :: Report -> !Int
+ Text.PariPari: [_reportErrors] :: Report -> [ErrorContext]
+ Text.PariPari: [_reportFile] :: Report -> !FilePath
+ Text.PariPari: [_reportLine] :: Report -> !Int
+ Text.PariPari: data ErrorContext
+ Text.PariPari: data Report
+ Text.PariPari: data ReportOptions
+ Text.PariPari: defaultReportOptions :: ReportOptions
+ Text.PariPari.Internal.CharCombinators: anyAsciiByte :: CharP k Word8

Files

paripari.cabal view
@@ -2,11 +2,11 @@ -- -- see: https://github.com/sol/hpack ----- hash: 2b6dd0a88b444dee67e31d36c8744b234a1ef0a86434d9caacc7196eba7ac3f9+-- hash: f7e834d1be86ccea3ebb59239a70a2c711d2713ef3eba70e8000c5551906bc1c  name:           paripari-version:        0.2.0.0-synopsis:       Fast-path parser combinators with fallback for error reporting+version:        0.2.1.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. category:       Text stability:      experimental@@ -87,6 +87,7 @@     , bytestring >=0.10 && <0.11     , paripari     , parser-combinators >=1.0 && <1.1+    , random     , tasty     , tasty-hunit     , text >=0.11 && <1.3
src/Text/PariPari.hs view
@@ -21,10 +21,14 @@   , A.runAcceptor    , R.Reporter+  , R.Report(..)+  , R.ErrorContext(..)+  , R.ReportOptions(..)   , R.runReporter   , R.showReport   , R.showErrors   , R.runReporterWithOptions+  , R.defaultReportOptions    , T.Tracer   , T.runTracer
src/Text/PariPari/Internal/CharCombinators.hs view
@@ -14,6 +14,7 @@   , char'   , notChar   , anyChar+  , anyAsciiByte   , alphaNumChar   , digitChar   , letterChar@@ -35,12 +36,13 @@  import Control.Applicative ((<|>), optional) import Control.Monad.Combinators (option, skipCount, skipMany)+import Data.Functor (void)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import Data.Word (Word8) import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class import Text.PariPari.Internal.ElementCombinators ((<?>))-import Data.Text (Text)-import Data.Functor (void)-import Data.Word (Word8) import qualified Data.Char as C  type CharP k a  = (forall p. CharParser k p => p a)@@ -77,6 +79,7 @@ -- Returns the integer and the number of digits. -- Bases 2 to 36 are supported. -- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator. integer' :: (Num a, CharParser k p) => p sep -> Int -> p (a, Int) integer' sep base = label (integerLabel base) $ do   d <- digit base@@ -91,6 +94,7 @@ -- | Parse an integer of the given base. -- Bases 2 to 36 are supported. -- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator. integer :: (Num a, CharParser k p) => p sep -> Int -> p a integer sep base = label (integerLabel base) $ do   d <- digit base@@ -109,14 +113,20 @@ integerLabel 16 = "hexadecimal integer" integerLabel b  = "integer of base " <> show b +-- | Parses a decimal integer.+-- Signs are not parsed by this combinator. decimal :: Num a => CharP k a decimal = integer (pure ()) 10 {-# INLINE decimal #-} +-- | Parses an octal integer.+-- Signs are not parsed by this combinator. octal :: Num a => CharP k a octal = integer (pure ()) 8 {-# INLINE octal #-} +-- | Parses a hexadecimal integer.+-- Signs are not parsed by this combinator. hexadecimal :: Num a => CharP k a hexadecimal = integer (pure ()) 16 {-# INLINE hexadecimal #-}@@ -128,21 +138,29 @@  -- | Parse a fraction of arbitrary exponent base and coefficient base. -- 'fractionDec' and 'fractionHex' should be used instead probably.+-- Does not parse integers.+-- Signs are not parsed by this combinator. fraction :: (Num a, CharParser k p) => p expSep -> Int -> Int -> p digitSep -> p (a, Int, a) fraction expSep expBase coeffBasePow digitSep = do   let coeffBase = expBase ^ coeffBasePow   coeff <- integer digitSep coeffBase-  void $ optional $ asciiByte asc_point-  (frac, fracLen) <- option (0, 0) $ integer' digitSep coeffBase-  expVal <- option 0 $ expSep *> signed (integer digitSep 10)-  pure (coeff * fromIntegral coeffBase ^ fracLen + frac,-        expBase,-        expVal - fromIntegral (fracLen * coeffBasePow))+  frac <- optional $ asciiByte asc_point *> option (0, 0) (integer' digitSep coeffBase)+  expn <- optional $ expSep *> signed (integer digitSep 10)+  let (fracVal, fracLen) = fromMaybe (0, 0) frac+      expVal = fromMaybe 0 expn+  case (frac, expn) of+    (Nothing, Nothing) -> failWith $ EExpected ["fraction"]+    _  ->+      pure (coeff * fromIntegral coeffBase ^ fracLen + fracVal,+            expBase,+            expVal - fromIntegral (fracLen * coeffBasePow)) {-# INLINE fraction #-}  -- | Parse a decimal fraction, returning (coefficient, 10, exponent), -- corresponding to coefficient * 10^exponent. -- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Does not parse integers.+-- Signs are not parsed by this combinator. fractionDec :: (Num a, CharParser k p) => p digitSep -> p (a, Int, a) fractionDec sep = fraction (asciiSatisfy (\b -> b == asc_E || b == asc_e)) 10 1 sep <?> "fraction" {-# INLINE fractionDec #-}@@ -150,6 +168,8 @@ -- | Parse a hexadecimal fraction, returning (coefficient, 2, exponent), -- corresponding to coefficient * 2^exponent. -- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Does not parse integers.+-- Signs are not parsed by this combinator. fractionHex :: (Num a, CharParser k p) => p digitSep -> p (a, Int, a) fractionHex sep = fraction (asciiSatisfy (\b -> b == asc_P || b == asc_p)) 2 4 sep <?> "hexadecimal fraction" {-# INLINE fractionHex #-}@@ -172,6 +192,11 @@ anyChar = satisfy (const True) {-# INLINE anyChar #-} +-- | Parse an arbitrary ASCII byte.+anyAsciiByte :: CharP k Word8+anyAsciiByte = asciiSatisfy (const True)+{-# INLINE anyAsciiByte #-}+ -- | Parse an alphanumeric character, including Unicode. alphaNumChar :: CharP k Char alphaNumChar = satisfy C.isAlphaNum <?> "alphanumeric character"@@ -215,7 +240,7 @@  -- | Parse a character beloning to the ASCII charset (< 128) asciiChar :: CharP k Char-asciiChar = unsafeAsciiToChar <$> asciiSatisfy (const True)+asciiChar = unsafeAsciiToChar <$> anyAsciiByte {-# INLINE asciiChar #-}  -- | Parse a character belonging to the given Unicode category
test/test.hs view
@@ -5,21 +5,40 @@ {-# LANGUAGE FlexibleContexts #-} module Main (main) where +import Control.Monad (replicateM, replicateM_) import Data.ByteString (ByteString) import Data.Either (isLeft) import Data.Text (Text) import GHC.Stack (HasCallStack) import Prelude hiding (getLine)+import System.Random import Test.Tasty import Test.Tasty.HUnit import Text.PariPari import Text.PariPari.Internal.Chunk (textToChunk, asc_a, asc_0, asc_9) import qualified Data.Char as C import qualified Data.List.NonEmpty as NE+import qualified Data.Text as T  main :: IO () main = defaultMain tests +randomTries :: Int+randomTries = 1000++randomStringLen :: Int+randomStringLen = 1000++randomString :: IO Text+randomString = do+  n <- randomRIO (1, randomStringLen)+  T.pack <$> replicateM n (randomRIO (C.chr 1, maxBound))++randomAsciiString :: IO Text+randomAsciiString = do+  n <- randomRIO (1, randomStringLen)+  T.pack <$> replicateM n (randomRIO (C.chr 1, C.chr 127))+ tests :: TestTree tests = testGroup "Tests"   [ testGroup "Chunk"@@ -54,12 +73,20 @@         err (satisfy (== '\0')) "\0"         err (satisfy (== '\0')) "" +    , testCase "satisfy-random" $ replicateM_ randomTries $ do+        s <- randomString+        ok (traverse (satisfy . (==)) (T.unpack s) *> eof) s ()+     , testCase "char" $ do         ok (char 'a') "abc" 'a'         ok (char 'a' <* eof) "a" 'a'         err (char 'b') "abc"         err (char 'a') "" +    , testCase "char-random" $ replicateM_ randomTries $ do+        s <- randomString+        ok (traverse char (T.unpack s) *> eof) s ()+     , testCase "asciiSatisfy" $ do         ok (asciiSatisfy (== asc_a)) "abc" asc_a         ok (asciiSatisfy (== asc_a) <* eof) "a" asc_a@@ -70,12 +97,20 @@         err (asciiSatisfy (== 0)) "\0"         err (asciiSatisfy (== 0)) "" +    , testCase "asciiSatisfy-random" $ replicateM_ randomTries $ do+        s <- randomAsciiString+        ok (traverse (asciiSatisfy . (==) . fromIntegral . C.ord) (T.unpack s) *> eof) s ()+     , testCase "asciiByte" $ do         ok (asciiByte asc_a) "abc" asc_a         ok (asciiByte asc_a <* eof) "a" asc_a         ok (asciiByte 127 <* eof) "\x7F" 127         err (asciiByte asc_0) "abc"         err (asciiByte asc_0) ""++    , testCase "asciiByte-random" $ replicateM_ randomTries $ do+        s <- randomAsciiString+        ok (traverse (asciiByte . fromIntegral . C.ord) (T.unpack s) *> eof) s ()     ]    , testGroup "Char Combinators"@@ -84,11 +119,29 @@         err (string "bc") "abc"         err (string "ab") "" +    , testCase "string-random" $ replicateM_ randomTries $ do+        s <- randomString+        ok (string s <* eof) s s+     , testCase "anyChar" $ do         ok anyChar "abc" 'a'         ok (anyChar <* eof) "a" 'a'         err anyChar "" +    , testCase "anyChar-random" $ replicateM_ randomTries $ do+        s <- randomString+        ok (traverse (const anyChar) (T.unpack s) *> eof) s ()++    , testCase "anyAsciiByte" $ do+        ok anyAsciiByte "abc" asc_a+        ok (anyAsciiByte <* eof) "a" asc_a+        err anyAsciiByte ""+        err anyAsciiByte "\x80"++    , testCase "anyAsciiByte-random" $ replicateM_ randomTries $ do+        s <- randomAsciiString+        ok (traverse (const anyAsciiByte) (T.unpack s) *> eof) s ()+     , testCase "notChar" $ do         ok (notChar 'b') "abc" 'a'         ok (notChar 'b' <* eof) "a" 'a'@@ -175,6 +228,38 @@         err (digitByte 10) ""     ] +  , testGroup "Fraction Combinators"+    [ testCase "fractionDec" $ do+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "1.23" (123, 10, -2)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "99e0" (99, 10, 0)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "123.45" (12345, 10, -2)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "00123." (123, 10, 0)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "456.000" (456000, 10, -3)++        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987e-5" (987, 10, -5)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.e-123" (987, 10, -123)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654e-67" (987654, 10, -70)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654000e-7" (987654000, 10, -13)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "000987.654000e-7" (987654000, 10, -13)++        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987e+5" (987, 10, 5)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.e+123" (987, 10, 123)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654e+67" (987654, 10, 64)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654000e+7" (987654000, 10, 1)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "000987.654000e+7" (987654000, 10, 1)++        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987e5" (987, 10, 5)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.e123" (987, 10, 123)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654e67" (987654, 10, 64)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "987.654000e7" (987654000, 10, 1)+        ok @(Integer, Int, Integer) (fractionDec (pure ()) <* eof) "000987.654000e7" (987654000, 10, 1)++        err @(Integer, Int, Integer) (fractionDec (pure ())) ""+        err @(Integer, Int, Integer) (fractionDec (pure ())) "123"+        err @(Integer, Int, Integer) (fractionDec (pure ())) "123e"+        err @(Integer, Int, Integer) (fractionDec (pure ())) "abc"+    ]+   , testGroup "Integer Combinators"     [ testCase "decimal" $ do         ok @Integer (decimal <* eof) "0123" 123@@ -201,11 +286,11 @@         err @Integer hexadecimal ""      , testCase "integer" $ do-        err @Integer (integer (pure ()) 10) "abc"         ok @Integer (integer (char '_') 10) "1_2_3" 123         ok @Integer (integer (char '_') 10 <* char '_') "1_2_3_" 123-        err @Integer (integer (char '_') 10) "_1_2_3"         ok @Integer (integer (optional $ char '_') 10) "123_456_789" 123456789+        err @Integer (integer (pure ()) 10) "abc"+        err @Integer (integer (char '_') 10) "_1_2_3"         err @Integer (integer (pure ()) 10) "-1"         err @Integer (integer (pure ()) 10) "" @@ -214,14 +299,18 @@         ok @Integer (integer (pure ()) 36) "XyZ" 44027      , testCase "integer'" $ do-        err @(Integer, Int) (integer' (pure ()) 10) "abc"         ok @(Integer, Int) (integer' (char '_') 10) "1_2_3" (123, 3)         ok @(Integer, Int) (integer' (char '_') 10 <* char '_') "1_2_3_" (123, 3)-        err @(Integer, Int) (integer' (char '_') 10) "_1_2_3"         ok @(Integer, Int) (integer' (optional $ char '_') 10) "123_456_789" (123456789, 9)+        err @(Integer, Int) (integer' (pure ()) 10) "abc"+        err @(Integer, Int) (integer' (char '_') 10) "_1_2_3"         err @(Integer, Int) (integer' (pure ()) 10) "-1"         err @(Integer, Int) (integer' (pure ()) 10) "" +        ok @(Integer, Int) (integer' (pure ()) 10) "0123" (123, 4)+        ok @(Integer, Int) (integer' (pure ()) 10) "01230" (1230, 5)+        ok @(Integer, Int) (integer' (pure ()) 10) "000" (0, 3)+         ok @(Integer, Int) (integer' (pure ()) 2) "101" (5, 3)         ok @(Integer, Int) (integer' (pure ()) 7) "321" (162, 3)         ok @(Integer, Int) (integer' (pure ()) 36) "XyZ" (44027, 3)@@ -432,18 +521,19 @@   {-+TODO: +Instances: Semigroup Monoid Functor Applicative Monad MonadPlus-Alternative:--TODO:+Alternative -Additional combinators:+Additional combinators provided by parser-combinators.+They are also tested by megaparsec: endBy1 someTill sepBy1@@ -472,7 +562,6 @@  Fraction: fractionHex-fractionDec  Char Combinators: skipChars