{"id":13631408,"url":"https://github.com/inhabitedtype/angstrom","last_synced_at":"2025-05-16T13:04:36.417Z","repository":{"id":43095173,"uuid":"47039984","full_name":"inhabitedtype/angstrom","owner":"inhabitedtype","description":"Parser combinators built for speed and memory efficiency","archived":false,"fork":false,"pushed_at":"2024-09-12T21:27:32.000Z","size":632,"stargazers_count":671,"open_issues_count":14,"forks_count":75,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-04-06T23:15:13.429Z","etag":null,"topics":["ocaml","parser-combinators","parsing"],"latest_commit_sha":null,"homepage":"","language":"OCaml","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/inhabitedtype.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,"publiccode":null,"codemeta":null}},"created_at":"2015-11-28T21:23:11.000Z","updated_at":"2025-03-28T01:06:38.000Z","dependencies_parsed_at":"2024-09-13T09:01:55.900Z","dependency_job_id":null,"html_url":"https://github.com/inhabitedtype/angstrom","commit_stats":{"total_commits":296,"total_committers":31,"mean_commits":9.548387096774194,"dds":0.5878378378378378,"last_synced_commit":"aff4665d207d85087e57420ce698fb9f0c8746b3"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhabitedtype%2Fangstrom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhabitedtype%2Fangstrom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhabitedtype%2Fangstrom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhabitedtype%2Fangstrom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inhabitedtype","download_url":"https://codeload.github.com/inhabitedtype/angstrom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535826,"owners_count":22087398,"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":["ocaml","parser-combinators","parsing"],"created_at":"2024-08-01T22:02:24.276Z","updated_at":"2025-05-16T13:04:36.374Z","avatar_url":"https://github.com/inhabitedtype.png","language":"OCaml","funding_links":[],"categories":["Ocaml","OCaml","Compilers and Compiler Tools"],"sub_categories":[],"readme":"# Angstrom\n\nAngstrom is a parser-combinator library that makes it easy to write efficient,\nexpressive, and reusable parsers suitable for high-performance applications. It\nexposes monadic and applicative interfaces for composition, and supports\nincremental input through buffered and unbuffered interfaces. Both interfaces\ngive the user total control over the blocking behavior of their application,\nwith the unbuffered interface enabling zero-copy IO. Parsers are backtracking\nby default and support unbounded lookahead.\n\n[![Build Status](https://github.com/inhabitedtype/angstrom/workflows/build/badge.svg)](https://github.com/inhabitedtype/angstrom/actions?query=workflow%3A%22build%22)\n\n\n## Installation\n\nInstall the library and its dependencies via [OPAM][opam]:\n\n[opam]: http://opam.ocaml.org/\n\n```bash\nopam install angstrom\n```\n\n## Usage\n\nAngstrom is written with network protocols and serialization formats in mind.\nAs such, its source distribution includes implementations of various RFCs that\nare illustrative of real-world applications of the library. These include an\n[HTTP parser][http] and a [JSON parser][json].\n\n[http]: https://github.com/inhabitedtype/angstrom/blob/master/examples/rFC2616.ml\n[json]: https://github.com/inhabitedtype/angstrom/blob/master/examples/rFC7159.ml\n\nIn addition, it is an informal tradition for OCaml parser-combinator libraries\nto include in their READMEs a parser for a simple arithmetic expression\nlanguage. The code below implements a parser for such a language and computes\nthe numerical result of the expression as it is being parsed. Because Angstrom\nis written with network protocols and serialization libraries in mind, it does\nnot include combinators for creating infix expression parsers. Such\ncombinators, e.g., `chainl1`, are nevertheless simple to define.\n\n```ocaml\nopen Angstrom\n\nlet parens p = char '(' *\u003e p \u003c* char ')'\nlet add = char '+' *\u003e return (+)\nlet sub = char '-' *\u003e return (-)\nlet mul = char '*' *\u003e return ( * )\nlet div = char '/' *\u003e return (/)\nlet integer =\n  take_while1 (function '0' .. '9' -\u003e true | _ -\u003e false) \u003e\u003e| int_of_string\n\nlet chainl1 e op =\n  let rec go acc =\n    (lift2 (fun f x -\u003e f acc x) op e \u003e\u003e= go) \u003c|\u003e return acc in\n  e \u003e\u003e= fun init -\u003e go init\n\nlet expr : int t =\n  fix (fun expr -\u003e\n    let factor = parens expr \u003c|\u003e integer in\n    let term   = chainl1 factor (mul \u003c|\u003e div) in\n    chainl1 term (add \u003c|\u003e sub))\n\nlet eval (str:string) : int =\n  match parse_string ~consume:All expr str with\n  | Ok v      -\u003e v\n  | Error msg -\u003e failwith msg\n```\n\nFor an explanation of the infix operators and other combinators used in the\nimplementation of this example, see the documentation in the [`mli`][mli].\n\n[mli]: https://github.com/inhabitedtype/angstrom/blob/master/lib/angstrom.mli\n\n\n## Comparison to Other Libraries\n\nThere are several other parser-combinator libraries available for OCaml that\nmay suit your needs, and are worth considering. Most of them are derivatives of\nor inspired by [Parsec][]. As such, they require the use of a `try` combinator\nto achieve backtracking, rather than providing it by default. They also all use\nsomething akin to a lazy character stream as the underlying input abstraction.\nWhile this suits Haskell quite nicely, it requires blocking read calls when the\nentire input is not immediately available\u0026mdash;an approach that is inherently\nincompatible with monadic concurrency libraries such as [Async] and [Lwt], and\nwriting high-performance, concurrent applications in general. Another\nconsequence of this approach to modeling and retrieving input is that the\nparsers cannot iterate over sections of input in a tight loop, which adversely\naffects performance.\n\nBelow is a table that compares the features of Angstrom against the those of\nother parser-combinator libraries.\n\n[parsec]: https://hackage.haskell.org/package/parsec\n[async]: https://github.com/janestreet/async\n[lwt]: https://ocsigen.org/lwt/\n\n\nFeature \\ Library                   | Angstrom | [mparser] | [planck] | [opal] |\n------------------------------------|:--------:|:---------:|:--------:|:------:|\nMonadic interface                   | ✅        | ✅         | ✅        | ✅      |\nBacktracking by default             | ✅        | ❌         | ❌        | ❌      |\nUnbounded lookahead                 | ✅        | ✅         | ✅        | ❌      |\nReports line numbers in errors      | ❌        | ✅         | ❌        | ❌      |\nEfficient `take_while`/`skip_while` | ✅        | ❌         | ❌        | ❌      |\nUnbuffered (zero-copy) interface    | ✅        | ❌         | ❌        | ❌      |\nNon-blocking incremental interface  | ✅        | ❌         | ❌        | ❌      |\nAsync Support                       | ✅        | ❌         | ❌        | ❌      |\nLwt Support                         | ✅        | ❌         | ❌        | ❌      |\n\n[mparser]: https://github.com/cakeplus/mparser\n[opal]: https://github.com/pyrocat101/opal\n[planck]: https://bitbucket.org/camlspotter/planck\n\n\n## Development\n\nTo install development dependencies, pin the package from the root of the\nrepository:\n\n```bash\nopam pin add -n angstrom .\nopam install --deps-only angstrom\n```\n\nAfter this, you may install a development version of the library using the\ninstall command as usual.\n\nFor building and running the tests during development, you will need to install\nthe `alcotest` package:\n\n```bash\nopam install alcotest\nmake test\n```\n\n## Acknowledgements\n\nThis library started off as a direct port of the inimitable [attoparsec][]\nlibrary. While the original approach of continuation-passing still survives in\nthe source code, several modifications have been made in order to adapt the\nideas to OCaml, and in the process allow for more efficient memory usage and\nintegration with monadic concurrency libraries. This library will undoubtedly\ndiverge further as time goes on, but its name will stand as an homage to its\norigin.\n\n[attoparsec]: https://github.com/bos/attoparsec\n\n\n## License\n\nBSD3, see LICENSE file for its text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finhabitedtype%2Fangstrom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finhabitedtype%2Fangstrom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finhabitedtype%2Fangstrom/lists"}