1 unstable release
0.1.0 | Jan 6, 2024 |
---|
#256 in Parser tooling
140KB
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( */
Ast::Expr(a)/*,
Span::new(toks[0].item.span.start, toks.last().unwrap().item.span.end)
)*/
}%
| "(" Expr:&e ")" -> {
Ast::Expr(e)
}%;
EntryPoint: Ast = Expr:&e -> {
Ast::EntryPoint(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.
Ideas:
-
Builder::dump_grammar
// should return aRuleMap
- 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
Dependencies
~4–12MB
~84K SLoC