{"id":13414873,"url":"https://github.com/ziman/lightyear","last_synced_at":"2026-01-07T00:23:00.027Z","repository":{"id":63679542,"uuid":"13540219","full_name":"ziman/lightyear","owner":"ziman","description":"Parser combinators for Idris","archived":false,"fork":false,"pushed_at":"2019-04-11T05:47:44.000Z","size":137,"stargazers_count":240,"open_issues_count":10,"forks_count":43,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-02-01T09:14:13.308Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Idris","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ziman.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}},"created_at":"2013-10-13T14:07:14.000Z","updated_at":"2025-01-27T20:10:28.000Z","dependencies_parsed_at":"2022-11-23T19:26:19.829Z","dependency_job_id":null,"html_url":"https://github.com/ziman/lightyear","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziman%2Flightyear","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziman%2Flightyear/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziman%2Flightyear/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziman%2Flightyear/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ziman","download_url":"https://codeload.github.com/ziman/lightyear/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245779435,"owners_count":20670684,"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":[],"created_at":"2024-07-30T21:00:39.038Z","updated_at":"2026-01-07T00:22:59.999Z","avatar_url":"https://github.com/ziman.png","language":"Idris","funding_links":[],"categories":["Parser Combinators","Idris"],"sub_categories":[],"readme":"# Lightyear\n\nLightweight parser combinator library for Idris,\ninspired by [Parsec](http://hackage.haskell.org/package/parsec).\n\n[![Build Status](https://travis-ci.org/ziman/lightyear.svg?branch=master)](https://travis-ci.org/ziman/lightyear)\n\nModule overview:\n* `Lightyear.Core`: central definitions + instances\n* `Lightyear.Errmsg`: error message formatting, mainly internal library\n* `Lightyear.Combinators`: generic combinators like `many` or `sepBy`\n* `Lightyear.Char`: char-bound parsers like `char` or `space`\n* `Lightyear.Strings`: string-bound parsers like `strings` or `lexeme`\n\n## Synopsis\n\nThis package is used (almost) the same way as Parsec, except for one difference: backtracking.\n\n### Commitment\n* Parsec combinators\n  won't backtrack if a branch of `\u003c|\u003e` has consumed any input, hence Parsec\n  parsers require an explicit `try`.\n\n* Lightyear parsers are backtrack-by-default and there is\n  the `commitTo` combinator that makes the parser commit to that branch.\n\nIn other words, the following two pieces of code are equivalent (using illustrative combinator names):\n\nParsec:\n```haskell\nelem :: Parser Int\nelem = (try (string \"0x\") \u003e\u003e hexNumber) \u003c|\u003e decNumber\n```\n\nLightyear:\n```haskell\nelem : Parser Int\nelem = (string \"0x\" $\u003e commitTo hexNumber) \u003c|\u003e decNumber\n-- which may be abbreviated as:\n--   = (string \"0x\" \u003e! hexNumber) \u003c|\u003e decNumber\n```\n\nAfter reading the prefix `0x`, both parsers commit to reading a hexadecimal number\nor nothing at all — Parsec does this automatically, Lightyear uses the `commitTo` combinator\nfor this purpose.\nOn the other hand, Parsec requires the `string \"0x\"` to be wrapped in `try` because\nif we are reading `0123`, we definitely don't want to commit to the left branch\nupon seeing the leading `0`.\n\nFor convenience, `commitTo` is merged in monadic and applicative operators,\nyielding the operators `\u003e!=`, `\u003e!`, `\u003c$!\u003e`, `\u003c$!`, and `$!\u003e`.\nThe `!` in the names is inspired by the notation used for cuts in Prolog.\n\nA parser that uses commitment might look like this (notice the leading\n`char '@'` that leads to commitment):\n```haskell\nentry : Parser Entry\nentry = char '@' \u003e! do\n  typ \u003c- pack \u003c@\u003e some (satisfy (/= '{'))\n  token \"{\"\n  ident \u003c- pack \u003c@\u003e some (satisfy (/= ','))\n  token \",\"\n  items \u003c- item `sepBy` comma\n  token \"}\"\n  return $ En typ ident items\n```\n\n### Lazy Branching with `\u003c|\u003e|`\n\nIt is worth noting that Idris itself is a _strict_ language, and thus the `\u003c|\u003e`\noperator will evaluate both its arguments eagerly by default. In order to lazily\nevaluate different parsing branches we are required to use a special operator:\n`\u003c|\u003e|`. In general, all recursive calls of combinators have to occur in a lazy context.\n(With mutual recursion, this generalises to the rule that each call cycle\nhas to be broken by laziness in at least one place.)\n\nIn the wild, it might look like this:\n\n```idris\npartial parseExpr : Parser SExpr\nparseExpr = parseName \u003c|\u003e| ( MkSExpr \u003c$\u003e parens (many parseExpr) )\n```\n\nIn the above example, the whole RHS of `\u003c|\u003e|` is lazy, and so the recursive\noccurrence of `parseExpr` in it will be evaluated only if the LHS of `\u003c|\u003e|` fails.\nUsing `\u003c|\u003e` would cause infinite recursion.\n\nFor convenience, a version of `\u003c*\u003e` that lazily evaluates its second argument is\nincluded as `\u003c*\u003e|`. Conversely to `\u003c|\u003e|`, the RHS of `\u003c*\u003e|` will be evaluated\nonly if the LHS of `\u003c*\u003e|` _succeeds_.\n\n### Example\n\nLightyear is used to parse BibTeX in \u003ca href=\"https://github.com/ziman/bibdris/blob/master/Bibtex.idr\"\u003ebibdris\u003c/a\u003e.\n\n## Build\n```bash\n$ make clean\n$ make test\n$ make install\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziman%2Flightyear","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fziman%2Flightyear","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziman%2Flightyear/lists"}