packages feed

parsley 0.1.0.1 → 0.1.1.0

raw patch · 12 files changed

+99/−47 lines, 12 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Parsley.Defunctionalized: [IF_S] :: Defunc Bool -> Defunc a -> Defunc a -> Defunc a
+ Parsley.Defunctionalized: [LAM_S] :: (Defunc a -> Defunc b) -> Defunc (a -> b)
+ Parsley.Defunctionalized: [LET_S] :: Defunc a -> (Defunc a -> Defunc b) -> Defunc b
+ Parsley.Internal.Backend.InstructionAnalyser: type family Length (xs :: [Type]) :: Nat
+ Parsley.Internal.Backend.Machine.InputRep: type OffWith ts = (# Int#, ts #)
+ Parsley.Internal.Common.Fresh: class (Monad n, Monad m) => RunFreshT x n m | m -> x, m -> n
+ Parsley.Internal.Core: [IF_S] :: Defunc Bool -> Defunc a -> Defunc a -> Defunc a
+ Parsley.Internal.Core: [LAM_S] :: (Defunc a -> Defunc b) -> Defunc (a -> b)
+ Parsley.Internal.Core: [LET_S] :: Defunc a -> (Defunc a -> Defunc b) -> Defunc b
+ Parsley.Internal.Core.Defunc: [IF_S] :: Defunc Bool -> Defunc a -> Defunc a -> Defunc a
+ Parsley.Internal.Core.Defunc: [LAM_S] :: (Defunc a -> Defunc b) -> Defunc (a -> b)
+ Parsley.Internal.Core.Defunc: [LET_S] :: Defunc a -> (Defunc a -> Defunc b) -> Defunc b
- Parsley.Internal.Backend.Machine.InputRep: type family Rep input
+ Parsley.Internal.Backend.Machine.InputRep: type family RepKind input

Files

ChangeLog.md view
@@ -9,3 +9,9 @@ * Moved tests and benchmarks into a subproject, which will be easier later down the line. * Removed useless `dump-core` flag (only used by test and bench, not by the library). * Fleshed out README properly!++## 0.1.1.0  -- 2021-06-10++* Added `IF_S`, `LAM_S` and `LET_S` to `Defunc`, which can be used with overloaded syntax+* Admin: Removed `idioms-plugin` and `lift-plugin` from the test suite, depending on `parsley-garnish` instead+* Fixed building with GHC 9
README.md view
@@ -1,11 +1,11 @@-# Parsley ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/j-mie6/ParsleyHaskell/CI) ![GitHub release](https://img.shields.io/github/v/release/j-mie6/ParsleyHaskell?include_prereleases&sort=semver) [![GitHub license](https://img.shields.io/github/license/j-mie6/ParsleyHaskell.svg)](https://github.com/j-mie6/ParsleyHakell/blob/master/LICENSE)+# Parsley ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/j-mie6/ParsleyHaskell/CI) ![GitHub release](https://img.shields.io/github/v/release/j-mie6/ParsleyHaskell) [![GitHub license](https://img.shields.io/github/license/j-mie6/ParsleyHaskell.svg)](https://github.com/j-mie6/ParsleyHaskell/blob/master/LICENSE) ![GitHub commits since latest release (by SemVer)](https://img.shields.io/github/commits-since/j-mie6/ParsleyHaskell/latest)  ## What is Parsley? Parsley is a very fast parser combinator library that outperforms the other libraries in both the parsec family, as well as Happy. To make this possible, it makes use of Typed Template Haskell to generate the code for the parsers. -## How do I use it? ![Hackage Version](https://img.shields.io/hackage/v/parsley)+## How do I use it? [![Hackage Version](https://img.shields.io/hackage/v/parsley)](https://hackage.haskell.org/package/parsley) ![Dependent repos (via libraries.io)](https://img.shields.io/librariesio/dependent-repos/hackage/parsley) Parsley is distributed on Hackage, and can be added by depending on the package `parsley`.  The version policy adheres to the regular Haskell PVP, but the two major versions are distinguished@@ -51,9 +51,10 @@ char c = satisfy (WQ (== c) [||(== c)||]) ``` -Using `WQ` explicitly like this can get annoying, which is what the `lift-plugin` and the-`idioms-plugin` are both for: versions compatible with Parsley can be found on my GitHub, and the-`cabal.project` in this repo shows how these should be installed until they are properly released.+Using `WQ` explicitly like this can get annoying, which is what the `parsley-garnish` package is for!+Currently, the garnish provides one plugin called `OverloadedQuotes`, which replaces the behaviour of+the default _Untyped_ Template Haskell quotes in a file so that they produce one of `WQ` or `Defunc`.+See the `Parsley.OverloadedQuotesPlugin` module in the [`parsley-garnish`](https://hackage.haskell.org/package/parsley-garnish) package for more information.  ## How does it work? In short, Parsley represents all parsers as Abstract Syntax Trees (ASTs). The representation of the@@ -70,3 +71,11 @@  ## References * This work spawned a paper at ICFP 2020: [**Staged Selective Parser Combinators**](https://dl.acm.org/doi/10.1145/3409002)++### Talks+For talks on how writing parsers changes when using Parsley see either of these:+* [*Garnishing Parsec with Parsley*](https://www.youtube.com/watch?v=tJcyY9L2z84) - Berlin Functional Programming Group, January 2021+* [*Exploring Parsley: Working with Staged Selective Parsers*](https://www.youtube.com/watch?v=Zhu-cPY1eac) - MuniHac 2020++For the technical overview of how Parsley works:+* [*Staged Selective Parser Combinators*](https://www.youtube.com/watch?v=lH65PvRgm8M) - ICFP 2020
parsley.cabal view
@@ -5,7 +5,7 @@ --                   | +------- breaking internal API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.1.0.1+version:             0.1.1.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@@ -29,7 +29,7 @@ bug-reports:         https://github.com/j-mie6/ParsleyHaskell/issues license:             BSD-3-Clause license-file:        LICENSE-author:              Jamie Willis+author:              Jamie Willis, Parsley Contributors maintainer:          Jamie Willis <j.willis19@imperial.ac.uk> category:            Parsing build-type:          Simple@@ -122,7 +122,7 @@                        text                 >= 1.2.3   && < 1.3,                        -- Not sure about this one, 0.11.0.0 introduced a type synonym for PS, so it _should_ work                        bytestring           >= 0.10.8  && < 0.12-  build-tool-depends:  cpphs:cpphs          >= 1.19+  build-tool-depends:  cpphs:cpphs          >= 1.18.8  && < 1.21   hs-source-dirs:      src/ghc   if impl(ghc >= 8.10)     hs-source-dirs:    src/ghc-8.10+
src/ghc-8.10+/Parsley/Internal/Backend/Machine/InputRep.hs view
@@ -3,9 +3,9 @@              UnboxedTuples,              StandaloneKindSignatures #-} module Parsley.Internal.Backend.Machine.InputRep (-    Rep,+    Rep, RepKind,     intSame, intLess, min#, max#,-    offWith, offWithSame, offWithShiftRight,+    OffWith, offWith, offWithSame, offWithShiftRight,     --OffWithStreamAnd(..),     UnpackedLazyByteString, emptyUnpackedLazyByteString,     Stream, dropStream,
src/ghc/Parsley/Combinator.hs view
@@ -103,7 +103,7 @@ @since 0.1.0.0 -} item :: Parser Char-item = satisfy (APP_H CONST ((makeQ True [||True||])))+item = satisfy (APP_H CONST (LIFTED True))  -- Composite Combinators {-|
src/ghc/Parsley/Internal/Backend/InstructionAnalyser.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses,              TypeFamilies,              UndecidableInstances #-}-module Parsley.Internal.Backend.InstructionAnalyser (coinsNeeded, relevancy) where+module Parsley.Internal.Backend.InstructionAnalyser (coinsNeeded, relevancy, Length) where  import Data.Kind                        (Type) import Parsley.Internal.Backend.Machine (Instr(..), MetaInstr(..))
src/ghc/Parsley/Internal/Common/Fresh.hs view
@@ -7,7 +7,8 @@     runFreshT, runFresh,     evalFreshT, evalFresh,     execFreshT, execFresh,-    MonadFresh(..), construct, mapVFreshT+    MonadFresh(..), construct, mapVFreshT,+    RunFreshT   ) where  import Control.Applicative        (liftA2)
src/ghc/Parsley/Internal/Common/Utils.hs view
@@ -25,7 +25,7 @@  @since 0.1.0.0 -}-#if __GLASGOW_HASKELL__ == 810+#if __GLASGOW_HASKELL__ >= 810 type Code :: forall (r :: RuntimeRep). TYPE r -> Type #endif #if __GLASGOW_HASKELL__ < 900
src/ghc/Parsley/Internal/Core/Defunc.hs view
@@ -37,23 +37,47 @@   -- | Wraps up any value of type `WQ`   BLACK   :: WQ a -> Defunc a +  -- Syntax constructors+  {-|+  Represents the regular Haskell @if@ syntax++  @since 0.1.1.0+  -}+  IF_S    :: Defunc Bool -> Defunc a -> Defunc a -> Defunc a+  {-|+  Represents a Haskell lambda abstraction++  @since 0.1.1.0+  -}+  LAM_S   :: (Defunc a -> Defunc b) -> Defunc (a -> b)+  {-|+  Represents a Haskell let binding++  @since 0.1.1.0+  -}+  LET_S   :: Defunc a -> (Defunc a -> Defunc b) -> Defunc b+ {-| This instance is used to manipulate values of `Defunc`.  @since 0.1.0.0 -} instance Quapplicative Defunc where-  makeQ x qx       = BLACK (makeQ x qx)-  _val ID          = id-  _val COMPOSE     = (.)-  _val FLIP        = flip-  _val (APP_H f x) = (_val f) (_val x)-  _val (LIFTED x)  = x-  _val (EQ_H x)    = ((_val x) ==)-  _val CONS        = (:)-  _val CONST       = const-  _val EMPTY       = []-  _val (BLACK f)   = _val f+  makeQ x qx        = BLACK (makeQ x qx)+  _val ID           = id+  _val COMPOSE      = (.)+  _val FLIP         = flip+  _val (APP_H f x)  = (_val f) (_val x)+  _val (LIFTED x)   = x+  _val (EQ_H x)     = ((_val x) ==)+  _val CONS         = (:)+  _val CONST        = const+  _val EMPTY        = []+  _val (BLACK f)    = _val f+  -- Syntax+  _val (IF_S c t e) = if _val c then _val t else _val e+  _val (LAM_S f)    = \x -> _val (f (makeQ x undefined))+  _val (LET_S x f)  = let y = _val x in _val (f (makeQ y undefined))   _code = genDefunc   (>*<) = APP_H @@ -90,19 +114,24 @@ ap f x = APP_H f x  genDefunc :: Defunc a -> Code a-genDefunc ID              = [|| \x -> x ||]-genDefunc COMPOSE         = [|| \f g x -> f (g x) ||]-genDefunc FLIP            = [|| \f x y -> f y x ||]-genDefunc (COMPOSE_H f g) = [|| \x -> $$(genDefunc1 (COMPOSE_H f g) [||x||]) ||]-genDefunc CONST           = [|| \x _ -> x ||]-genDefunc FLIP_CONST      = [|| \_ y -> y ||]-genDefunc (FLIP_H f)      = [|| \x -> $$(genDefunc1 (FLIP_H f) [||x||]) ||]-genDefunc (APP_H f x)     = genDefunc1 f (genDefunc x)-genDefunc (LIFTED x)      = [|| x ||]-genDefunc (EQ_H x)        = [|| \y -> $$(genDefunc1 (EQ_H x) [||y||]) ||]-genDefunc CONS            = [|| \x xs -> x : xs ||]-genDefunc EMPTY           = [|| [] ||]-genDefunc (BLACK f)       = _code f+genDefunc ID                        = [|| \x -> x ||]+genDefunc COMPOSE                   = [|| \f g x -> f (g x) ||]+genDefunc FLIP                      = [|| \f x y -> f y x ||]+genDefunc (COMPOSE_H f g)           = [|| \x -> $$(genDefunc1 (COMPOSE_H f g) [||x||]) ||]+genDefunc CONST                     = [|| \x _ -> x ||]+genDefunc FLIP_CONST                = [|| \_ y -> y ||]+genDefunc (FLIP_H f)                = [|| \x -> $$(genDefunc1 (FLIP_H f) [||x||]) ||]+genDefunc (APP_H f x)               = genDefunc1 f (genDefunc x)+genDefunc (LIFTED x)                = [|| x ||]+genDefunc (EQ_H x)                  = [|| \y -> $$(genDefunc1 (EQ_H x) [||y||]) ||]+genDefunc CONS                      = [|| \x xs -> x : xs ||]+genDefunc EMPTY                     = [|| [] ||]+genDefunc (IF_S (LIFTED True) t _)  = genDefunc t+genDefunc (IF_S (LIFTED False) _ e) = genDefunc e+genDefunc (IF_S c t e)              = [|| if $$(genDefunc c) then $$(genDefunc t) else $$(genDefunc e) ||]+genDefunc (LAM_S f)                 = [|| \x -> $$(genDefunc1 (LAM_S f) [||x||]) ||]+genDefunc (LET_S x f)               = [|| let y = $$(genDefunc x) in $$(genDefunc (f (makeQ undefined [||y||]))) ||]+genDefunc (BLACK f)                 = _code f  genDefunc1 :: Defunc (a -> b) -> Code a -> Code b genDefunc1 ID              qx = qx@@ -115,6 +144,7 @@ genDefunc1 FLIP_CONST      _  = genDefunc ID genDefunc1 (FLIP_H f)      qx = [|| \y -> $$(genDefunc2 (FLIP_H f) qx [||y||]) ||] genDefunc1 (EQ_H x)        qy = [|| $$(genDefunc x)  == $$qy ||]+genDefunc1 (LAM_S f)       qx = genDefunc (f (makeQ undefined qx)) genDefunc1 f               qx = [|| $$(genDefunc f) $$qx ||]  genDefunc2 :: Defunc (a -> b -> c) -> Code a -> Code b -> Code c@@ -126,7 +156,7 @@ genDefunc2 FLIP_CONST      _  qy  = qy genDefunc2 (FLIP_H f)      qx qy  = genDefunc2 f qy qx genDefunc2 CONS            qx qxs = [|| $$qx : $$qxs ||]-genDefunc2 f               qx qy  = [|| $$(genDefunc f) $$qx $$qy ||]+genDefunc2 f               qx qy  = [|| $$(genDefunc1 f qx) $$qy ||]  instance Show (Defunc a) where   show COMPOSE = "(.)"@@ -140,4 +170,6 @@   show EMPTY = "[]"   show CONS = "(:)"   show CONST = "const"+  show (IF_S c b e) = concat ["(if ", show c, " then ", show b, " else ", show e, ")"]+  show (LAM_S _) = "f"   show _ = "x"
src/ghc/Parsley/Internal/Frontend/Optimiser.hs view
@@ -129,7 +129,7 @@ -- pure Right law: branch (pure (Right x)) p q          = q <*> pure x optimise (Branch (In (Pure (r@(_val -> Right x)))) _ q) = optimise (q :<*>: In (Pure (makeQ x qx))) where qx = [||case $$(_code r) of Right x -> x||] -- Generalised Identity law: branch b (pure f) (pure g) = either f g <$> b-optimise (Branch b (In (Pure f)) (In (Pure g)))         = optimise ({-([either f g])-}makeQ (either (_val f) (_val g)) [||either $$(_code f) $$(_code g)||] :<$>: b)+optimise (Branch b (In (Pure f)) (In (Pure g)))         = optimise (makeQ (either (_val f) (_val g)) [||either $$(_code f) $$(_code g)||] :<$>: b) -- Interchange law: branch (x *> y) p q                 = x *> branch y p q optimise (Branch (In (x :*>: y)) p q)                   = optimise (x :*>: optimise (Branch y p q)) -- Negated Branch law: branch b p empty                 = branch (swapEither <$> b) empty p
src/ghc/Parsley/Precedence.hs view
@@ -68,7 +68,7 @@                | Postfix [Parser (b -> b)]      (Defunc (a -> b)) -- ^ postfix unary operators  {-|-This class provides a way of working with the `Level` datatype without needing to+This class provides a way of working with the t`Level` datatype without needing to provide wrappers, or not providing `Defunc` arguments.  @since 0.1.0.0
src/ghc/Parsley/Selective.hs view
@@ -27,7 +27,7 @@ import Language.Haskell.TH.Syntax (Lift(..)) import Parsley.Alternative        (empty) import Parsley.Applicative        (pure, (<$>), liftA2, unit, constp)-import Parsley.Internal           (makeQ, Code, Parser, Defunc(ID, EQ_H), ParserOps, conditional, branch)+import Parsley.Internal           (makeQ, Parser, Defunc(ID, EQ_H, IF_S, LAM_S, LET_S, APP_H), ParserOps, conditional, branch)  {-| Similar to `branch`, except the given branch is only executed on a @Left@ returned.@@ -49,12 +49,16 @@ -} infixl 4 >??> (>??>) :: Parser a -> Parser (a -> Bool) -> Parser a-px >??> pf = select (liftA2 (makeQ g qg) pf px) empty+px >??> pf = select (liftA2 g pf px) empty   where-    g :: (a -> Bool) -> a -> Either () a-    g f x = if f x then Right x else Left ()-    qg :: Code ((a -> Bool) -> a -> Either () a)-    qg = [||\f x -> if f x then Right x else Left ()||]+    -- Not sure if I need the LET_S?+    g =+      LAM_S $ \f ->+        LAM_S $ \x ->+          LET_S x $ \x ->+            IF_S (APP_H f x)+                 (APP_H (makeQ Right [||Right||]) x)+                 (makeQ (Left ()) [||Left ()||])  {-| An alias for @(`>?>`)@.