1 unstable release

0.1.0 Jan 6, 2024

#175 in Parser tooling

MIT license

3.5K SLoC

An easy-to-use, compilation-driven interface for the lrp parser library

Writing direct grammars sucks: handling the lexer's input, creating tiny different rule productions, creating the reductor table and some other stuffs that we don't care about. This library is focused on simplifying this process, the only external thing you need is a lexer like logos

A grammar example

use my_crate::Ast;
use my_crate::Sym::*; // Each module should be imported separetely (there's no { } support yet)

// you can define alias for idents and string literals
alias Number = Number;
alias "+" = Add;
alias "(" = OpenParen;
alias ")" = CloseParen;

Add: Ast = Number:&n1 "+" Number:&n2 -> {
    Ast::Add(n1, n2)

Expr: Ast = Add:&a -> {
/* Meta::new( */
    Span::new(toks[0].item.span.start, toks.last().unwrap().item.span.end)
    | "(" Expr:&e ")" -> {

EntryPoint: Ast = Expr:&e -> {

Building it

Just use parse or from_str for Builder and set the entry type (the tokens type):

let src = include_str!("your.grammar");
let builder1 = src.parse::<wop::Builder>();
let builder2 = wop::Builder::from_str(src);
assert_eq!(builder1, builder2);

Using it

To use it, just build it from Builder and call builder.dump_grammar() to generate the code for the grammar:

format!("let grammar = Grammar::new(Sym::EntryPoint, {}, Sym::Eof)", builder.dump_grammar(src)) // `src` is the source code for the grammar we used above

And for DFA building, remember to dump the reduct_map:

format!("parser.dfa(buf, {})", builder.dump_reduct_map(src))

Fun fact: This project uses itself.


  • Builder::dump_grammar // should return a RuleMap
  • For composite rules (with ( x | y)), the codeblock will be applied to both
  • Impl codeblocks
  • Impl item alias
  • Impl optional item
  • Allow to set custom slice entry
  • Impl item alias cloning
  • Allow custom token entries


~75K SLoC