Expand description
Compose nom parsers with grammar-shaped expressions.
rule! is a procedural macro. It does not tokenize input and does not
introduce a new parsing runtime. It expands a rule into ordinary nom
parser values, using terminal matcher functions supplied by the calling
crate.
The generated code refers to nom::..., so crates using this macro must
depend on nom directly.
§Quick Start
use nom::bytes::complete::tag;
use nom::character::complete::{alpha1, digit1};
use nom::combinator::map_res;
use nom::error::ParseError;
use nom::{IResult, Parser};
use nom_rule::rule;
fn match_text<'a, Error>(
text: &'static str,
) -> impl Parser<&'a str, Output = &'a str, Error = Error>
where
Error: ParseError<&'a str>,
{
tag(text)
}
fn number(input: &str) -> IResult<&str, u32> {
map_res(digit1, str::parse).parse(input)
}
fn assignment(input: &str) -> IResult<&str, (&str, u32)> {
let mut parser = rule! {
"let " ~ #alpha1 ~ " = " ~ #number ~ ";"
};
let (rest, (_, name, _, value, _)) = parser.parse(input)?;
Ok((rest, (name, value)))
}
let (rest, (name, value)) = assignment("let answer = 42;").unwrap();
assert_eq!(rest, "");
assert_eq!(name, "answer");
assert_eq!(value, 42);§Terminals
Terminals are the boundary between the grammar expression and your input representation.
| Rule form | Expanded call |
|---|---|
"text" | match_text("text") |
TOKEN or path::TOKEN | match_token(TOKEN) or match_token(path::TOKEN) |
The matcher signatures are not fixed. They only need to return values that
implement nom::Parser for your input type.
Custom terminal matcher paths can be supplied before the rule:
let parser = rule! {
crate::tokens::text, crate::tokens::kind,
TokenKind::Create ~ #ident
};§Rule Syntax
| Form | Meaning | Output shape |
|---|---|---|
"text" | Match text with match_text | matcher output |
TOKEN | Match a token with match_token | matcher output |
#parser | Use an existing parser | parser output |
#parser(args...) | Call a parser factory | parser output |
a ~ b | Run parsers in sequence | (A, B) |
a | b | Try alternatives with nom::branch::alt | branch output |
a? | Optional parser | Option<A> |
a* | Zero or more matches | Vec<A> |
a+ | One or more matches | Vec<A> |
&a | Peek without consuming input | A |
!a | Negative lookahead | () |
^a | Cut on failure | A |
a : "context" | Add nom::error::context | A |
Use parentheses to group subrules.
Operator precedence, from low to high:
- choice:
a | b - context:
a : "context" - sequence:
a ~ b - postfix operators:
?,*,+ - prefix operators:
&,!,^
Choice branches must return compatible output shapes. An optional branch is rejected before later alternatives because it can succeed without consuming input.
Macros§
- rule
- Expands a grammar-shaped expression into a
nomparser.