{"id":13566286,"url":"https://github.com/jsinger67/parol","last_synced_at":"2026-04-05T11:32:09.470Z","repository":{"id":39140208,"uuid":"407928423","full_name":"jsinger67/parol","owner":"jsinger67","description":"LL(k) and LALR(1) parser generator for Rust and C#","archived":false,"fork":false,"pushed_at":"2026-03-31T04:46:42.000Z","size":12895,"stargazers_count":234,"open_issues_count":0,"forks_count":19,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-03-31T07:11:17.114Z","etag":null,"topics":["grammar","parser","rust"],"latest_commit_sha":null,"homepage":"https://jsinger67.github.io/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsinger67.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-18T17:45:31.000Z","updated_at":"2026-03-31T04:45:29.000Z","dependencies_parsed_at":"2023-09-24T15:42:36.531Z","dependency_job_id":"1f79ab80-9bb0-4fdd-b2c2-6b1f39d58238","html_url":"https://github.com/jsinger67/parol","commit_stats":{"total_commits":847,"total_committers":8,"mean_commits":105.875,"dds":0.08854781582054305,"last_synced_commit":"0128752f892cb871a7d2a24f587d7d15f668267d"},"previous_names":[],"tags_count":162,"template":false,"template_full_name":null,"purl":"pkg:github/jsinger67/parol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fparol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fparol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fparol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fparol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsinger67","download_url":"https://codeload.github.com/jsinger67/parol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fparol/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31434624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["grammar","parser","rust"],"created_at":"2024-08-01T13:02:06.107Z","updated_at":"2026-04-05T11:32:09.458Z","avatar_url":"https://github.com/jsinger67.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable first-line-h1 --\u003e\n\n[![Rust](https://github.com/jsinger67/parol/actions/workflows/rust.yml/badge.svg)](https://github.com/jsinger67/parol/actions/workflows/rust.yml)\n[![Docs.rs](https://docs.rs/parol/badge.svg)](https://docs.rs/parol)\n[![Crates.io](https://img.shields.io/crates/v/parol.svg)](https://crates.io/crates/parol)\n\n\u003c!-- markdownlint-enable first-line-h1 --\u003e\n\n# About `parol`\n\n\u003c!-- markdownlint-disable Inline HTML --\u003e\n\u003cbr\u003e\n\u003cimg src=\"https://github.com/jsinger67/parol/raw/main/crates/parol/logo/Parol.svg\" alt=\"Logo\" height=300 with=300\u003e\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\u003c!-- markdownlint-enable Inline HTML --\u003e\n\n## ATTENTION - The main branch is subject to constant changes, so the experience can be bumpy\n\nTherefore, please use an officially released version from\n[crates.io](https://crates.io/crates/parol) or refer to one of the latest\n[tags](https://github.com/jsinger67/parol/tags) applied to main branch.\n\n---\n\nThis workspace contains four essential crates that are all separately released on crates.io.\n\n- [parol](https://crates.io/crates/parol)\n- [parol_runtime](https://crates.io/crates/parol_runtime)\n- [parol-macros](https://crates.io/crates/parol-macros)\n- [parol-ls](https://crates.io/crates/parol-ls)\n\nNew changes can be viewed in the change logs of the respective projects.\n\n- [CHANGELOG parol](./crates/parol/CHANGELOG.md)\n- [CHANGELOG parol_runtime](./crates/parol_runtime/CHANGELOG.md)\n- [CHANGELOG parol-macros](./crates/parol-macros/CHANGELOG.md)\n- [CHANGELOG parol-ls](./crates/parol-ls/CHANGELOG.md)\n\nIt also contains the vs-code extension `parol-vscode` which is released on VS Code marketplace\n[parol-vscode](https://marketplace.visualstudio.com/items?itemName=jsinger67.parol-vscode)\n\n- [CHANGELOG parol-vscode](./tools/parol-vscode/CHANGELOG.md)\n- [Development checks parol-vscode](./tools/parol-vscode/README.md#development-checks)\n\n---\n\n\u003c!-- Start of content from CommonReadMe copied here.\nUnfortunately there is no include directive available in Markdown --\u003e\n\n[parol](https://github.com/jsinger67/parol/tree/main/crates/parol) is a LL(k) and a LALR(1) parser\ngenerator **for Rust and C#**.\n\nIt's an installable command line tool that can generate complete parsers from a single grammar\ndescription file including all AST data types you would otherwise had to design by yourself. `parol`\ndoes this solely by analyzing your language's grammar. `parol` is also a library that you can use in\nyour own crates.\n\nYou can control the process of AST type generation. First you can mark elements for omission in your\nAST. Also you can specify your own types for language elements.\n\nLanguage description and language implementation is strictly separated in `parol`. Thus you can\ndesign your language's grammar without any need to process anything because generated parsers\nfunction by default as acceptors. This empowers you to do a real _rapid prototyping_ of your grammar.\n\n`parol` generates a trait as interface between your language processing and the generated parser.\nThe trait contains functions for each non-terminal of your grammar which you can implement for\nnon-terminals you need to process. In the simplest case you only implement the trait function for\nthe start symbol of your grammar which is called after the whole input string is parsed. This\nfunction then is called with a parameter that comprises the complete structure of the parsed\ndocument.\n\nFor generated C# parsers this interface is emitted as `I\u003cGrammarName\u003eActions` and extends\n`IUserActions` and `IProvidesValueConverter`. Generated actions include a default\n`GeneratedValueConverter` and delegate `%nt_type` conversions via `RuntimeValueConverter.Convert\u003cT\u003e`.\nYou can override the `ValueConverter` property in a derived actions class to provide custom\ngrammar-specific conversions.\nThe .NET SDK is only required for C# generation/build workflows. Rust-only workflows do not\nrequire .NET, and C# integration tests are skipped automatically when `dotnet` is not available.\nC# code generation supports both LL(k) and `%grammar_type 'LALR(1)'` grammars.\n\nThe parser calls the interface trait's functions via a separately generated adapter automatically\nduring the process of parsing.\n\nWith such a generated interface trait you theoretically never have to let `parol` generate new code\nfor you anymore and you can concentrate on the development of your language processing. Although,\noften a more iterative approach is taken.\n\n## Generated parsers\n\n- are true LL(k) parsers implemented by push down automata (PDAs).\n- are predictive, i.e. they implement a **non-backtracking** parsing technique. This often results\n  in much faster parsers.\n- are clean and easy to read.\n- use only as much lookahead as needed for a certain non-terminal (from 0 to k)\n- are generated from **a single grammar description** file.\n- can generate types that resemble the AST of your grammar automatically. Semantic actions are then\n  called with these types. This greatly improves the development process and makes it less error-prone.\n- As of version 0.24.0 generated parsers can recover from syntax errors automatically\n- As of version 0.28.0 `parol` starts to support LR style grammars as well, in detail LALR(1)\ngrammars. Please have a look at the [CHANGELOG](https://github.com/jsinger67/parol/blob/main/crates/parol/CHANGELOG.md)\n\n## Other properties of `parol`\n\n- Selection of production is done by a deterministic finite **lookahead automaton** for each\n  non-terminal.\n- **Semantic actions** with empty default implementations are generated as a trait. You can\n  implement this trait for your grammar processing item and implement only needed actions. This\n  provides a loose coupling between your language definition and the language processing.\n- As a result semantic actions are strictly separated from the grammar definition in contrast to\n  Bison. No parser generation step is needed when you merely change the implementation of a semantic\n  action.\n- The grammar description is provided in a **Yacc/Bison-like style** with additional features known\n  from EBNF such as grouping, optional elements and repetitions.\n- You can define multiple scanner states (aka start conditions) and define switches between them\n  directly in the productions of your grammar.\n- You can opt out the default handling of whitespace and newlines for each scanner state separately.\n- The grammar description supports definition of language comments via **%line_comment** and\n  **%block_comment** declarations for each scanner state.\n- The crate provides several tools for **grammar analysis**, **transformation** and **parse tree visualization**\n  to support your grammar implementation.\n- The parser generator **detects direct and indirect left recursions** in your grammar description.\n- `parol`'s parser is generated by `parol` itself.\n- Use `parol new` to create your own crate that uses `parol`.\n- `parol new -L c-sharp` creates a .NET console project and references\n  [Parol.Runtime](https://www.nuget.org/packages/Parol.Runtime) from NuGet by default.\n\n## Why should you use LL(k) parsers in your language implementation?\n\nLL parsing technique is a top-down parsing strategy that always starts from the start symbol of your\ngrammar. This symbol becomes the root node of the parse tree. Then it tries to derive the left-most\nsymbol first. All such symbols are then processed in a pre-order traversal. During this process the\nparse tree is created from the root downwards.\n\nBoth, processing the input and producing the parse tree in 'natural' direction ensures that at every\npoint during parsing you can see where you came from and what you want to derive next. `parol`'s\nparse stack contains 'End of Production' markers which reflect the 'call hierarchy' of productions.\n\nThis tremendously helps to put your language processing into operation. In contrast, anyone who has\never debugged a LR parser will remember the effect of 'coming out of nowhere'.\n\nAlthough LL grammars are known to be less powerful than LR grammars many use cases exist where LL\ngrammars are sufficient. By supporting more than one lookahead token the abilities of traditional\nLR(1) grammars and LL(k) grammars become more and more indistinct.\n\n## Why should you use `parol`?\n\n`parol` is simple. You can actually understand all parts of it without broader knowledge in parsing\ntheory.\n\n`parol` is fast. The use of deterministic automata ensures a minimal overhead during parsing, no\nbacktracking needed.\n\n`parol` is a true LL(k) parser. You won't find much working LL(k) parsers out there.\n\n`parol` generates beautiful code that is easy to read which fosters debugging.\n\n`parol` is young. Although this might be a problem some times, especially regarding the stability of\nthe API, the best is yet to come.\n\n`parol` is actively developed. Thus new features are likely to be added as the need arises.\n\n## Documentation\n\n### [Examples](https://github.com/jsinger67/parol/tree/main/examples)\n\nThis project contains some introductory grammar examples from entry level up to a more complex\n[C-like expression language](https://github.com/jsinger67/parol/tree/main/examples/calc)\nand an acceptor for [Oberon-0](https://github.com/jsinger67/parol/tree/main/examples/oberon_0) grammar.\n\nA complete Oberon-2 acceptor generated by `parol` can be found in the examples of this\n[repository](https://github.com/jsinger67/parol/tree/main/examples/oberon2).\n\nA rudimentary [Basic interpreter](https://github.com/jsinger67/parol/tree/main/examples/basic_interpreter)\nstrives to mimic a small part of C64 Basic.\n\nI also provide a [JSON Parser](https://github.com/jsinger67/parol/tree/main/examples/json_parser).\n\nC# examples are available as [calc_csharp](https://github.com/jsinger67/parol/tree/main/examples/calc_csharp)\nand [json_parser_csharp](https://github.com/jsinger67/parol/tree/main/examples/json_parser_csharp).\n\n`parol`'s input language processing is an additional and very practical example.\n\n### [The book](https://jsinger67.github.io/)\n\nA book explains some internals and the practical use of `parol` in detail. It is still a work in\nprogress but should be considered as the central documentation.\n\nFor external generators, see the\n[Export Model Contract](./book/src/ExportModelContract.md) chapter.\nMachine-readable schema (v1):\n[parser-export-model.v1.schema.json](./crates/parol/schemas/parser-export-model.v1.schema.json)\n\n### [The video](https://youtu.be/TJMwMqD4XSo)\n\nThis video explains the installation of `parol` and the language server to setup your working\nenvironment. Then it shows the process of designing grammars with `parol` with the help of an\nexample project.\n\n## State of the project\n\n- Version 1 of `parol` is stable and production ready with all the usual disclaimers.\nIt receives fixes on branch `release1.0`\nYou should use the latest releases available on crates.io with version \u003e=1.\n\n- Version 2 is stable and production ready with all the usual disclaimers.\nIt receives fixes on branch `release2.2`\n\n- Version 3 is stable and production ready with all the usual disclaimers.\nIt receives fixes on branch `release3.1`\n\n- Version 4 is the current stable version. It is in active development to receive new features and bug fixes.\nWatch CHANGELOG closely and update when new releases are published.\n\n## Dependencies\n\nPlease note that any necessary dependencies are automatically added to your new `parol` project if\nyou use the `parol new` subcommand to create your new crate. The following sections are therefore\nfor information only.\n\n### Runtime library\n\nParsers generated by `parol` have to add a dependency to the\n[parol_runtime](https://crates.io/crates/parol_runtime) crate. It provides the scanner and parser\nimplementations needed. The parol_runtime crate is very lightweight.\n\nFor generated C# projects, `parol new -L c-sharp` adds a dependency to\n[Parol.Runtime](https://www.nuget.org/packages/Parol.Runtime) on NuGet.\n\n### Macros\n\nYou have to add the [parol-macros](https://github.com/jsinger67/parol-macros) crate to your\ndependencies. When using `parol new` all necessary dependencies are added for you automatically.\n\n## License\n\n`parol` and its accompanied tools included in this workspace are free, open source and permissively\nlicensed! Except where noted (below and/or in individual files), all code in this repository is\ndual-licensed under either:\n\n- MIT License ([LICENSE-MIT](LICENSE-MIT) or\n  [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))\n\nat your option.\nThis means you can select the license you prefer!\n\n### Your contributions\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the\nwork by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any\nadditional terms or conditions.\n\n## Further readings\n\n- [CHANGELOG](https://github.com/jsinger67/parol/blob/main/crates/parol/CHANGELOG.md)\n- [The book](https://jsinger67.github.io/)\n- [The video](https://youtu.be/TJMwMqD4XSo)\n\n## Contributors\n\nThanks to all the contributors for improving this project!\n\n- [Techcable](https://github.com/Techcable)\n- [oaleaf](https://github.com/oaleaf)\n- [mobotsar](https://github.com/mobotsar)\n- [ryo33](https://github.com/ryo33)\n- [dalance](https://github.com/dalance)\n- [udoprog](https://github.com/udoprog)\n- [AumyF](https://github.com/AumyF)\n- [yui-knk](https://github.com/yui-knk)\n- [ydah](https://github.com/ydah)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsinger67%2Fparol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsinger67%2Fparol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsinger67%2Fparol/lists"}