{"id":20177810,"url":"https://github.com/tfc/attoparsecpp","last_synced_at":"2025-10-12T12:33:54.440Z","repository":{"id":43039250,"uuid":"121984951","full_name":"tfc/attoparsecpp","owner":"tfc","description":"Trying to imitate the elegance of Haskell parsers","archived":false,"fork":false,"pushed_at":"2024-09-30T15:32:05.000Z","size":112,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T04:38:53.617Z","etag":null,"topics":["cpp","haskell","library","parsec","parsing"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tfc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-02-18T19:51:09.000Z","updated_at":"2024-09-30T15:32:09.000Z","dependencies_parsed_at":"2025-04-10T04:33:12.854Z","dependency_job_id":"5d7d196c-0634-4704-98b6-6528c87231ef","html_url":"https://github.com/tfc/attoparsecpp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tfc/attoparsecpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fattoparsecpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fattoparsecpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fattoparsecpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fattoparsecpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tfc","download_url":"https://codeload.github.com/tfc/attoparsecpp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fattoparsecpp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266076383,"owners_count":23872750,"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":["cpp","haskell","library","parsec","parsing"],"created_at":"2024-11-14T02:17:31.416Z","updated_at":"2025-10-12T12:33:54.376Z","avatar_url":"https://github.com/tfc.png","language":"C++","readme":"# AttoParsec++\n\nThis repository contains a little experimental C++ library for parsing strings.\n\n## Context\n\nI am still totally amazed by the simplicity and power of [Haskell](https://www.haskell.org/) parser libraries like [`parsec`](https://hackage.haskell.org/package/parsec).\nThere are also libraries like [`attoparsec`](https://hackage.haskell.org/package/attoparsec) and [`megaparsec`](https://hackage.haskell.org/package/megaparsec).\nThese are all pretty similar in how to use them, but tuned for different use cases.\n\nThe general idea for such parsers originates from [this paper](http://www.cs.nott.ac.uk/~pszgmh/pearl.pdf).\n\nThere have been [attempts](http://yapb-soc.blogspot.de/2012/11/monadic-parsing-in-c.html) to implement this in C++.\nThis repository is my attempt to provide a useful and simple library for composing string based parsers that does not scare non-Haskell programmers away immediately.\n\n## Usage\n\nJust include `parser.hpp` from the `include/` folder in your C++ file.\nThis is a header-only library (but does not inherently have to be).\n\nYou can find a lot of examples in the `test/` and `benchmark/` folders.\n\nThere is also the mathematical expression parser example in `include/math_expression.hpp` which implements the very short and elegant `expr` parser from the [original Haskell monadic parsing paper](http://www.cs.nott.ac.uk/~pszgmh/pearl.pdf).\nUnit tests for this parser are in `test/math_expression.cpp`.\n\n## Example\n\nThe *Mathematical Expression* grammar from the pearl paper that can parse and evaluate the result of expressions like `1 + (3 + 4 * 3) / 2` looks like the following:\n\n``` haskell\nexpr = term   `chainl1` add_op\nterm = factor `chainl1` mul_op\nfactor = integer \u003c|\u003e (char '(' *\u003e expr \u003c* char ')')\n\nadd_op = (char '+' *\u003e pure (+)) \u003c|\u003e (char '-' *\u003e pure (-))\nmul_op = (char '*' *\u003e pure (*)) \u003c|\u003e (char '/' *\u003e pure (/))\n```\n\nWith this library, it is possible to get close to it like this:\n\n``` c++\nstatic parser\u003cint\u003e expr(  str_pos p);\nstatic parser\u003cint\u003e term(  str_pos p);\nstatic parser\u003cint\u003e factor(str_pos p);\n\nstatic parser\u003cint\u003e expr(str_pos p) {\n    return chainl1(token(term), token(add_op))(p);\n};\n\nstatic parser\u003cint\u003e term(str_pos p) {\n    return chainl1(token(factor), token(mul_op))(p);\n};\n\nstatic parser\u003cint\u003e factor(str_pos p) {\n    return choice(integer, clasped(oneOf('('), oneOf(')'), expr))(p);\n}\n```\n\nIn order to write a little calculator tool from it, the only code left to be implemented is:\n\n``` c++\nstd::optional\u003cint\u003e evalutate_math_expression(std::string input) {\n    return parse_result(expr, input);\n}\n\n// evaluate_math_expression(\"1 + 2 * (3 + 2)\")\n// ==\u003e returns    std::optional\u003cint\u003e{ 11 }\n```\n\n`run_parser` returns a tuple that contains the result of successful parsing in the first field and the rest of the not consumed part of the string in the second field.\nThe whole tuple is wrapped into an `std::optional` which enables the parser lib to indicate failure.\n\n## Building tests and benchmarks\n\nYou need to install the following libraries:\n\n- [googletest](https://github.com/google/googletest)\n- [google benchmark](https://github.com/google/benchmark)\n\n\u003e In order to install them automatically, you can just run `nix develop` in the project directory.\n\u003e It will install all dependencies and put them in place.\n\u003e\n\u003e `nix develop` is part of the [Nix package manager](https://nixos.org/nix/) for Unix/Linux/Mac.\n\n### Build and Test\n\n``` bash\ncmake -B build -S .\ncd build\ncmake --build .\nctest\n```\n\n### Benchmrks\n\nAfter building, run:\n\n``` bash\n./benchmark/attoparsecpp-benchmark\n```\n\n## Performance\n\nBenchmark output on a Macbook Pro late 2013\n\n- 22 nm \"Haswell/Crystalwell\" 2.6 GHz Intel \"Core i7\" processor (4960HQ)\n- 256 KB L2, 6 MB L3 Cache\n- 16 GB 1600 MHz DDR3L SDRAM\n\n``` bash\n$ make \u0026\u0026 ./main\nclang++ -O2 -std=c++14 -lbenchmark -I../include main.cpp -o main\nRun on (8 X 2300 MHz CPU s)\n2018-02-27 13:53:18\n-----------------------------------------------------------------------\nBenchmark                                Time           CPU Iterations\n-----------------------------------------------------------------------\nmeasure_word_parsing/10                 60 ns         59 ns   11958044\nmeasure_word_parsing/100              1122 ns       1117 ns     615309\nmeasure_word_parsing/1000             5624 ns       5614 ns     122420\nmeasure_word_parsing/10000           46167 ns      46050 ns      15128\nmeasure_word_parsing/100000         447579 ns     446684 ns       1523\nmeasure_word_parsing/1000000       4793773 ns    4770685 ns        149\nmeasure_word_parsing/10000000     51993664 ns   51924583 ns         12\nmeasure_word_parsing_BigO             5.20 N       5.19 N\nmeasure_word_parsing_RMS                 2 %          2 %\nmeasure_vector_filling/10              424 ns        422 ns    1642071\nmeasure_vector_filling/100            2291 ns       2280 ns     301999\nmeasure_vector_filling/1000          20898 ns      20852 ns      34442\nmeasure_vector_filling/10000        208505 ns     207562 ns       3555\nmeasure_vector_filling/100000      2054322 ns    2040226 ns        337\nmeasure_vector_filling/1000000    21730601 ns   21642455 ns         33\nmeasure_vector_filling/10000000  223637116 ns  223132000 ns          3\nmeasure_vector_filling_BigO          22.36 N      22.31 N\nmeasure_vector_filling_RMS               1 %          1 %\ncsv_vector_of_ints/10                  414 ns        412 ns    1693202\ncsv_vector_of_ints/100                2194 ns       2185 ns     320976\ncsv_vector_of_ints/1000              18223 ns      18196 ns      38116\ncsv_vector_of_ints/10000            181302 ns     181041 ns       3820\ncsv_vector_of_ints/100000          1867089 ns    1862028 ns        363\ncsv_vector_of_ints/1000000        18843539 ns   18808769 ns         39\ncsv_vector_of_ints/10000000      200541779 ns  200397750 ns          4\ncsv_vector_of_ints_BigO              20.04 N      20.03 N\ncsv_vector_of_ints_RMS                   1 %          1 %\nsum_of_ints/10                         313 ns        312 ns    2183304\nsum_of_ints/100                       3068 ns       3064 ns     220643\nsum_of_ints/1000                     30839 ns      30772 ns      22453\nsum_of_ints/10000                   310284 ns     310001 ns       2243\nsum_of_ints/100000                 3130188 ns    3124631 ns        225\nsum_of_ints/1000000               30558996 ns   30527304 ns         23\nsum_of_ints/10000000             309699901 ns  309107000 ns          2\nproduct_of_ints/10                     195 ns        195 ns    3498286\nproduct_of_ints/100                   1814 ns       1812 ns     397680\nproduct_of_ints/1000                 17817 ns      17805 ns      38756\nproduct_of_ints/10000               176918 ns     176772 ns       3829\nproduct_of_ints/100000             1762898 ns    1761650 ns        369\nproduct_of_ints/1000000           17843418 ns   17833368 ns         38\nproduct_of_ints/10000000         176399736 ns  176310500 ns          4\nproduct_of_ints_BigO                 17.64 N      17.63 N\nproduct_of_ints_RMS                      0 %          0 %\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfc%2Fattoparsecpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftfc%2Fattoparsecpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfc%2Fattoparsecpp/lists"}