{"id":17442575,"url":"https://github.com/jez/ragel-bison-parser-sandbox","last_synced_at":"2025-12-12T13:30:12.949Z","repository":{"id":73798517,"uuid":"260838017","full_name":"jez/ragel-bison-parser-sandbox","owner":"jez","description":"A small parser for the lambda calculus in C++ using Bazel, Ragel, and Bison","archived":false,"fork":false,"pushed_at":"2020-05-17T00:13:48.000Z","size":50,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-08T18:18:53.054Z","etag":null,"topics":["bison-parser","lambda-calculus","programming-languages","ragel"],"latest_commit_sha":null,"homepage":"","language":"C++","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/jez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2020-05-03T05:55:12.000Z","updated_at":"2022-11-13T02:48:19.000Z","dependencies_parsed_at":"2023-03-25T11:18:02.178Z","dependency_job_id":null,"html_url":"https://github.com/jez/ragel-bison-parser-sandbox","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/jez%2Fragel-bison-parser-sandbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jez%2Fragel-bison-parser-sandbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jez%2Fragel-bison-parser-sandbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jez%2Fragel-bison-parser-sandbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jez","download_url":"https://codeload.github.com/jez/ragel-bison-parser-sandbox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239679581,"owners_count":19679500,"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":["bison-parser","lambda-calculus","programming-languages","ragel"],"created_at":"2024-10-17T16:18:01.009Z","updated_at":"2025-12-12T13:30:12.893Z","avatar_url":"https://github.com/jez.png","language":"C++","readme":"# ragel-bison-parser-sandbox\n\nA small sandbox to play around with some C++ parsing libraries and learn. It\nparses lambda calculus expressions to an AST and prints it.\n\nVery much inspired by the build toolchain that [Sorbet] uses.\n\n```bash\n./bazel run //main:sandbox -- $'let f = \\\\x -\u003e x in f f'\n# input:  let x = \\x -\u003e x in x x\n# output: Let { bind = x, what = Lam { param = x, body = Var { var = x } }, inWhere = App { f = Var { var = x }, arg = Var { var = x } } }\n\n# if you want to generate a compile_commands.json file:\ntools/scripts/build_compilation_db.sh\n```\n\nSome things I cared about\n\n- I wrote a lot of comments\n  - This was a learning exercise. I don't really intend to pursue this project\n    further (I find it way more fun to hack on existing projects than to\n    duplicate existing efforts into my own greenfield projects). But still, I\n    had never worked with the lexer+parser much in Sorbet, so if I had needed to\n    build a project from scratch, I knew this part would have taken me some\n    getting used to. So the comments are there to remind me how the whole thing\n    works.\n- Bazel for the build tool\n  - It's what Sorbet uses\n  - I'm mostly convinced all build tools are terrible; Bazel just happens to be\n    the one that I know the most, and the one for which I know how to set up to\n    work with libraries and my editor.\n- Ragel for lexing, Bison for parsing\n  - They're what Sorbet uses, but I wanted something simpler.\n  - Both the generated Ragel lexer and Bison parser are fully self-contained C++\n    classes (no global variables tracking state).\n- `std::unique_ptr` for the Bison parse result\n  - I couldn't find any examples online of a simple Bison parser that used\n    `unique_ptr`, so I wasn't sure if it would work or not (e.g., it might have\n    been the case that it copy constructed something under the hood, but that's\n    not the case; looks like you can use Bison with unique_ptr just fine).\n- The Ragel lexer iterates over a `string_view::const_iterator` instead of a\n  `char *`.\n  - This is actually pretty cool; Ragel doesn't even know that it's not\n    operating on a `char *`. The generated Ragel lexer just manipulates whatever\n    variables called `p`/`pe`/`ts`/`te` are in scope, and as long as they\n    support the operations that it needs them to, it just compiles. Turns out\n    that the `string_view::const_iterator` interface supports everything Ragel\n    needs it to.\n- Move semantics for strings allocated by the lexer.\n  - I'm told that one of the big inefficiencies in Sorbet's parser is that it\n    does a lot of string copying. I made the `sandbox::parser::Node`\n    constructors always take `std::string\u0026\u0026`'s to require that they're `move`'d\n    when constructing an AST node, instead of copied.\n- There are a lot of TODO's\n  - I tried to write TODOs for most of the things I like about Sorbet that I'd\n    want to cargo cult if I ever used this as a starting point for something\n    bigger.\n\nAnyways, if you read this far, you might also want to look at some other things\nI work on:\n\n- [Sorbet]\n  - The internals are documented and the codebase is using pretty modern C++.\n    It's also relatively small compared to it's peer projects.\n- [rust-lc-interp]\n  - I used a similar project (lambda calculus interpretter) to learn about Rust.\n    That one not only parses but also interprets the output.\n- [stlc-infer]\n  - At one point, I worked through an exercise from TAPL to write (naive) type\n    inference for the simply-typed lambda calculus. It lexes, parses, type\n    checks/infers, and interprets. It's written in Haskell.\n\nThe Rust project and the Haskell project use basically the same surface syntax,\nso you can get a more or less equal comparison of Ragel/Bison, Alex/Happy, and\nlalrpop.\n\n## TODO(jez)\n\n- core::GlobalState / core::Context threaded through whole program.\n  - error reporting\n\n[Sorbet]: https://github.com/sorbet/sorbet\n[rust-lc-interp]: https://github.com/jez/rust-lc-interp\n[stlc-infer]: https://github.com/jez/stlc-infer\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjez%2Fragel-bison-parser-sandbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjez%2Fragel-bison-parser-sandbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjez%2Fragel-bison-parser-sandbox/lists"}