rusty_lr
A Yacc-like, procedural macro-based parser generator for Rust supporting LR(1), LALR(1), and GLR parsing strategies.
RustyLR enables you to define context-free grammars (CFGs) directly in Rust using macros or build scripts. It constructs deterministic finite automata (DFA) at compile time, ensuring efficient and reliable parsing.
Please refer to docs.rs for detailed example and documentation.
Features
- Multiple Parsing Strategies: Supports LR(1), LALR(1), and GLR parsers.
- Procedural Macros: Define grammars using lr1! and lalr1! macros for compile-time parser generation.
- Build Script Integration: Generate parsers via build scripts for complex grammars with detailed error messages.
- Custom Reduce Actions: Define custom actions during reductions to build ASTs or perform computations.
- Grammar Conflict Detection: Automatically detects shift/reduce and reduce/reduce conflicts during parser generation, providing informative diagnostics to help resolve ambiguities.
Installation
Add RustyLR to your Cargo.toml:
[]
= "..."
To use buildscript tools:
[]
= { = "...", = ["build"] }
Or you want to use executable version (optional):
Quick Start
Using Procedural Macros
Define your grammar using the lr1! or lalr1! macro:
// this define `EParser` struct
// where `E` is the start symbol
lr1!
This defines a simple arithmetic expression parser.
Using Build Script
For complex grammars, you can use a build script to generate the parser. This will provide more detailed error messages when conflicts occur.
1. Create a grammar file (e.g., src/parser.rs) with the following content:
// Rust code of `use` and type definitions
%% // start of grammar definition
%tokentype u8;
%start E;
%eof b'\0';
%token a b'a';
%token lparen b'(';
%token rparen b')';
E: lparen E rparen
| a;
...
2. Setup build.rs:
// build.rs
use build;
3. Include the generated source code:
include!;
4. Use the parser in your code:
let mut parser = new; // create <StartSymbol>Parser class
let mut context = new; // create <StartSymbol>Context class
let mut userdata: i32 = 0;
for b in input.chars
println!;
context.feed.unwrap; // feed EOF
let result:i32 = context.accept; // get value of start 'E'
GLR Parsing
RustyLR offers built-in support for Generalized LR (GLR) parsing, enabling it to handle ambiguous or nondeterministic grammars that traditional LR(1) or LALR(1) parsers cannot process. See GLR.md for details.
Examples
- Calculator: A calculator using
u8as token type. - lua 5.4 syntax parser
- Bootstrap: rusty_lr syntax parser is written in rusty_lr itself.
Cargo Features
build: Enable build script tools.fxhash: Use FXHashMap instead ofstd::collections::HashMapfor parser tables.tree: Enable automatic syntax tree construction (For debugging purposes).error: Enable detailed parsing error messages (For debugging purposes).
Syntax
RustyLR's grammar syntax is inspired by traditional Yacc/Bison formats. See SYNTAX.md for details of grammar-definition syntax.
Contribution
- Any contribution is welcome.
- Please feel free to open an issue or pull request.
License (Since 2.8.0)
Either of
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
Images
It is highly recommended to use buildscipt tools or executable instead of procedural macros, to generate readable error messages.
-Reduce/Reduce conflicts

- Shift/Reduce conflicts
