nom-rule
nom-rule is a small procedural macro for composing nom parsers with
grammar-shaped expressions.
The macro does not tokenize input and does not replace nom. It expands a rule
into ordinary nom parsers. You provide terminal matchers for your input type,
then use rule! to describe how those parsers fit together.
Quick Start
Add both crates to your project. The generated code refers to nom::..., so
nom must be a direct dependency.
[]
= "8"
= "0.5"
use tag;
use ;
use map_res;
use ParseError;
use ;
use rule;
String literals call match_text. Parsers prefixed with # are ordinary nom
parsers or parser factories. A sequence returns a tuple, so the example maps out
the punctuation it does not need.
Terminals
By default, rule! expects these names to be in scope when the corresponding
terminal form is used:
| Rule form | Expanded call |
|---|---|
"text" |
match_text("text") |
TOKEN or path::TOKEN |
match_token(TOKEN) or match_token(path::TOKEN) |
The matcher signatures are up to your input type. They only need to return
something that implements nom::Parser.
You can also pass custom matcher paths before the rule:
let parser = rule! ;
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.
Complete Example
See examples/sqlparser.rs for a token-stream parser
that lexes a small SQL statement and parses it with rule!.