I’m writing a small parser in Rust, with nom, a parser combinators library.
If you have heard about nom, you might know nom is using macros heavily. It was, but not anymore since 5.0.0.
This version comes with a complete rewrite of nom internals to use functions as a base for parsers, instead of macros. Macros have been updated to use functions under the hood, so that most existing parsers will work directly or require minimal changes.
Writing a parser in nom reminds me boost::xpressive. It feels like writing a regexp with functions.
fn parse_literal<'a>(input: &'a str) -> IResult<&'a str, Literal, VerboseError<&'a str>> {
alt((
map_res(digit1, |s: &str| s.parse::<i32>().map(Literal::Number)),
map(
preceded(
char('\"'),
terminated(escaped(none_of("\\\""), '\\', one_of("\"n\\")), char('\"')),
),
|s: &str| Literal::String(s.to_string()),
),
))(input)
}
For me, writing a parser in nom starts from thinking about its abstract syntax tree, often with a lot of enums. Then I write all small parsers like the function above.
Source: posts/2020/nom-1.md