Hi everyone!
I have recently released my first library, marser and I would love to get some feedback! It is a parsing library that enables writing PEG grammars in Rust. It focuses on easy to implement error recovery and good error messages.
One notable feature is that you can just write the grammar in Rust code and then use it to parse input. This works using the capture! macro. For example you can define a json array like this:
// defining an array
// capture allows you to "match" an input to a grammar
// while storing results in "buckets". These results can then be
// used to construct the output
// capture!(grammar_with_binds => result)
// the code below corresponds to '[' (element (',' element)*)? ']' plus whitespace handling
let array = capture!((
'[',
whitespace.clone(),
optional((
// this binds the result of the element parser in the
// elements bucket. The * before elements means that the bucket is a vector
// ?{name} for Optional and just {name} for just the value
bind!(element.clone(), *elements),
many((
',',
whitespace.clone(),
bind!(element.clone(), *elements) // * can be bound to multiple times
)),
)),
whitespace.clone(),
']',
whitespace.clone()
)
// we can then use the result from the matching to construct the return value of the parser
=> JsonValue::Array(elements)
);
(This example also requires that whitespace and element are already defined. I have a full json parser example here)
You can find more about this capture! syntax here
Additionally you can make the parser recover from errors in multiple ways. You can read more about it here
^ an example of error messages created by the json parser. Rendered using annotate-snippets.
Some other features:
- Zero copy parsing support
- Multiple input formats possible - use
&strand&[u8]/&[T]or implement theInputtrait yourself. - Simple debugging of your parsers using a custom TUI
Screenshot of the tui, rust grammar on the left, parsed source code on the right:
Any feedback is appreciated. These are some things where feedback interests me the most:
- The capture! / bind! syntax - Do you think this is useful? Would it make sense to change something?
- I use unsafe to enable packrat-style caching of parser results which have different types by using type erasure. Sadly I cannot use dyn Any here because Any requires 'static and I want to allow for zero-copy parsing. I would really appreciate it if someone took the time to look over it to make sure it is sound. You can find the relevant code here
- General presentation of the library - Is the README missing something? Should I explain something better?
I have used AI for parts of the documentation and for some of the macro code, but the core parsing code has been written by me.
Some links:
Thanks in advance for anyone taking the time to look at it!

