| Crates.io | syn-grammar |
| lib.rs | syn-grammar |
| version | 0.1.0 |
| created_at | 2026-01-25 21:46:07.715407+00 |
| updated_at | 2026-01-25 21:46:07.715407+00 |
| description | A parser generator for Rust that compiles EBNF-like grammars into syn::parse::Parse implementations. |
| homepage | |
| repository | https://github.com/keywan-ghadami/syn-grammar |
| max_upload_size | |
| id | 2069661 |
| size | 23,658 |
syn-grammar is a parser generator for Rust that allows you to define EBNF-like grammars directly inside your code (or in external files) and compiles them into syn parsers.
It is designed to make writing procedural macros and Domain Specific Languages (DSLs) in Rust significantly easier by handling the parsing boilerplate for you.
|), optionals (?), repetitions (*, +), and groups (...).-> { ... }) to rules to transform parsed tokens into your own AST or syn structures.ident), integers (int_lit), and strings (string_lit).expr = expr "+" term), making expression parsing intuitive..g files with include_grammar!.Add this to your Cargo.toml:
[dependencies]
syn-grammar = "0.1"
syn = { version = "2.0", features = ["full", "extra-traits"] }
quote = "1.0"
proc-macro2 = "1.0"
You can define a grammar directly inside a macro:
use syn_grammar::grammar;
use syn::parse::Parser; // Required for .parse_str()
grammar! {
grammar Calc {
// The return type of the rule is defined after `->`
rule expression -> i32 =
l:expression "+" r:term -> { l + r }
| t:term -> { t }
rule term -> i32 =
f:factor "*" t:term -> { f * t }
| f:factor -> { f }
rule factor -> i32 =
i:int_lit -> { i }
| paren(e:expression) -> { e }
}
}
fn main() {
// The macro generates a module `Calc` with functions `parse_<rule_name>`
let result = Calc::parse_expression.parse_str("1 + 2 * 3");
assert_eq!(result.unwrap(), 7);
}
src/grammar.g
grammar MyGrammar {
rule main -> String = "hello" "world" -> { "Success".to_string() }
}
src/lib.rs
use syn_grammar::include_grammar;
include_grammar!("grammar.g");
fn test() {
let res = MyGrammar::parse_main.parse_str("hello world");
assert!(res.is_ok());
}
| Syntax | Description | Example |
|---|---|---|
"lit" |
Literal match | "fn" |
ident |
Rust Identifier | my_var |
int_lit |
Integer Literal | 42 |
string_lit |
String Literal | "hello" |
name:rule |
Rule call with binding | e:expr |
( A B ) |
Grouping | ("a" "b") |
A | B |
Alternatives | "true" | "false" |
A? |
Optional | ","? |
A* |
Zero or more | item* |
A+ |
One or more | digit+ |
paren(A) |
Parentheses (...) |
paren(expr) |
bracketed[A] |
Brackets [...] |
bracketed[expr] |
braced{A} |
Braces {...} |
braced{expr} |
A => B |
Cut Operator (Commit) | "let" => "mut" |
Licensed under either of Apache License, Version 2.0 or MIT license at your option.