packages feed

parsley 1.0.2.0 → 2.0.0.0

raw patch · 30 files changed

+730/−371 lines, 30 filesdep ~basedep ~parsley-coredep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, parsley-core, text

API changes (from Hackage documentation)

- Parsley: runParser :: (Trace, Input input) => Parser a -> Code (input -> Maybe a)
- Parsley.Combinator: char :: Char -> Parser Char
- Parsley.Combinator: item :: Parser Char
- Parsley.Combinator: noneOf :: [Char] -> Parser Char
- Parsley.Combinator: oneOf :: [Char] -> Parser Char
- Parsley.Combinator: satisfy :: ParserOps rep => rep (Char -> Bool) -> Parser Char
- Parsley.Combinator: string :: String -> Parser String
- Parsley.Combinator: token :: String -> Parser String
- Parsley.Fold: chainPost :: Parser a -> Parser (a -> a) -> Parser a
- Parsley.Fold: chainPre :: Parser (a -> a) -> Parser a -> Parser a
- Parsley.Fold: chainl1' :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (b -> a -> b) -> Parser b
- Parsley.Fold: chainr1' :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (a -> b -> b) -> Parser b
- Parsley.Fold: pfoldl :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b
- Parsley.Fold: pfoldl1 :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b
- Parsley.Fold: pfoldr :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b
- Parsley.Fold: pfoldr1 :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b
- Parsley.Precedence: InfixL :: [Parser (b -> a -> b)] -> Defunc (a -> b) -> Level a b
- Parsley.Precedence: InfixR :: [Parser (a -> b -> b)] -> Defunc (a -> b) -> Level a b
- Parsley.Precedence: Postfix :: [Parser (b -> b)] -> Defunc (a -> b) -> Level a b
- Parsley.Precedence: Prefix :: [Parser (b -> b)] -> Defunc (a -> b) -> Level a b
- Parsley.Precedence: [NoLevel] :: Prec a a
- Parsley.Precedence: class Monolith a b c
- Parsley.Precedence: data Level a b
- Parsley.Precedence: infixL :: Monolith a b c => [Parser (b -> a -> b)] -> c
- Parsley.Precedence: infixR :: Monolith a b c => [Parser (a -> b -> b)] -> c
- Parsley.Precedence: instance (x GHC.Types.~ (Parsley.Internal.Common.Utils.WQ (a -> b) -> Parsley.Precedence.Level a b)) => Parsley.Precedence.Monolith a b x
- Parsley.Precedence: instance (x GHC.Types.~ a) => Parsley.Precedence.Monolith x a (Parsley.Precedence.Level a a)
- Parsley.Precedence: monolith :: [Level a a] -> Prec a a
- Parsley.Precedence: postfix :: Monolith a b c => [Parser (b -> b)] -> c
- Parsley.Precedence: prefix :: Monolith a b c => [Parser (b -> b)] -> c
+ Parsley: parse :: (Trace, Input input) => Parser a -> Code (input -> Maybe a)
+ Parsley.Char: char :: Char -> Parser Char
+ Parsley.Char: digit :: Parser Char
+ Parsley.Char: item :: Parser Char
+ Parsley.Char: letter :: Parser Char
+ Parsley.Char: letterOrDigit :: Parser Char
+ Parsley.Char: noneOf :: [Char] -> Parser Char
+ Parsley.Char: oneOf :: [Char] -> Parser Char
+ Parsley.Char: satisfy :: ParserOps rep => rep (Char -> Bool) -> Parser Char
+ Parsley.Char: string :: String -> Parser String
+ Parsley.Char: token :: String -> Parser String
+ Parsley.Debug: debug :: String -> Parser a -> Parser a
+ Parsley.Defunctionalized: [RANGES] :: Bool -> [(Char, Char)] -> Defunc (Char -> Bool)
+ Parsley.Fold: infixl1 :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (b -> a -> b) -> Parser b
+ Parsley.Fold: infixr1 :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (a -> b -> b) -> Parser b
+ Parsley.Fold: manyl :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b
+ Parsley.Fold: manyr :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b
+ Parsley.Fold: postfix :: Parser a -> Parser (a -> a) -> Parser a
+ Parsley.Fold: prefix :: Parser (a -> a) -> Parser a -> Parser a
+ Parsley.Fold: somel :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b
+ Parsley.Fold: somer :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b
+ Parsley.ParserOps: class ParserOps rep
+ Parsley.ParserOps: conditional :: ParserOps rep => [(rep (a -> Bool), Parser b)] -> Parser a -> Parser b -> Parser b
+ Parsley.ParserOps: instance (x GHC.Types.~ Parsley.Internal.Core.Defunc.Defunc) => Parsley.ParserOps.ParserOps x
+ Parsley.ParserOps: instance Parsley.ParserOps.ParserOps Parsley.Internal.Common.Utils.WQ
+ Parsley.ParserOps: pure :: ParserOps rep => rep a -> Parser a
+ Parsley.ParserOps: satisfy :: ParserOps rep => rep (Char -> Bool) -> Parser Char
+ Parsley.Precedence: (+<) :: Op a b -> Prec a -> Prec b
+ Parsley.Precedence: (>+) :: Prec a -> Op a b -> Prec b
+ Parsley.Precedence: [Atom] :: Parser a -> Prec a
+ Parsley.Precedence: [InfixL] :: Fixity a b (b -> a -> b)
+ Parsley.Precedence: [InfixN] :: Fixity a b (a -> a -> b)
+ Parsley.Precedence: [InfixR] :: Fixity a b (a -> b -> b)
+ Parsley.Precedence: [Postfix] :: Fixity a b (b -> b)
+ Parsley.Precedence: [Prefix] :: Fixity a b (b -> b)
+ Parsley.Precedence: class GOps rep
+ Parsley.Precedence: class Subtype sub sup
+ Parsley.Precedence: data Fixity a b sig
+ Parsley.Precedence: data Op a b
+ Parsley.Precedence: downcast :: Subtype sub sup => sup -> Maybe sub
+ Parsley.Precedence: gops :: GOps rep => Fixity a b sig -> [Parser sig] -> rep (a -> b) -> Op a b
+ Parsley.Precedence: infixl 5 >+
+ Parsley.Precedence: infixr 5 +<
+ Parsley.Precedence: instance (x GHC.Types.~ Parsley.Internal.Core.Defunc.Defunc) => Parsley.Precedence.GOps x
+ Parsley.Precedence: instance Parsley.Precedence.GOps Parsley.Internal.Common.Utils.WQ
+ Parsley.Precedence: ops :: Fixity a a sig -> [Parser sig] -> Op a a
+ Parsley.Precedence: precHomo :: Parser a -> [Op a a] -> Parser a
+ Parsley.Precedence: sops :: Subtype a b => Fixity a b sig -> [Parser sig] -> Op a b
+ Parsley.Precedence: upcast :: Subtype sub sup => sub -> sup
- Parsley.Defunctionalized: [LIFTED] :: forall a. (Show a, Lift a) => a -> Defunc a
+ Parsley.Defunctionalized: [LIFTED] :: forall a. (Show a, Lift a, Typeable a) => a -> Defunc a
- Parsley.Precedence: [Level] :: Level a b -> Prec b c -> Prec a c
+ Parsley.Precedence: [Level] :: Prec a -> Op a b -> Prec b
- Parsley.Precedence: data Prec a b
+ Parsley.Precedence: data Prec a
- Parsley.Precedence: precedence :: Prec a b -> Parser a -> Parser b
+ Parsley.Precedence: precedence :: Prec a -> Parser a

Files

