{"id":22837780,"url":"https://github.com/j-mie6/parsleyhaskell","last_synced_at":"2025-07-16T11:06:06.936Z","repository":{"id":40347148,"uuid":"168396367","full_name":"j-mie6/ParsleyHaskell","owner":"j-mie6","description":"Reimplementation of Parsley in Haskell, with improvements","archived":false,"fork":false,"pushed_at":"2024-03-04T16:47:15.000Z","size":3700,"stargazers_count":52,"open_issues_count":2,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-25T08:18:42.509Z","etag":null,"topics":["parser-combinators","template-haskell"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/j-mie6.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-01-30T18:49:55.000Z","updated_at":"2025-03-17T15:20:57.000Z","dependencies_parsed_at":"2024-03-04T18:34:46.731Z","dependency_job_id":null,"html_url":"https://github.com/j-mie6/ParsleyHaskell","commit_stats":{"total_commits":488,"total_committers":8,"mean_commits":61.0,"dds":0.3811475409836066,"last_synced_commit":"f216d02793ccc502649e98a7c8142d3dd3ad89a6"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mie6%2FParsleyHaskell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mie6%2FParsleyHaskell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mie6%2FParsleyHaskell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mie6%2FParsleyHaskell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/j-mie6","download_url":"https://codeload.github.com/j-mie6/ParsleyHaskell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250554401,"owners_count":21449606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["parser-combinators","template-haskell"],"created_at":"2024-12-12T23:19:42.010Z","updated_at":"2025-04-24T03:27:44.079Z","avatar_url":"https://github.com/j-mie6.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Parsley ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/j-mie6/ParsleyHaskell/ci.yaml?branch=master) ![GitHub release](https://img.shields.io/github/v/release/j-mie6/ParsleyHaskell) [![GitHub license](https://img.shields.io/badge/License-BSD%203--Clause-blue.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)\n\n## What is Parsley?\nParsley is a very fast parser combinator library that outperforms the other libraries in both the\nparsec family, as well as Happy. To make this possible, it makes use of Typed Template Haskell\nto generate the code for the parsers.\n\n## 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)\nParsley is distributed on [Hackage](https://hackage.haskell.org/package/parsley), and can be added by depending on the package `parsley`.\n\nThe version policy for `parsley-core` adheres to the regular Haskell PVP, but the two major versions are distinguished: the first is the _Public API_ major version, which represents backwards incompatible changes\nin the regular PVP sense that could affect `parsley` itself (note `parsley` _only_ imports from `Parsley.Internal` itself); the second version is the\n_Internal API_ major version, which would only effect users who use part of the internal parsley\nmodules. As such, for people that are **not** explicitly importing anything from `Parsley.Internal.*`, the second major version does not matter: `0.2.0.0` and `0.3.0.0` would be compatible, for instance.\n\nTo use it, you'll need to write you parsers in another file from where they will be used: this is\ndue to Template Haskell.\n\n### How does Parsley being a _Staged Selective_ library change its use?\nBy being a _Selective_ Parser Combinator library, Parsley does not support monadic operations such\nas `(\u003e\u003e=)` or `return`. Instead, the most powerful operations are `select` or `branch`. Most monadic\npower can be recovered using the functionality provided by `Parsley.Register`, as well as the\nselectives.\n\nThe reason monads are not supported is because of the _Staging_: Parsley parsers are compiled ahead\nof time to produce fast code, but this means the entirety of the parser must be known before any\ninput is provided, ruling out dynamic monadic operations. The use of staging (in this instance provided\nby Typed Template Haskell) means that the signatures of the combinators do not correspond to their\ncounterparts in other libraries: they don't use raw values, they use code of values. A consequence\nof this is that Parsley does not implement instances of `Functor`, `Applicative`, `Alternative`,\nor indeed `Selective`; `do`-notation also cannot be used even with `ApplicativeDo`, except perhaps\nif `RebindableSyntax` is used.\n\nCode is provided to the combinators by way of the datatype `WQ` (or `Defunc` if you're feeling fancy),\nwhich pairs a normal value with its Haskell code representation:\n\n```hs\ndata WQ a\n\nmakeQ :: a -\u003e Code a -\u003e WQ a -- or Defunc a\n```\n\nThis gives us combinators like:\n\n```hs\npure :: WQ a -\u003e Parser a\nsatisfy :: WQ a -\u003e Parser a\n\nchar :: Char -\u003e Parser a\nchar c = satisfy (makeQ (== c) [||(== c)||])\n```\n\nUsing `WQ` explicitly like this can get annoying, which is what the `parsley-garnish` package is for!\nCurrently, the garnish provides one plugin called `OverloadedQuotes`, which replaces the behaviour of\nthe default _Untyped_ Template Haskell quotes in a file so that they produce one of `WQ` or `Defunc`.\nSee the `Parsley.OverloadedQuotesPlugin` module in the [`parsley-garnish`](https://hackage.haskell.org/package/parsley-garnish) package for more information.\n\n### How to avoid manual `WQ` on GHC 9.2\nCurrently, `parsley-garnish` is not ready for GHC 9.2. Instead of using `[|` and `|]` as the builder\nfor `Defunc` values, you can make use of the following `CPP` macro instead:\n\n```hs\n{-# LANGUAGE CPP #-}\n\n#define QQ(x) (makeQ (x) [||(x)||])\n\nchar :: Char -\u003e Parser a\nchar c = satisfy QQ(== c)\n```\n\nThis may require the use of the `cpphs` buildtool.\n\n## How does it work?\nIn short, Parsley represents all parsers as Abstract Syntax Trees (ASTs). The representation of the\nparsers the users write is called the Combinator Tree, which is analysed and optimised by Parsley.\nThis representation is then transformed into an Abstract Machine in CPS form, this is analysed further\nbefore being partially evaluated at compile-time to generate high quality Haskell code. For the long\nversion, I'd recommend checking out the paper!\n\n## Bug Reports\nIf you encounter a bug when using Parsley, try and minimise the example of the parser (and the input)\nthat triggers the bug. If possible, make a self contained example: this will help me to identify the\nissue without too much issue. It might be helpful to import `parsley-core:Parsley.Internal.Verbose` to provide a\ndebug dump that I can check out.\n\n## References\n* This work spawned a paper at ICFP 2020: [**Staged Selective Parser Combinators**](https://dl.acm.org/doi/10.1145/3409002)\n* Supports patterns and combinators from Haskell Symposium 2021: [**Design Patterns of Parser Combinators**](https://dl.acm.org/doi/10.1145/3471874.3472984)\n\n### Talks\nFor talks on how writing parsers changes when using Parsley see either of these:\n* [*Garnishing Parsec with Parsley*](https://www.youtube.com/watch?v=tJcyY9L2z84) - Berlin Functional Programming Group, January 2021\n* [*Exploring Parsley: Working with Staged Selective Parsers*](https://www.youtube.com/watch?v=Zhu-cPY1eac) - MuniHac 2020\n\nFor the technical overview of how Parsley works:\n* [*Staged Selective Parser Combinators*](https://www.youtube.com/watch?v=lH65PvRgm8M) - ICFP 2020\n\nFor information about how to write parsers cleanly:\n* [*Design Patterns for Parser Combinators*](https://www.youtube.com/watch?v=RwzX1XltOGY) - Haskell 2021\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj-mie6%2Fparsleyhaskell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fj-mie6%2Fparsleyhaskell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj-mie6%2Fparsleyhaskell/lists"}