{"id":20078773,"url":"https://github.com/nasso/comparse","last_synced_at":"2025-07-08T00:08:43.674Z","repository":{"id":49470588,"uuid":"432313305","full_name":"nasso/comparse","owner":"nasso","description":"A highly generic parser combinators library.","archived":false,"fork":false,"pushed_at":"2023-02-24T01:24:11.000Z","size":39,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-05T11:18:56.275Z","etag":null,"topics":["haskell","parser","parser-combinators"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/comparse","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/nasso.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"publiccode":null,"codemeta":null}},"created_at":"2021-11-26T22:15:47.000Z","updated_at":"2024-09-10T21:14:35.000Z","dependencies_parsed_at":"2024-11-13T15:26:38.974Z","dependency_job_id":null,"html_url":"https://github.com/nasso/comparse","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasso%2Fcomparse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasso%2Fcomparse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasso%2Fcomparse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasso%2Fcomparse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nasso","download_url":"https://codeload.github.com/nasso/comparse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasso%2Fcomparse/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258814446,"owners_count":22762063,"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":["haskell","parser","parser-combinators"],"created_at":"2024-11-13T15:16:33.584Z","updated_at":"2025-06-24T06:01:59.058Z","avatar_url":"https://github.com/nasso.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# comparse\n\n[![Tests](https://github.com/nasso/comparse/actions/workflows/tests.yml/badge.svg)](https://github.com/nasso/comparse/actions/workflows/tests.yml)\n[![Hackage](https://img.shields.io/hackage/v/comparse)](https://hackage.haskell.org/package/comparse)\n\n`comparse` is a parser combinator library supporting arbitrary input types.\nCombinators do not care about the exact type of the input stream, allowing you\nto use them on your own data source, as long as it supports a specific set of\noperations. The `ParserT` monad transformer can wrap around another monad,\nallowing you to easily implement features such as tracing, context-sensitive\nparsing, state machines, and so on. `comparse` does its best to provide\nmeaningful error messages without sacrificing performances or the developer\nexperience when writing parsers.\n\n## How?\n\nThe main difference between `comparse` and other equivalent libraries is that\nthe parsers you write are generic over the exact type of the input stream. That\nmeans you can write parsers that work with both `String`, `Text` or any other\nsource of `Char`s with no modification. The combinators in `comparse` also work\nwith anything that's an instance of `Stream`, even if it's not a `Stream` of\n`Char`s (e.g. a `TokenStream`!).\n\n## Example\n\nThe following example shows how to use the `comparse` library to parse a\nsimplified subset of the [JSON](https://en.wikipedia.org/wiki/JSON) data format:\n\n```hs\n-- TypeFamilies is required by the `CharParser` constraint\n{-# LANGUAGE TypeFamilies #-}\n\nimport Control.Monad (void)\nimport Control.Monad.Parser\nimport Data.Char (isAlpha, isDigit)\nimport Data.Text (Text)\nimport qualified Data.Text as T\n\ndata JValue\n  = JString String\n  | JNumber Int\n  | JBool Bool\n  | JNull\n  | JObject [(String, JValue)]\n  | JArray [JValue]\n  deriving (Show)\n\nmain :: IO ()\nmain = do\n  input \u003c- getContents\n  putStrLn \"Parsing as String:\"\n  print (parseString input)\n  putStrLn \"Parsing as Text:\"\n  print (parseText $ T.pack input)\n\nparseString :: String -\u003e Maybe JValue\nparseString s =\n  case runStringParser (json \u003c* eof) s of\n    Parsed v _ _ -\u003e Just v\n    _ -\u003e Nothing\n\nparseText :: Text -\u003e Maybe JValue\nparseText t =\n  case runTextParser (json \u003c* eof) t of\n    Parsed v _ _ -\u003e Just v\n    _ -\u003e Nothing\n\nlexeme :: CharParser p =\u003e p a -\u003e p a\nlexeme p = spaces *\u003e p \u003c* spaces\n  where\n    spaces = void $ many $ oneOf \" \\n\\r\\t\"\n\nsymbol :: CharParser p =\u003e String -\u003e p String\nsymbol = lexeme . string\n\njson :: CharParser p =\u003e p JValue\njson =\n  JString \u003c$\u003e stringLiteral\n    \u003c|\u003e JNumber \u003c$\u003e number\n    \u003c|\u003e JBool \u003c$\u003e bool\n    \u003c|\u003e JNull \u003c$ symbol \"null\"\n    \u003c|\u003e JObject \u003c$\u003e object\n    \u003c|\u003e JArray \u003c$\u003e array\n\nstringLiteral :: CharParser p =\u003e p String\nstringLiteral = lexeme $ like '\"' *\u003e many (unlike '\\\"') \u003c* like '\"'\n\nnumber :: CharParser p =\u003e p Int\nnumber =\n  lexeme\n    ( read \u003c$\u003e ((:) \u003c$\u003e like '-' \u003c*\u003e many1 digit)\n        \u003c|\u003e read \u003c$\u003e (optional (like '+') *\u003e many1 digit)\n    )\n    \u003c* notFollowedBy (match isAlpha)\n  where\n    digit = match isDigit\n\nbool :: CharParser p =\u003e p Bool\nbool = True \u003c$ symbol \"true\" \u003c|\u003e False \u003c$ symbol \"false\"\n\nobject :: CharParser p =\u003e p [(String, JValue)]\nobject =\n  symbol \"{\"\n    *\u003e sepBy ((,) \u003c$\u003e (stringLiteral \u003c* symbol \":\") \u003c*\u003e json) (symbol \",\")\n    \u003c* symbol \"}\"\n\narray :: CharParser p =\u003e p [JValue]\narray = symbol \"[\" *\u003e sepBy json (symbol \",\") \u003c* symbol \"]\"\n```\n\nThe `CharParser p` constraint lets us easily write parsers specialised to\ncharacter input streams. It's actually defined as a `type` alias:\n\n```hs\ntype ParserOf i p = (MonadParser p, Item (Input p) ~ i)\n\ntype CharParser p = ParserOf Char p\n```\n\nThis design makes it very easy to write reusable parsers and combinators.\n\nFor more examples, please refer to the [tests](test/Parsing.hs).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasso%2Fcomparse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnasso%2Fcomparse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasso%2Fcomparse/lists"}