ChangeLog.md view
@@ -42,3 +42,22 @@  * Added `local_` combinator to `Register`. * Added `localModify` and `localModify_` combinators to `Register`.++## 2.0.0.0 -- 2021-11-24++* Incorporated API naming conventions from _Design Patterns for Parser Combinators_.+    * `chainPre` -> `prefix`+    * `chainPost` -> `postfix`+    * `chainl1'` -> `infixl1`+    * `chainr1'` -> `infixr1`+    * `pfoldr` -> `manyr`+    * `pfoldl` -> `manyl`+    * `pfoldr1` -> `somer`+    * `pfoldl1` -> `somel`+* Reworked the `precedence` combinator system in line with the paper: the horrible overloading+  has gone now!+* Added in the `ParserOps` and `Debug` modules.+* Added `RANGES` to the `Defunc` API.+* Renamed `runParser` to `parse`.+* Moved some functionality to `Parsley.Char`.+* Added `digit`, `letter`, and `letterOrDigit`.
README.md view
@@ -63,6 +63,7 @@  ## References * This work spawned a paper at ICFP 2020: [**Staged Selective Parser Combinators**](https://dl.acm.org/doi/10.1145/3409002)+* Supports patterns and combinators from Haskell Symposium 2021: [**Design Patterns of Parser Combinators**](https://dl.acm.org/doi/10.1145/3471874.3472984)  ### Talks For talks on how writing parsers changes when using Parsley see either of these:@@ -71,3 +72,6 @@  For the technical overview of how Parsley works: * [*Staged Selective Parser Combinators*](https://www.youtube.com/watch?v=lH65PvRgm8M) - ICFP 2020++For information about how to write parsers cleanly:+* [*Design Patterns for Parser Combinators*](https://www.youtube.com/watch?v=RwzX1XltOGY) - Haskell 2021
benchmarks/BrainfuckBench/Main.hs view
@@ -32,19 +32,19 @@ deriving instance NFData BrainFuckOp  brainfuckParsleyS :: String -> Maybe [BrainFuckOp]-brainfuckParsleyS = $$(Parsley.runParser BrainfuckBench.Parsley.Parser.brainfuck)+brainfuckParsleyS = $$(Parsley.parse BrainfuckBench.Parsley.Parser.brainfuck)  brainfuckParsleyT :: Text -> Maybe [BrainFuckOp]-brainfuckParsleyT = $$(Parsley.runParser BrainfuckBench.Parsley.Parser.brainfuck)+brainfuckParsleyT = $$(Parsley.parse BrainfuckBench.Parsley.Parser.brainfuck)  brainfuckParsleyB :: ByteString -> Maybe [BrainFuckOp]-brainfuckParsleyB = $$(Parsley.runParser BrainfuckBench.Parsley.Parser.brainfuck)+brainfuckParsleyB = $$(Parsley.parse BrainfuckBench.Parsley.Parser.brainfuck)  brainfuckParsleySS :: CharList -> Maybe [BrainFuckOp]-brainfuckParsleySS = $$(Parsley.runParser BrainfuckBench.Parsley.Parser.brainfuck)+brainfuckParsleySS = $$(Parsley.parse BrainfuckBench.Parsley.Parser.brainfuck)  brainfuckParsleyLB :: Data.ByteString.Lazy.ByteString -> Maybe [BrainFuckOp]-brainfuckParsleyLB = $$(Parsley.runParser BrainfuckBench.Parsley.Parser.brainfuck)+brainfuckParsleyLB = $$(Parsley.parse BrainfuckBench.Parsley.Parser.brainfuck)  brainfuck :: Benchmark brainfuck =
benchmarks/BrainfuckBench/Parsley/Parser.hs view
@@ -7,7 +7,8 @@ import Prelude hiding (fmap, pure, (<*), (*>), (<*>), (<$>), (<$), pred) import BrainfuckBench.Shared import Parsley-import Parsley.Combinator (noneOf, eof)+import Parsley.Combinator (eof)+import Parsley.Char(noneOf) import Parsley.Fold (skipMany) --import Parsley.Garnish import Language.Haskell.TH.Syntax (Lift(..))
benchmarks/JavascriptBench/Main.hs view
@@ -42,10 +42,10 @@ deriving instance NFData JSAtom  javascriptParsleyS :: String -> Maybe JSProgram-javascriptParsleyS = $$(Parsley.runParser JavascriptBench.Parsley.Parser.javascript)+javascriptParsleyS = $$(Parsley.parse JavascriptBench.Parsley.Parser.javascript)  javascriptParsleyT :: Text -> Maybe JSProgram-javascriptParsleyT = $$(Parsley.runParser JavascriptBench.Parsley.Parser.javascript)+javascriptParsleyT = $$(Parsley.parse JavascriptBench.Parsley.Parser.javascript)  javascript :: Benchmark javascript =
benchmarks/JavascriptBench/Parsley/Parser.hs view
@@ -7,9 +7,10 @@  import Prelude hiding (fmap, pure, (<*), (*>), (<*>), (<$>), (<$), pred) import Parsley-import Parsley.Combinator (token, oneOf, noneOf, eof)-import Parsley.Fold (skipMany, skipSome, sepBy, sepBy1, pfoldl1, chainl1)-import Parsley.Precedence (precedence, monolith, prefix, postfix, infixR, infixL)+import Parsley.Char (token, oneOf, noneOf, digit)+import Parsley.Combinator (eof)+import Parsley.Fold (skipMany, skipSome, sepBy, sepBy1, somel, chainl1)+import Parsley.Precedence (precHomo, ops, Fixity(InfixL, Prefix, Postfix)) import Parsley.Defunctionalized (Defunc(CONS, ID, LIFTED, LAM_S), pattern FLIP_H, pattern COMPOSE_H) import JavascriptBench.Shared import Data.Char (isSpace, isUpper, digitToInt, isDigit)@@ -64,25 +65,24 @@     condExpr :: Parser JSExpr'     condExpr = liftA2 [|jsCondExprBuild|] expr' (maybeP ((symbol '?' *> asgn) <~> (symbol ':' *> asgn)))     expr' :: Parser JSExpr'-    expr' = precedence (monolith-      [ prefix  [ operator "--" $> [|jsDec|], operator "++" $> [|jsInc|]-                , operator "-" $> [|jsNeg|], operator "+" $> [|jsPlus|]-                , operator "~" $> [|jsBitNeg|], operator "!" $> [|jsNot|] ]-      , postfix [ operator "--" $> [|jsDec|], operator "++" $> [|jsInc|] ]-      , infixL  [ operator "*" $> [|JSMul|], operator "/" $> [|JSDiv|]-                , operator "%" $> [|JSMod|] ]-      , infixL  [ operator "+" $> [|JSAdd|], operator "-" $> [|JSSub|] ]-      , infixL  [ operator "<<" $> [|JSShl|], operator ">>" $> [|JSShr|] ]-      , infixL  [ operator "<=" $> [|JSLe|], operator "<" $> [|JSLt|]-                , operator ">=" $> [|JSGe|], operator ">" $> [|JSGt|] ]-      , infixL  [ operator "==" $> [|JSEq|], operator "!=" $> [|JSNe|] ]-      , infixL  [ try (operator "&") $> [|JSBitAnd|] ]-      , infixL  [ operator "^" $> [|JSBitXor|] ]-      , infixL  [ try (operator "|") $> [|JSBitOr|] ]-      , infixL  [ operator "&&" $> [|JSAnd|] ]-      , infixL  [ operator "||" $> [|JSOr|] ]-      ])-      ([|JSUnary|] <$> memOrCon)+    expr' = precHomo ([|JSUnary|] <$> memOrCon)+      [ ops Prefix  [ operator "--" $> [|jsDec|], operator "++" $> [|jsInc|]+                    , operator "-" $> [|jsNeg|], operator "+" $> [|jsPlus|]+                    , operator "~" $> [|jsBitNeg|], operator "!" $> [|jsNot|] ]+      , ops Postfix [ operator "--" $> [|jsDec|], operator "++" $> [|jsInc|] ]+      , ops InfixL  [ operator "*" $> [|JSMul|], operator "/" $> [|JSDiv|]+                    , operator "%" $> [|JSMod|] ]+      , ops InfixL  [ operator "+" $> [|JSAdd|], operator "-" $> [|JSSub|] ]+      , ops InfixL  [ operator "<<" $> [|JSShl|], operator ">>" $> [|JSShr|] ]+      , ops InfixL  [ operator "<=" $> [|JSLe|], operator "<" $> [|JSLt|]+                    , operator ">=" $> [|JSGe|], operator ">" $> [|JSGt|] ]+      , ops InfixL  [ operator "==" $> [|JSEq|], operator "!=" $> [|JSNe|] ]+      , ops InfixL  [ try (operator "&") $> [|JSBitAnd|] ]+      , ops InfixL  [ operator "^" $> [|JSBitXor|] ]+      , ops InfixL  [ try (operator "|") $> [|JSBitOr|] ]+      , ops InfixL  [ operator "&&" $> [|JSAnd|] ]+      , ops InfixL  [ operator "||" $> [|JSOr|] ]+      ]     memOrCon :: Parser JSUnary     memOrCon = keyword "delete" *> ([|JSDel|] <$> member)            <|> keyword "new" *> ([|JSCons|] <$> con)@@ -132,11 +132,11 @@     zeroNumFloat :: Parser (Either Int Double)     zeroNumFloat = [|Left|] <$> (hexadecimal <|> octal)                <|> decimalFloat-               <|> (fromMaybeP (fractFloat <*> pure (LIFTED 0)) empty)+               <|> fromMaybeP (fractFloat <*> pure (LIFTED 0)) empty                <|> pure [|Left 0|]      decimalFloat :: Parser (Either Int Double)-    decimalFloat = fromMaybeP (decimal <**> (option (COMPOSE_H [|Just|] [|Left|]) fractFloat)) empty+    decimalFloat = fromMaybeP (decimal <**> option (COMPOSE_H [|Just|] [|Left|]) fractFloat) empty      fractFloat :: Parser (Int -> Maybe (Either Int Double))     fractFloat = [|\g x -> liftM Right (g x)|] <$> fractExponent@@ -149,7 +149,7 @@         g = [|\exp n -> readMaybe (show n ++ exp)|]      fraction :: Parser [Char]-    fraction = char '.' <:> some (oneOf ['0'..'9'])+    fraction = char '.' <:> some digit      exponent' :: Parser [Char]     exponent' = [|$(CONS) 'e'|] <$> (oneOf "eE"@@ -157,12 +157,12 @@              <*> ([|show|] <$> decimal)))      decimal :: Parser Int-    decimal = number (LIFTED 10) (oneOf ['0'..'9'])+    decimal = number (LIFTED 10) digit     hexadecimal = oneOf "xX" *> number (LIFTED 16) (oneOf (['a'..'f'] ++ ['A'..'F'] ++ ['0'..'9']))     octal = oneOf "oO" *> number (LIFTED 8) (oneOf ['0'..'7'])      number :: Defunc Int -> Parser Char -> Parser Int-    number qbase digit = pfoldl1 addDigit (LIFTED 0) digit+    number qbase digit = somel addDigit (LIFTED 0) digit       where         addDigit = [|\x d -> $qbase * x + digitToInt d|] 
benchmarks/NandlangBench/Main.hs view
@@ -17,7 +17,7 @@ main = defaultMain [nandlang]  nandParsleyB :: ByteString -> Maybe ()-nandParsleyB = $$(Parsley.runParser NandlangBench.Parsley.Parser.nandlang)+nandParsleyB = $$(Parsley.parse NandlangBench.Parsley.Parser.nandlang)  nandlang :: Benchmark nandlang =
benchmarks/NandlangBench/Parsley/Parser.hs view
@@ -6,7 +6,8 @@  import Prelude hiding (fmap, pure, (<*), (*>), (<*>), (<$>), (<$), pred) import Parsley-import Parsley.Combinator (token, oneOf, eof)+import Parsley.Combinator (eof)+import Parsley.Char (token, oneOf) import Parsley.Fold (skipMany, skipSome) --import Parsley.Garnish import NandlangBench.Parsley.Functions
parsley.cabal view
@@ -5,7 +5,7 @@ --                   | +------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             1.0.2.0+version:             2.0.0.0 synopsis:            A fast parser combinator library backed by Typed Template Haskell description:         Parsley is a staged selective parser combinator library, which means                      it does not support monadic operations, and relies on Typed Template@@ -35,15 +35,16 @@   exposed-modules:     Parsley,                        Parsley.Applicative,                        Parsley.Alternative,+                       Parsley.Char,+                       Parsley.Combinator,                        Parsley.Defunctionalized,+                       Parsley.Debug,                        Parsley.Selective,                        Parsley.Register,-                       Parsley.Combinator,                        Parsley.Fold,+                       --Parsley.Patterns,                        Parsley.InputExtras,-                       Parsley.Precedence--  other-modules:       Parsley.Debug+                       Parsley.Precedence,                        Parsley.ParserOps    default-extensions:  BangPatterns,@@ -62,9 +63,10 @@  --                     ghc                  >= 8.6     && < 9.2,   build-depends:       base                 >= 4.10    && < 4.16,-                       parsley-core         >= 1.8     && < 3,+                       parsley-core         >= 2       && < 3,                        template-haskell     >= 2.14    && < 3,-                       text                 >= 1.2.3   && < 1.3,+                       text                 >= 1.2.3   && < 1.3+   hs-source-dirs:      src/ghc   default-language:    Haskell2010   ghc-options:         -Wall -Weverything -Wcompat@@ -108,9 +110,9 @@   build-depends:       tasty-hunit, tasty-quickcheck, th-test-utils, deepseq   main-is:             Parsley/Tests.hs   other-modules:       Parsley.Alternative.Test, Parsley.Applicative.Test, Parsley.Combinator.Test, Parsley.Fold.Test,-                       Parsley.Precedence.Test, Parsley.Register.Test, Parsley.Selective.Test,+                       Parsley.Precedence.Test, Parsley.Register.Test, Parsley.Selective.Test, Parsley.Char.Test,                        Parsley.Alternative.Parsers, Parsley.Applicative.Parsers, Parsley.Combinator.Parsers, Parsley.Fold.Parsers,-                       Parsley.Precedence.Parsers, Parsley.Register.Parsers, Parsley.Selective.Parsers+                       Parsley.Precedence.Parsers, Parsley.Register.Parsers, Parsley.Selective.Parsers, Parsley.Char.Parsers  test-suite regression-test   import:              test-common
src/ghc/Parsley.hs view
@@ -7,7 +7,7 @@ Maintainer  : Jamie Willis Stability   : stable -This module contains the core execution functions `runParser` and `parseFromFile`.+This module contains the core execution functions `parse` and `parseFromFile`. It exports the `Parser` type, as well as the `ParserOps` typeclass, which may be needed as a constraint to create more general combinators. It also exports several of the more important modules and functionality in particular the core set of combinators.@@ -15,14 +15,15 @@ @since 0.1.0.0 -} module Parsley (-    runParser, parseFromFile,+    parse, parseFromFile,     module Core,-    module Primitives,     module Applicative,     module Alternative,     module Selective,     module Combinator,+    module Char,     module Fold,+    module Debug,     module THUtils,   ) where @@ -33,12 +34,13 @@  import Parsley.Alternative              as Alternative import Parsley.Applicative              as Applicative-import Parsley.Combinator               as Combinator  (item, char, string, satisfy, notFollowedBy, lookAhead, try)+import Parsley.Char                     as Char        (item, char, string, satisfy)+import Parsley.Combinator               as Combinator  (notFollowedBy, lookAhead, try) import Parsley.Fold                     as Fold        (many, some) import Parsley.Internal                 as Core        (Parser) import Parsley.ParserOps                as Core        (ParserOps) import Parsley.Internal                 as THUtils     (Quapplicative(..), WQ, Code)-import Parsley.Debug                    as Primitives  (debug)+import Parsley.Debug                    as Debug       (debug) import Parsley.Selective                as Selective  import qualified Parsley.Internal as Internal (parse)@@ -56,7 +58,7 @@ /In @Main.hs@/:  > parseHelloParsley :: String -> Maybe String-> parseHelloParsley = $$(runParser helloParsley)+> parseHelloParsley = $$(parse helloParsley)  Note that the definition of the parser __must__ be in a separate module to the splice (@$$@).@@ -66,25 +68,25 @@ The `Trace` instance is used to enable verbose debugging output for the compilation pipeline when "Parsley.Internal.Verbose" is imported. -@since 0.1.0.0+@since 2.0.0.0 -}-runParser :: (Trace, Input input)-          => Parser a                -- ^ The parser to be compiled-          -> Code (input -> Maybe a) -- ^ The generated parsing function-runParser = Internal.parse+parse :: (Trace, Input input)+      => Parser a                -- ^ The parser to be compiled+      -> Code (input -> Maybe a) -- ^ The generated parsing function+parse = Internal.parse  {-| This function generates a function that reads input from a file and parses it. The input files contents are treated as `Text16`. -See `runParser` for more information.+See `parse` for more information.  @since 0.1.0.0 -} parseFromFile :: Trace               => Parser a                        -- ^ The parser to be compiled               -> Code (FilePath -> IO (Maybe a)) -- ^ The generated parsing function-parseFromFile p = [||\filename -> do input <- readFile filename; return ($$(runParser p) (Text16 input))||]+parseFromFile p = [||\filename -> do input <- readFile filename; return ($$(parse p) (Text16 input))||]  {-| The default instance for `Trace`, which disables all debugging output about the parser compilation
+ src/ghc/Parsley/Char.hs view
@@ -0,0 +1,126 @@+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+{-|+Module      : Parsley.Char+Description : The input consuming combinators+License     : BSD-3-Clause+Maintainer  : Jamie Willis+Stability   : stable++This module contains combinators that deal with input consumption..++@since 2.0.0.0+-}+module Parsley.Char (+    satisfy, char, item,+    string, token,+    oneOf, noneOf,+    digit, letter, letterOrDigit+  ) where++import Prelude hiding           (traverse)+import Data.Char                (isAlpha, isAlphaNum)+import Data.List                (sort)+import Parsley.Applicative      (($>), traverse)+import Parsley.Defunctionalized (Defunc(LIFTED, RANGES))+import Parsley.Internal         (Parser, makeQ)+import Parsley.ParserOps        (satisfy)++import qualified Parsley.Internal as Internal (try)++{-|+This combinator will attempt match a given string. If the parser fails midway through, this+combinator will fail having consumed input. On success, the string itself is returned and input+will be consumed.++@since 2.0.0.0+-}+string :: String -> Parser String+string = traverse char++{-|+This combinator will attempt to match any one of the provided list of characters. If one of those+characters is found, it will be returned and the input consumed. If not, the combinator will fail+having consumed no input.++@since 2.0.0.0+-}+oneOf :: [Char] -> Parser Char+oneOf = satisfy . RANGES True . ranges++{-|+This combinator will attempt to not match any one of the provided list of characters. If one of those+characters is found, the combinator will fail having consumed no input. If not, it will return+the character that was not an element of the provided list.++@since 2.0.0.0+-}+noneOf :: [Char] -> Parser Char+noneOf = satisfy . RANGES False . ranges++ranges :: [Char] -> [(Char, Char)]+ranges [] = []+ranges (sort -> c:cs) = go c (fromEnum c) cs+  where+    go :: Char -> Int -> [Char] -> [(Char, Char)]+    go lower prev [] = [(lower, toEnum prev)]+    go lower prev (c:cs)+      | i <- fromEnum c, i == prev + 1 = go lower i cs+      | otherwise = (lower, toEnum prev) : go c (fromEnum c) cs++{-|+Like `string`, excepts parses the given string atomically using `try`. Never consumes input on+failure.++@since 2.0.0.0+-}+token :: String -> Parser String+token = Internal.try . string++{-|+This combinator will attempt to match a given character. If that character is the next input token,+the parser succeeds and the character is returned. Otherwise, the combinator will fail having not+consumed any input.++@since 2.0.0.0+-}+char :: Char -> Parser Char+char c = satisfy (RANGES True [(c, c)]) $> LIFTED c++{-|+Reads any single character. This combinator will only fail if there is no more input remaining.+The parsed character is returned.++@since 2.0.0.0+-}+item :: Parser Char+item = satisfy (RANGES False [])++isDigit :: Defunc (Char -> Bool)+isDigit = RANGES True [('0', '9')]++{-|+Reads a digit (0 through 9).++@since 2.0.0.0+-}+digit :: Parser Char+digit = satisfy isDigit++{-|+Uses `isAlpha` to parse a letter, this includes+unicode letters.++@since 2.0.0.0+-}+letter :: Parser Char+letter = satisfy (makeQ isAlpha [||isAlpha||])++{-|+Uses `isAlphaNum` to parse a letter, this includes+unicode letters, or a digit.++@since 2.0.0.0+-}+letterOrDigit :: Parser Char+letterOrDigit = satisfy (makeQ isAlphaNum [||isAlphaNum||])
src/ghc/Parsley/Combinator.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS_GHC -Wno-incomplete-patterns #-}-{-# LANGUAGE PatternSynonyms, ViewPatterns #-} {-| Module      : Parsley.Combinator Description : The parsing combinators@@ -7,15 +5,12 @@ Maintainer  : Jamie Willis Stability   : stable -This module contains the classic parser combinator operations specific to parsers themselves.-This means any combinators that deal with input consumption at a primitive level.+This module contains the classic parser combinator operations specific to parsers themselves, excluding+those that consume input.  @since 0.1.0.0 -} module Parsley.Combinator (-    satisfy, char, item,-    string, token,-    oneOf, noneOf,     eof, more,     someTill,     try,@@ -23,13 +18,11 @@     line, col, pos   ) where -import Prelude hiding           (traverse, (*>))-import Data.List                (sort)+import Prelude hiding           ((*>)) import Parsley.Alternative      (manyTill)-import Parsley.Applicative      (($>), void, traverse, (<:>), (*>), (<~>))-import Parsley.Defunctionalized (Defunc(LIFTED, EQ_H, CONST, LAM_S), pattern APP_H, pattern COMPOSE_H)-import Parsley.Internal         (Code, Quapplicative(..), Parser)-import Parsley.ParserOps        (satisfy)+import Parsley.Applicative      (void, (<:>), (*>), (<~>))+import Parsley.Internal         (Parser)+import Parsley.Char             (item)  import qualified Parsley.Internal as Internal (try, lookAhead, notFollowedBy, line, col) @@ -70,66 +63,6 @@ try = Internal.try  {-|-This combinator will attempt match a given string. If the parser fails midway through, this-combinator will fail having consumed input. On success, the string itself is returned and input-will be consumed.--@since 0.1.0.0--}-string :: String -> Parser String-string = traverse char--{-|-This combinator will attempt to match any one of the provided list of characters. If one of those-characters is found, it will be returned and the input consumed. If not, the combinator will fail-having consumed no input.--@since 0.1.0.0--}-oneOf :: [Char] -> Parser Char-oneOf = satisfy . elem'--{-|-This combinator will attempt to not match any one of the provided list of characters. If one of those-characters is found, the combinator will fail having consumed no input. If not, it will return-the character that was not an element of the provided list.--@since 0.1.0.0--}-noneOf :: [Char] -> Parser Char-noneOf = satisfy . COMPOSE_H (makeQ not [||not||]) . elem'--elem' :: [Char] -> Defunc (Char -> Bool)-elem' cs = LAM_S (\c -> makeQ (elem (_val c) cs) (ofChars cs (_code c)))--ofChars :: [Char] -> Code Char -> Code Bool-ofChars [] _ = [||False||]-ofChars cs qc = foldr1 (\p q -> [|| $$p || $$q ||]) (map (makePred qc) (ranges cs))--makePred :: Code Char -> (Char, Char) -> Code Bool-makePred qc (c, c')-  | c == c' = [|| c == $$qc ||]-  | otherwise = [|| c <= $$qc && $$qc <= c' ||]--ranges :: [Char] -> [(Char, Char)]-ranges (sort -> c:cs) = go c (fromEnum c) cs-  where-    go :: Char -> Int -> [Char] -> [(Char, Char)]-    go lower prev [] = [(lower, toEnum prev)]-    go lower prev (c:cs)-      | i <- fromEnum c, i == prev + 1 = go lower i cs-      | otherwise = (lower, toEnum prev) : go c (fromEnum c) cs--{-|-Like `string`, excepts parses the given string atomically using `try`. Never consumes input on-failure.--@since 0.1.0.0--}-token :: String -> Parser String-token = try . string--{-| This parser succeeds only if there is no input left to consume, and fails without consuming input otherwise. @@ -145,26 +78,6 @@ -} more :: Parser () more = lookAhead (void item)---- Parsing Primitives-{-|-This combinator will attempt to match a given character. If that character is the next input token,-the parser succeeds and the character is returned. Otherwise, the combinator will fail having not-consumed any input.--@since 0.1.0.0--}-char :: Char -> Parser Char-char c = satisfy (EQ_H (LIFTED c)) $> LIFTED c--{-|-Reads any single character. This combinator will only fail if there is no more input remaining.-The parsed character is returned.--@since 0.1.0.0--}-item :: Parser Char-item = satisfy (APP_H CONST (LIFTED True))  -- Composite Combinators {-|
src/ghc/Parsley/Debug.hs view
@@ -1,3 +1,14 @@+{-|+Module      : Parsley.Debug+Description : Debug combinators+License     : BSD-3-Clause+Maintainer  : Jamie Willis+Stability   : stable++This module contains debugging combinators.++@since 2.0.0.0+-} module Parsley.Debug (debug) where  import Parsley.Internal (Parser)
src/ghc/Parsley/Fold.hs view
@@ -16,18 +16,18 @@     skipMany, skipSome, skipManyN, --loop,     sepBy, sepBy1, endBy, endBy1, sepEndBy, sepEndBy1,     chainl1, chainr1, chainl, chainr,-    chainl1', chainr1', chainPre, chainPost,-    pfoldr, pfoldl,-    pfoldr1, pfoldl1+    infixl1, infixr1, prefix, postfix,+    manyr, manyl,+    somer, somel   ) where  import Prelude hiding           (pure, (<*>), (<$>), (*>), (<*)) import Parsley.Alternative      ((<|>), option) import Parsley.Applicative      (pure, (<*>), (<$>), (*>), (<*), (<:>), (<**>), void)-import Parsley.Defunctionalized (Defunc(FLIP, ID, COMPOSE, EMPTY, CONS, CONST), pattern FLIP_H, pattern COMPOSE_H, pattern UNIT)+import Parsley.Defunctionalized (Defunc(FLIP, ID, COMPOSE, EMPTY, CONS, CONST, APP_H), pattern FLIP_H, pattern UNIT) import Parsley.Internal         (Parser) import Parsley.ParserOps        (ParserOps)-import Parsley.Register         (bind, get, put, modify, newRegister, newRegister_)+import Parsley.Register         (get, modify, newRegister, newRegister_)  import qualified Parsley.Internal as Internal (loop) @@ -37,7 +37,7 @@  > loop body exit = let go = body *> go <|> exit in go -@since 1.1.0.0+@since 2.0.0.0 -} loop :: Parser () -> Parser a -> Parser a loop = Internal.loop@@ -46,12 +46,12 @@ This combinator parses repeated applications of an operator to a single final operand. This is primarily used to parse prefix operators in expressions. -@since 0.1.0.0+@since 2.0.0.0 -}-chainPre :: Parser (a -> a) -> Parser a -> Parser a-chainPre op p =-  newRegister (pure ID) (\r ->-    loop (put r (pure (FLIP_H COMPOSE) <*> op <*> get r))+prefix :: Parser (a -> a) -> Parser a -> Parser a+prefix op p =+  newRegister_ ID (\r ->+    loop (modify r (FLIP_H COMPOSE <$> op))          (get r))   <*> p @@ -59,99 +59,95 @@ This combinator parses repeated applications of an operator to a single initial operand. This is primarily used to parse postfix operators in expressions. -@since 0.1.0.0+@since 2.0.0.0 -}-chainPost :: Parser a -> Parser (a -> a) -> Parser a-chainPost p op =+postfix :: Parser a -> Parser (a -> a) -> Parser a+postfix p op =   newRegister p $ \r ->-    loop (put r (op <*> get r))+    loop (modify r op)          (get r)  -- Parser Folds {-|-@pfoldr f k p@ parses __zero__ or more @p@s and combines the results using the function @f@. When @p@+@manyr f k p@ parses __zero__ or more @p@s and combines the results using the function @f@. When @p@ fails without consuming input, the terminal result @k@ is returned. -> many = pfoldr CONS EMPTY+> many = manyr CONS EMPTY -@since 0.1.0.0+@since 2.0.0.0 -}-pfoldr :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b-pfoldr f k p = chainPre (f <$> p) (pure k)+manyr :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b+manyr f k p = prefix (f <$> p) (pure k)  {-|-@pfoldr1 f k p@ parses __one__ or more @p@s and combines the results using the function @f@. When @p@+@somer f k p@ parses __one__ or more @p@s and combines the results using the function @f@. When @p@ fails without consuming input, the terminal result @k@ is returned. -> some = pfoldr1 CONS EMPTY+> some = somer CONS EMPTY -@since 0.1.0.0+@since 2.0.0.0 -}-pfoldr1 :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b-pfoldr1 f k p = f <$> p <*> pfoldr f k p+somer :: (ParserOps repf, ParserOps repk) => repf (a -> b -> b) -> repk b -> Parser a -> Parser b+somer f k p = f <$> p <*> manyr f k p  {-|-@pfoldl f k p@ parses __zero__ or more @p@s and combines the results using the function @f@. The+@manyl f k p@ parses __zero__ or more @p@s and combines the results using the function @f@. The accumulator is initialised with the value @k@. -@since 0.1.0.0+@since 2.0.0.0 -}-pfoldl :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b-pfoldl f k p = chainPost (pure k) ((FLIP <$> pure f) <*> p)+manyl :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b+manyl f k p = postfix (pure k) ((FLIP <$> pure f) <*> p)  {-|-@pfoldl1 f k p@ parses __one__ or more @p@s and combines the results using the function @f@. The+@somel f k p@ parses __one__ or more @p@s and combines the results using the function @f@. The accumulator is initialised with the value @k@. -@since 0.1.0.0+@since 2.0.0.0 -}-pfoldl1 :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b-pfoldl1 f k p = chainPost (f <$> pure k <*> p) ((FLIP <$> pure f) <*> p)+somel :: (ParserOps repf, ParserOps repk) => repf (b -> a -> b) -> repk b -> Parser a -> Parser b+somel f k p = postfix (f <$> pure k <*> p) ((FLIP <$> pure f) <*> p)  -- Chain Combinators {-|-@chainl1' wrap p op @ parses one or more occurrences of @p@, separated by @op@. Returns a value obtained+@infixl1 wrap p op @ parses one or more occurrences of @p@, separated by @op@. Returns a value obtained by a /left/ associative application of all functions returned by @op@ to the values returned by @p@. The function @wrap@ is used to transform the initial value from @p@ into the correct form. -@since 0.1.0.0+@since 2.0.0.0 -}-chainl1' :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (b -> a -> b) -> Parser b-chainl1' f p op = chainPost (f <$> p) (FLIP <$> op <*> p)+infixl1 :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (b -> a -> b) -> Parser b+infixl1 wrap p op = postfix (wrap <$> p) (FLIP <$> op <*> p)  {-|-The classic version of the left-associative chain combinator. See 'chainl1''.+The classic version of the left-associative chain combinator. See 'infixl1'. -> chainl1 p op = chainl1' ID p op+> chainl1 p op = infixl1 ID p op  @since 0.1.0.0 -} chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a-chainl1 = chainl1' ID+chainl1 = infixl1 ID  {-|-@chainr1' wrap p op @ parses one or more occurrences of @p@, separated by @op@. Returns a value obtained+@infixr1 wrap p op @ parses one or more occurrences of @p@, separated by @op@. Returns a value obtained by a /right/ associative application of all functions returned by @op@ to the values returned by @p@. The function @wrap@ is used to transform the final value from @p@ into the correct form. -@since 0.1.0.0+@since 2.0.0.0 -}-chainr1' :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (a -> b -> b) -> Parser b-chainr1' f p op = newRegister_ ID $ \acc ->-  let go = bind p $ \x ->-           modify acc (FLIP_H COMPOSE <$> (op <*> x)) *> go-       <|> f <$> x-  in go <**> get acc+infixr1 :: ParserOps rep => rep (a -> b) -> Parser a -> Parser (a -> b -> b) -> Parser b+infixr1 wrap p op = let go = p <**> (FLIP <$> op <*> go <|> pure wrap) in go  {-|-The classic version of the right-associative chain combinator. See 'chainr1''.+The classic version of the right-associative chain combinator. See 'infixr1'. -> chainr1 p op = chainr1' ID p op+> chainr1 p op = infixr1 ID p op  @since 0.1.0.0 -} chainr1 :: Parser a -> Parser (a -> a -> a) -> Parser a-chainr1 = chainr1' ID+chainr1 = infixr1 ID  {-| Like `chainr1`, but may parse zero occurences of @p@ in which case the value is returned.@@ -177,7 +173,7 @@ @since 0.1.0.0 -} many :: Parser a -> Parser [a]-many = pfoldr CONS EMPTY+many = manyr CONS EMPTY  {-| Attempts to parse the given parser __n__ or more times, collecting all of the successful results@@ -203,9 +199,8 @@ @since 0.1.0.0 -} skipMany :: Parser a -> Parser ()---skipMany p = let skipManyp = p *> skipManyp <|> unit in skipManyp-skipMany = void . pfoldl CONST UNIT -- the void here will encourage the optimiser to recognise that the register is unused---skipMany = flip loop (pure UNIT) . void -- This should be the optimal one, with register removed, but apparently not?! something is amiss, perhaps space leak?+--skipMany p = loop (void p) unit+skipMany = void . manyl CONST UNIT -- This is still faster, the above generates better code, but GHC starts doing weird things!  {-| Like `manyN`, excepts discards its results.@@ -275,13 +270,7 @@ @since 0.1.0.0 -} sepEndBy1 :: Parser a -> Parser b -> Parser [a]-sepEndBy1 p sep = newRegister_ ID $ \acc ->-  let go = modify acc (COMPOSE_H (FLIP_H COMPOSE) CONS <$> p)-         *> (sep *> (go <|> get acc) <|> get acc)-  in go <*> pure EMPTY--{-sepEndBy1 :: Parser a -> Parser b -> Parser [a] sepEndBy1 p sep =   let seb1 = p <**> (sep *> (FLIP_H CONS <$> option EMPTY seb1)                  <|> pure (APP_H (FLIP_H CONS) EMPTY))-  in seb1-}+  in seb1
src/ghc/Parsley/ParserOps.hs view
@@ -1,3 +1,15 @@+{-|+Module      : Parsley.ParserOps+Description : Combinators that interact with user-defined functions.+License     : BSD-3-Clause+Maintainer  : Jamie Willis+Stability   : stable++This module contains the definition of `ParserOps`, which is used to generalise+the representation of user-defined functions to either `Defunc` or `WQ`.++@since 2.0.0.0+-} module Parsley.ParserOps (module Parsley.ParserOps) where  import Prelude hiding (pure)
src/ghc/Parsley/Precedence.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE AllowAmbiguousTypes,-             MultiParamTypeClasses #-}+{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances #-} {-| Module      : Parsley.Precedence Description : The precedence parser functionality@@ -10,100 +9,247 @@ This module exposes the required machinery for parsing expressions given by a precedence table. Unlike those found in [parser-combinators](https://hackage.haskell.org/package/parser-combinators-1.3.0/docs/Control-Monad-Combinators-Expr.html) or [parsec](https://hackage.haskell.org/package/parsec-3.1.14.0/docs/Text-Parsec-Expr.html), this-implementation allows the precedence layers to change type in the table.+implementation allows the precedence layers to change type in the table. This implementation is+based off of /Design Patterns for Parser Combinators (Willis and Wu 21)/.  @since 0.1.0.0 -}-module Parsley.Precedence (module Parsley.Precedence) where+module Parsley.Precedence (+    -- * Main Precedence Combinators+    -- $prec-doc+    precedence, precHomo,+    -- * Operator Fixity+    Fixity(..),+    -- * Level Construction+    -- $ops-doc+    Op,+    GOps(..), sops, ops,+    -- * Level Combining+    -- $levels-doc+    Prec(..), (>+), (+<),+    -- * Subtype Relation+    Subtype(..),+  ) where -import Prelude hiding           ((<$>))-import Parsley.Alternative      (choice)-import Parsley.Applicative      ((<$>))-import Parsley.Defunctionalized (Defunc(BLACK, ID))-import Parsley.Fold             (chainPre, chainPost, chainl1', chainr1')-import Parsley.Internal         (WQ, Parser)+import Prelude hiding                ((<$>), (<*>), pure)+import Data.List                     (foldl') +import Parsley.Alternative           (choice, (<|>))+import Parsley.Applicative           ((<$>), (<*>), pure, (<**>))+import Parsley.Fold                  (prefix, postfix, infixl1, infixr1)+import Parsley.Internal.Common.Utils (WQ(WQ))+import Parsley.Internal.Core         (Parser, Defunc(BLACK, ID, FLIP))++--import qualified Data.Generics.Internal.Profunctor.Prism as GLens+--import qualified Data.Generics.Sum.Internal.Subtype as GLens++{- $prec-doc+Compared to using chain combinators to construct parsers for expression grammars, precedence+combinators provide a light-weight and convenient representation of a precedence table. In @parsley@+these take two forms: a more traditional version called `precHomo` which takes a list of precedence+levels which are all of the same, monolithic, type; and a heterogeneous version called `precedence`.++In /Design Patterns for Parser Combinators/ it is mentioned that the homogeneous approach to+encoding precedence tables can inadvertently misrepresent the grammar: say by changing+left-associative operators into right-associative ones. When the grammar doesn't specify+associativities, then `precHomo` is perfectly appropriate, as it becomes an implementation decision.+Otherwise, `precedence` uses a heterogeneous list to form a precedence table, allowing each layer of+operators to form part of a different datatype. By encoding the resulting AST as a hierarchy of+independent datatypes for each grammar rule, the precedence table can be made to be very strict:+reordering levels or switching their associativities will fail to compile!+-}+ {-|-This combinator will construct and expression parser will provided with a table of precedence along-with a terminal atom.+This combinator will construct and expression parser will provided with a table of precedence. -@since 0.1.0.0+@since 2.0.0.0 -}-precedence :: Prec a b -> Parser a -> Parser b-precedence NoLevel atom = atom-precedence (Level lvl lvls) atom = precedence lvls (level lvl atom)+precedence :: Prec a -> Parser a+precedence (Atom atom) = atom+precedence (Level lvls op) = level (precedence lvls) op   where-    level (InfixL ops wrap) atom  = chainl1' wrap atom (choice ops)-    level (InfixR ops wrap) atom  = chainr1' wrap atom (choice ops)-    level (Prefix ops wrap) atom  = chainPre (choice ops) (wrap <$> atom)-    level (Postfix ops wrap) atom = chainPost (wrap <$> atom) (choice ops)+    level :: Parser a -> Op a b -> Parser b+    level atom (Op InfixL op wrap) = infixl1 wrap atom op+    level atom (Op InfixR op wrap) = infixr1 wrap atom op+    level atom (Op InfixN op wrap) = atom <**> (FLIP <$> op <*> atom <|> pure wrap)+    level atom (Op Prefix op wrap) = prefix op (wrap <$> atom)+    level atom (Op Postfix op wrap) = postfix (wrap <$> atom) op  {-| A simplified version of `precedence` that does not use the heterogeneous list `Prec`, but-instead requires all layers of the table to have the same type.+instead requires all layers of the table to have the same type. The list encodes the precedence+in strongest-to-weakest layout. -@since 0.1.0.0+@since 2.0.0.0 -}-monolith :: [Level a a] -> Prec a a-monolith = foldr Level NoLevel+precHomo :: Parser a -- ^ The root atom of the precedence hierarchy+         -> [Op a a] -- ^ Each layer laid out strongest-to-weakest binding.+         -> Parser a+precHomo atom = precedence . foldl' (>+) (Atom atom)  {-|-A heterogeneous list that represents a precedence table so that @Prec a b@ transforms the type @a@-into @b@ via various layers of operators.+Denotes the fixity of a given level in a precedence table. The type parameter @sig@ encodes the+types of the operators on this level, in a heterogeneous fashion. -@since 0.1.0.0+@since 2.0.0.0 -}-data Prec a b where-  NoLevel :: Prec a a-  Level :: Level a b -> Prec b c -> Prec a c+data Fixity a b sig where+  -- | Denotes a left-associative binary operator.+  InfixL  :: Fixity a b (b -> a -> b)+  -- | Denotes a right-associative binary operator.+  InfixR  :: Fixity a b (a -> b -> b)+  -- | Denotes a non-associative binary operator.+  InfixN  :: Fixity a b (a -> a -> b)+  -- | Denotes a prefix unary operator.+  Prefix  :: Fixity a b (b -> b)+  -- | Denotes a postfix unary operator.+  Postfix :: Fixity a b (b -> b) +{- $ops-doc+By combining a `Fixity` with a `Parser` which can read the operators at a given level, a new+level can be created, ready to add to the table. To provide uniformity and safety, the `Fixity`+type exposes a @sig@ type that expresses the shape of operators that match it. The `Op` datatype,+which is not constructed directly, ties the operators to this signature using existentials.++There are three ways to create a value of type `Op`: `ops`, `sops`, and `gops`. These functions+represent different degrees of relations between this layer of the table, and the one that comes+below:++  - `ops` says that the level below is the same type as this one, in other words the classic+    @a -> a -> a@ type for binary operators.+  - `sops` is stronger, and says that the level below must be a sub-type of this one (see `Subtype`).+    This means that there is a known canonical embedding from one layer into the other, called an+    `upcast`.+  - `gops` is the most general, and says that the level below is related to this one by some more+    complex transformation than the canonical sub-type embedding. Any arbitrary function from+    @underlying -> this@ can be provided to this level to handle the translation.+-}+ {-|-This datatype represents levels of the precedence table `Prec`, where each constructor-takes many parsers of the same level and fixity.+Packages together a level of a precedence table, by associating a `Fixity` with the operators that+match that specific signature converting from one layer of type @a@ to a new layer of type @b@.+See `ops`, `sops`, and `gops` for how to construct them. -@since 0.1.0.0+@since 2.0.0.0 -}-data Level a b = InfixL  [Parser (b -> a -> b)] (Defunc (a -> b)) -- ^ left-associative infix operators-               | InfixR  [Parser (a -> b -> b)] (Defunc (a -> b)) -- ^ right-associative infix operators-               | Prefix  [Parser (b -> b)]      (Defunc (a -> b)) -- ^ prefix unary operators-               | Postfix [Parser (b -> b)]      (Defunc (a -> b)) -- ^ postfix unary operators+data Op a b where+  Op :: Fixity a b sig -> Parser sig -> Defunc (a -> b) -> Op a b  {-|-This class provides a way of working with the t`Level` datatype without needing to-provide wrappers, or not providing `Defunc` arguments.+This typeclass is used to allow abstraction of the representation of user-level functions.+See the instances for information on what these representations are. -@since 0.1.0.0+@since 2.0.0.0 -}-class Monolith a b c where-  -- | Used to construct a precedence level of infix left-associative operators-  infixL  :: [Parser (b -> a -> b)] -> c-  -- | Used to construct a precedence level of infix right-associative operators-  infixR  :: [Parser (a -> b -> b)] -> c-  -- | Used to construct a precedence level of prefix operators-  prefix  :: [Parser (b -> b)]      -> c-  -- | Used to construct a precedence level of postfix operators-  postfix :: [Parser (b -> b)]      -> c+class GOps rep where+  {-|+  Sometimes, the relationship between two levels of a heterogeneous precedence hierarchy is non-trivial.+  By using `gops`, the conversion function can be used to adapt one layer into the type of the next. +  @since 2.0.0.0+  -}+  gops :: Fixity a b sig -> [Parser sig] -> rep (a -> b) -> Op a b+ {-|-This instance is used to handle monolithic types where the input and output are the same,-it does not require the wrapping function to be provided.+This is the default representation used for user-level functions and values: plain old code. -@since 0.1.0.0+@since 2.0.0.0 -}-instance x ~ a => Monolith x a (Level a a) where-  infixL  = flip InfixL ID-  infixR  = flip InfixR ID-  prefix  = flip Prefix ID-  postfix = flip Postfix ID+instance GOps WQ where+  gops fixity ps = gops fixity ps . BLACK  {-|-This instance is used to handle non-monolithic types: i.e. where the input and output types of-a level differ.+This is used to allow defunctionalised versions of many standard Haskell functions to be used+directly as an argument to relevant combinators. -@since 0.1.0.0+@since 2.0.0.0 -}-instance {-# INCOHERENT #-} x ~ (WQ (a -> b) -> Level a b) => Monolith a b x where-  infixL  ops = InfixL ops . BLACK-  infixR  ops = InfixR ops . BLACK-  prefix  ops = Prefix ops . BLACK-  postfix ops = Postfix ops . BLACK+instance {-# INCOHERENT #-} x ~ Defunc => GOps x where+  gops fixity ps = Op fixity (choice ps)++{-|+When two levels in a precedence hierarchy are the same type, they are trivially embedded using the+identity function.++@since 2.0.0.0+-}+ops :: Fixity a a sig -> [Parser sig] -> Op a a+ops fixity ps = Op fixity (choice ps) ID++{-|+Encodes a subtyping relationship between two types @sub@ and @sup@. This allows for the conversion+or embedding of one type into the other, as well as their extraction.++It should be the case that:++prop> fmap upcast . downcast = Just+prop> downcast . upcast = Just++@since 2.0.0.0+-}+class Subtype sub sup where+  -- | Casts a value of the subtype into one of the supertype, likely by wrapping it in some constructor+  upcast   :: sub -> sup+  -- | Attempts to extract a value of a subtype from a supertype+  downcast :: sup -> Maybe sub++{-instance GLens.Context sub sup => Subtype sub sup where+  upcast = GLens.build GLens.derived+  downcast = either (const Nothing) Just . GLens.match GLens.derived-}++{-|+When two levels of a precedence hierarchy are in a subtyping relation, the conversion between+the two can be trivially provided as the `upcast` function.++@since 2.0.0.0+-}+sops :: Subtype a b => Fixity a b sig -> [Parser sig] -> Op a b+sops fixity ps = gops fixity ps (WQ upcast [||upcast||])++{- $levels-doc+Independently, `Op`s are meaningless: they must be combined together to form a table to be useful.+The `Prec` datatype encodes the structure linking together each `Op` level in turn.++The base case+for the table is called `Atom`, which takes a parser for the root of the table: think numbers,+variables, bracketed expressions, and the like.++The `Level` constructor is used to add layers on top of the growing table. It's not designed to be+used directly, which would be clunky, instead use the `(>+)` and `(+<)` operators. These operators+are sugar for `Level`, but allow freedom over which way round the table should be expressed: use+`(>+)` to build the table from strongest- to weakest-binding (with the atom at the front); use+`(+<)` to build the table from weakest- to strongest-binding (with the atom at the end). The direction+the table should be built in is purely stylistic.+-}++{-|+A heterogeneous list that represents a precedence table so that @Prec a@ produces values of type+@a@.++@since 2.0.0.0+-}+data Prec a where+  -- | A Level of the table, containing the sub-level and the operators. See `(>+)` and `(+<)`.+  Level :: Prec a -> Op a b -> Prec b+  -- | The terminal atom in the table.+  Atom :: Parser a -> Prec a++infixl 5 >++{-|+Sugar for the `Level` constructor, this operator - along with its sibling - is hungry and greedy: it+eats the levels with the higher precedence: in @lvls >+ lvl@, @lvl@ is lower precedence than @lvls@.++@since 2.0.0.0+-}+(>+) :: Prec a -> Op a b -> Prec b+(>+) = Level++infixr 5 +<+{-|+Sugar for the `Level` constructor, this operator - along with its sibling - is hungry and greedy: it+eats the levels with the higher precedence: in @lvl +< lvls@, @lvl@ is lower precedence than @lvls@.++@since 2.0.0.0+-}+(+<) :: Op a b -> Prec a -> Prec b+(+<) = flip (>+)
test/Parsley/Alternative/Test.hs view
@@ -6,7 +6,6 @@ import qualified Parsley.Alternative.Parsers as Parsers  import Prelude hiding ()-import Parsley (runParser)  tests :: TestTree tests = testGroup "Alternative" [ coproductTests
test/Parsley/Applicative/Test.hs view
@@ -6,7 +6,6 @@ import qualified Parsley.Applicative.Parsers as Parsers  import Prelude hiding ()-import Parsley (runParser) import Parsley.Applicative (unit)  tests :: TestTree
+ test/Parsley/Char/Parsers.hs view
@@ -0,0 +1,10 @@+module Parsley.Char.Parsers where++import Parsley (Parser)+import Parsley.Char (oneOf)++abc :: Parser Char+abc = oneOf ['a', 'b', 'c']++nothing :: Parser Char+nothing = oneOf []
+ test/Parsley/Char/Test.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE TemplateHaskell, UnboxedTuples, ScopedTypeVariables #-}+module Parsley.Char.Test where+import Test.Tasty+import Test.Tasty.HUnit+import TestUtils+import qualified Parsley.Char.Parsers as Parsers++import Prelude hiding ((*>))+import Parsley ((*>))+import Parsley.Char (char, item)++tests :: TestTree+tests = testGroup "Char" [ stringTests+                         , oneOfTests+                         , noneOfTests+                         , tokenTests+                         , charTests+                         , itemTests+                         ]++stringTests :: TestTree+stringTests = testGroup "string should" []++nothing :: String -> Maybe Char+nothing = $$(runParserMocked Parsers.nothing [||Parsers.nothing||])++abc :: String -> Maybe Char+abc = $$(runParserMocked Parsers.abc [||Parsers.abc||])++oneOfTests :: TestTree+oneOfTests = testGroup "oneOf should"+  [ testCase "handle no options no input" $ nothing "" @?= Nothing+  , testCase "handle no options with input" $ nothing "a" @?= Nothing+  , testCase "parse any of characters" $ do+      abc "a" @?= Just 'a'+      abc "b" @?= Just 'b'+      abc "c" @?= Just 'c'+  , testCase "fail otherwise" $ abc "d" @?= Nothing+  ]++noneOfTests :: TestTree+noneOfTests = testGroup "noneOf should" []++tokenTests :: TestTree+tokenTests = testGroup "token should" []++charA :: String -> Maybe Char+charA = $$(runParserMocked (char 'a') [||char 'a'||])++charTests :: TestTree+charTests = testGroup "char should"+  [ testCase "fail on empty input" $ charA "" @?= Nothing+  , testCase "succeed on correct char" $ charA "a" @?= Just 'a'+  , testCase "fail on wrong char" $ charA "b" @?= Nothing+  ]++itemTests :: TestTree+itemTests = testGroup "item should" []
test/Parsley/Combinator/Parsers.hs view
@@ -1,10 +1,1 @@ module Parsley.Combinator.Parsers where--import Parsley (Parser)-import Parsley.Combinator (oneOf)--abc :: Parser Char-abc = oneOf ['a', 'b', 'c']--nothing :: Parser Char-nothing = oneOf []
test/Parsley/Combinator/Test.hs view
@@ -6,47 +6,16 @@ import qualified Parsley.Combinator.Parsers as Parsers  import Prelude hiding ((*>))-import Parsley (runParser, (*>))-import Parsley.Combinator (eof, more, char, item)+import Parsley ((*>))+import Parsley.Combinator (eof, more)+import Parsley.Char       (char)  tests :: TestTree-tests = testGroup "Combinator" [ stringTests-                               , oneOfTests-                               , noneOfTests-                               , tokenTests-                               , eofTests+tests = testGroup "Combinator" [ eofTests                                , moreTests-                               , charTests-                               , itemTests                                , someTillTests                                ] -stringTests :: TestTree-stringTests = testGroup "string should" []--nothing :: String -> Maybe Char-nothing = $$(runParserMocked Parsers.nothing [||Parsers.nothing||])--abc :: String -> Maybe Char-abc = $$(runParserMocked Parsers.abc [||Parsers.abc||])--oneOfTests :: TestTree-oneOfTests = testGroup "oneOf should"-  [ testCase "handle no options no input" $ nothing "" @?= Nothing-  , testCase "handle no options with input" $ nothing "a" @?= Nothing-  , testCase "parse any of characters" $ do-      abc "a" @?= Just 'a'-      abc "b" @?= Just 'b'-      abc "c" @?= Just 'c'-  , testCase "fail otherwise" $ abc "d" @?= Nothing-  ]--noneOfTests :: TestTree-noneOfTests = testGroup "noneOf should" []--tokenTests :: TestTree-tokenTests = testGroup "token should" []- isNull :: String -> Maybe () isNull = $$(runParserMocked eof [||eof||]) @@ -68,19 +37,6 @@   , testCase "succeed on non-empty input" $ notNull "a" @?= Just ()   , testCase "not consume input" $ notNullThenA "a" @?= Just 'a'   ]--charA :: String -> Maybe Char-charA = $$(runParserMocked (char 'a') [||char 'a'||])--charTests :: TestTree-charTests = testGroup "char should"-  [ testCase "fail on empty input" $ charA "" @?= Nothing-  , testCase "succeed on correct char" $ charA "a" @?= Just 'a'-  , testCase "fail on wrong char" $ charA "b" @?= Nothing-  ]--itemTests :: TestTree-itemTests = testGroup "item should" []  someTillTests :: TestTree someTillTests = testGroup "someTill should" []
test/Parsley/Fold/Parsers.hs view
@@ -7,19 +7,19 @@ --import Parsley.Garnish  plusOne :: Parser Int-plusOne = chainPre (string "++" $> [|succ|]) (char '1' $> [|1|])+plusOne = prefix (string "++" $> [|succ|]) (char '1' $> [|1|])  plusOne' :: Parser Int-plusOne' = chainPre (try (string "++") $> [|succ|]) (char '1' $> [|1|])+plusOne' = prefix (try (string "++") $> [|succ|]) (char '1' $> [|1|])  plusOnePure :: Parser Int-plusOnePure = try (chainPre (string "++" $> [|succ|]) (pure [|1|])) <|> pure [|0|]+plusOnePure = try (prefix (string "++" $> [|succ|]) (pure [|1|])) <|> pure [|0|]  onePlus :: Parser Int-onePlus = chainPost (char '1' $> [|1|]) (string "++" $> [|succ|])+onePlus = postfix (char '1' $> [|1|]) (string "++" $> [|succ|])  onePlus' :: Parser Int-onePlus' = chainPost (char '1' $> [|1|]) (try (string "++") $> [|succ|])+onePlus' = postfix (char '1' $> [|1|]) (try (string "++") $> [|succ|])  manyAA :: Parser [String] manyAA = many (string "aa")
test/Parsley/Fold/Test.hs view
@@ -6,15 +6,18 @@ import qualified Parsley.Fold.Parsers as Parsers  import Prelude hiding ()-import Parsley (runParser)  tests :: TestTree-tests = testGroup "Fold" [ chainPreTests-                         , chainPostTests-                         , pfoldrTests-                         , pfoldlTests+tests = testGroup "Fold" [ prefixTests+                         , postfixTests+                         , manyrTests+                         , somerTests+                         , manylTests+                         , somelTests                          , chainlTests                          , chainrTests+                         , infixl1Tests+                         , infixr1Tests                          , manyTests                          , skipManyTests                          , sepByTests@@ -30,8 +33,8 @@ plusOnePure :: String -> Maybe Int plusOnePure = $$(runParserMocked Parsers.plusOnePure [||Parsers.plusOnePure||]) -chainPreTests :: TestTree-chainPreTests = testGroup "chainPre should"+prefixTests :: TestTree+prefixTests = testGroup "prefix should"   [ testCase "parse an operatorless value" $ do       plusOne "1" @?= Just 1       plusOne "" @?= Nothing@@ -49,8 +52,8 @@ onePlus' :: String -> Maybe Int onePlus' = $$(runParserMocked Parsers.onePlus' [||Parsers.onePlus'||]) -chainPostTests :: TestTree-chainPostTests = testGroup "chainPost should"+postfixTests :: TestTree+postfixTests = testGroup "postfix should"   [ testCase "require an initial value" $ do       onePlus "1" @?= Just 1       onePlus "" @?= Nothing@@ -59,17 +62,29 @@   , testCase "not fail if the operator fails with try" $ onePlus' "1+++" @?= Just 2   ] -pfoldrTests :: TestTree-pfoldrTests = testGroup "pfoldr should" [] -- pfoldr pfoldr1+manyrTests :: TestTree+manyrTests = testGroup "manyr should" [] -pfoldlTests :: TestTree-pfoldlTests = testGroup "pfoldl should" [] -- pfoldl pfoldl1+somerTests :: TestTree+somerTests = testGroup "somer should" [] +manylTests :: TestTree+manylTests = testGroup "manyl should" []++somelTests :: TestTree+somelTests = testGroup "somel should" []+ chainlTests :: TestTree-chainlTests = testGroup "chainl should" [] -- chainl1' chainl1 chainl+chainlTests = testGroup "chainl should" [] -- chainl1 chainl  chainrTests :: TestTree-chainrTests = testGroup "chainr should" [] -- chainr1' chainr1 chainr+chainrTests = testGroup "chainr should" [] -- chainr1 chainr++infixl1Tests :: TestTree+infixl1Tests = testGroup "infixl1 should" []++infixr1Tests :: TestTree+infixr1Tests = testGroup "infixr1 should" []  manyAA :: String -> Maybe [String] manyAA = $$(runParserMocked Parsers.manyAA [||Parsers.manyAA||])
test/Parsley/Precedence/Parsers.hs view
@@ -1,1 +1,42 @@+{-# LANGUAGE TemplateHaskellQuotes, MultiParamTypeClasses #-} module Parsley.Precedence.Parsers where++import Prelude hiding (pure, (<*>), (*>), (<*), (<$>), ($>), pred)+import Parsley+import Parsley.Precedence+import Parsley.Fold (somel)+import Parsley.Char (oneOf)+import Data.Char (digitToInt)++data Expr = Add Expr Expr | Mul Expr Expr | Negate Expr | Num Int deriving (Eq, Show)++number :: Parser Int+number = somel [| \x d -> x * 10 + digitToInt d |] [|0|] (oneOf ['0'..'9'])++expr :: Parser Expr+expr = precHomo ([|Num|] <$> number)+                [ ops Prefix [string "negate" $> [|Negate|]]+                , ops InfixL [char '*' $> [|Mul|]]+                , ops InfixR [char '+' $> [|Add|]]+                ]++data Pred = Or Term Pred | OfTerm Term deriving (Eq, Show)+data Term = And Not Term | OfNot Not deriving (Eq, Show)+data Not = Not Not | OfAtom Atom deriving (Eq, Show)+data Atom = T | F | Parens Pred deriving (Eq, Show)++instance Subtype Atom Not where+  upcast = OfAtom+  downcast (OfAtom x) = Just x+  downcast _          = Nothing++instance Subtype Not Term where+  upcast = OfNot+  downcast (OfNot x) = Just x+  downcast _         = Nothing++pred = precedence $+  gops InfixR [char '|' $> [|Or|]] [|OfTerm|] +<+  sops InfixR [char '&' $> [|And|]]           +<+  sops Prefix [char '!' $> [|Not|]]           +<+  Atom (char 'T' $> [|T|] <|> char 'F' $> [|F|] <|> char '(' *> ([|Parens|] <$> pred) <* char ')')
test/Parsley/Precedence/Test.hs view
@@ -1,14 +1,79 @@-{-# LANGUAGE TemplateHaskell, UnboxedTuples, ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell, UnboxedTuples, ScopedTypeVariables, MultiParamTypeClasses, GADTs, DeriveGeneric, TypeApplications, FlexibleInstances, FlexibleContexts #-}+--{-# OPTIONS_GHC -ddump-splices #-} module Parsley.Precedence.Test where import Test.Tasty import Test.Tasty.HUnit import TestUtils import qualified Parsley.Precedence.Parsers as Parsers -import Prelude hiding ()-import Parsley (runParser)+import Prelude hiding (pred)+import Parsley (empty, Parser)+--import Parsley.Patterns (deriveSubtype, deriveLiftedConstructors, deriveDeferredConstructors, Pos)+import Parsley.Precedence (Subtype(..))+--import GHC.Generics (Generic) -tests :: TestTree-tests = testGroup "Precedence should" [+{-data Foo where+  Foo :: Bar -> Foo+  Goo :: String -> Pos -> Int -> Foo+  deriving (Eq, Show, Generic)+newtype Bar = Bar Int deriving (Eq, Show, Generic) +data X a = X a a Pos++deriveSubtype ''Bar ''Foo+deriveLiftedConstructors "mk" ['X]+deriveLiftedConstructors "mk" ['Bar, 'Goo]+deriveDeferredConstructors "mkD" ['X]++testParser :: Parser (X a)+testParser = mkX empty empty+testParser' :: Parser Foo+testParser' = mkGoo empty empty+testParser'' :: Parser (a -> a -> X a)+testParser'' = mkDX-}++tests :: TestTree+tests = testGroup "Precedence" [+    precHomoTests,+    precedenceTests+    --subtypeTests   ]++expr :: String -> Maybe Parsers.Expr+expr = $$(runParserMocked Parsers.expr [||Parsers.expr||])++pred :: String -> Maybe Parsers.Pred+pred = $$(runParserMocked Parsers.pred [||Parsers.pred||])++precHomoTests :: TestTree+precHomoTests = testGroup "precHomo should"+  [ testCase "parse precedence with correct associativity" $ expr "1+3*negate5+4" @?=+        Just (Parsers.Add (Parsers.Num 1)+                          (Parsers.Add (Parsers.Mul (Parsers.Num 3)+                                                    (Parsers.Negate (Parsers.Num 5)))+                                       (Parsers.Num 4)))]++instance Subtype a a where+  upcast = id+  downcast = Just++upcast' :: Parsers.Atom -> Parsers.Term+upcast' = upcast @Parsers.Not . upcast++upcast'' :: Subtype x Parsers.Term => x -> Parsers.Pred+upcast'' = Parsers.OfTerm . upcast++precedenceTests :: TestTree+precedenceTests = testGroup "precedence should"+  [ testCase "parse precedence with correct associativity" $ pred "T|F|(T|!F)&F" @?=+        Just (Parsers.Or (upcast' Parsers.T)+                         (Parsers.Or (upcast' Parsers.F)+                                     (upcast'' (Parsers.And (upcast (Parsers.Parens+                                                               (Parsers.Or (upcast' Parsers.T)+                                                                           (upcast'' (Parsers.Not (upcast Parsers.F))))))+                                                            (upcast' Parsers.F)))))]++{-subtypeTests :: TestTree+subtypeTests = testGroup "Subtype should"+  [ testCase "upcast properly" $ upcast (Bar 5) @?= Foo (Bar 5)+  , testCase "downcast properly" $ downcast (Foo (Bar 5)) @?= Just (Bar 5) ]-}
test/Parsley/Register/Test.hs view
@@ -6,7 +6,6 @@ import qualified Parsley.Register.Parsers as Parsers  import Prelude hiding ()-import Parsley (runParser)  -- NewRegister is required for any test and can only be tested with another component -- so it is omitted
test/Regression/Parsers.hs view
@@ -4,7 +4,7 @@ import Prelude hiding (pure, (<*>), (*>), (<*)) import Data.Char (isDigit) import Parsley-import Parsley.Combinator (token)+import Parsley.Char (token) --import Parsley.Garnish  issue26_ex1 :: Parser ()
test/Regression/Tests.hs view
@@ -5,7 +5,7 @@ import TestUtils import qualified Regression.Parsers as Parsers -import Parsley (runParser)+import Parsley (parse) import Parsley.InputExtras (CharList(..))  main :: IO ()@@ -21,7 +21,7 @@   ]  issue26_ex1 :: CharList -> Maybe ()-issue26_ex1 = $$(Parsley.runParser Parsers.issue26_ex1)+issue26_ex1 = $$(Parsley.parse Parsers.issue26_ex1)  issue26_ex2 :: CharList -> Maybe ()-issue26_ex2 = $$(Parsley.runParser Parsers.issue26_ex2)+issue26_ex2 = $$(Parsley.parse Parsers.issue26_ex2)
test/TestUtils.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TemplateHaskell, TypeApplications, DeriveAnyClass, StandaloneDeriving, CPP, FlexibleInstances, MonoLocalBinds #-} module TestUtils where -import Parsley (runParser, Parser, Code)+import Parsley (parse, Parser, Code) import Parsley.Internal.Trace (Trace) import Language.Haskell.TH.Syntax #if MIN_VERSION_template_haskell(2,17,0)@@ -23,11 +23,11 @@ -- TODO Use WQ: requires lift plugin to not require any Lift instance for variables (if missing) runParserMocked :: Trace => Parser a -> Code (Parser a) -> Code (String -> Maybe a) runParserMocked p qp = [|| \s ->-    runParserMocked' $$qp `deepseq` $$(runParser p) s+    runParserMocked' $$qp `deepseq` $$(parse p) s   ||]  runParserMocked' :: Parser a -> Exp-runParserMocked' = runTestQ (QState MockQ [] []) . unTypeCode . runParser @String+runParserMocked' = runTestQ (QState MockQ [] []) . unTypeCode . parse @String  deriving instance NFData Exp deriving instance NFData Name