#nom #parser #dsl #grammar #proc-macro

macro nom-rule

A procedural macro for writing nom parsers using a grammar-like DSL

11 unstable releases (4 breaking)

new 0.5.1 Jan 31, 2025
0.4.0 Sep 19, 2024
0.3.1 Jul 9, 2024
0.3.0 May 8, 2022
0.2.1 Feb 6, 2022

#1916 in Procedural macros

Download history 1177/week @ 2024-10-10 1143/week @ 2024-10-17 1384/week @ 2024-10-24 1179/week @ 2024-10-31 1208/week @ 2024-11-07 1165/week @ 2024-11-14 1761/week @ 2024-11-21 1472/week @ 2024-11-28 1345/week @ 2024-12-05 1003/week @ 2024-12-12 1194/week @ 2024-12-19 1034/week @ 2024-12-26 1786/week @ 2025-01-02 811/week @ 2025-01-09 843/week @ 2025-01-16 308/week @ 2025-01-23

3,818 downloads per month
Used in 3 crates (via databend-common-ast)

MIT license

31KB
588 lines

nom-rule

Documentation Crates.io LICENSE

A procedural macro for writing nom parsers using a grammar-like syntax.

Overview

The nom-rule crate provides the rule! macro, which allows you to define nom parsers using a domain-specific language (DSL) that resembles grammar rules. This makes your parsers more readable and easier to maintain.

Features

  • Define parsers using a grammar-like syntax.
  • Integrates seamlessly with nom combinators.
  • Supports sequences, choices, repetitions, optional parsing, and more.

Usage

use nom_rule::rule;

// Define your match functions
fn match_text<'a>(text: &'a str) -> impl FnMut(Input<'a>) -> IResult<Input<'a>, &'a Token<'a>> {
    // Implementation
}

fn match_token<'a>(kind: TokenKind) -> impl FnMut(Input<'a>) -> IResult<Input<'a>, &'a Token<'a>> {
    // Implementation
}

fn ident<'a>(input: Input<'a>) -> IResult<Input<'a>, &str> {
    // Implementation
}

fn main() {
    // Use the `rule!` macro
    let mut parser = rule!(
        CREATE ~ TABLE ~ #ident ~ ^"(" ~ (#ident ~ #ident ~ ","?)* ~ ")" ~ ";"
        : "CREATE TABLE statement"
    );
}

Syntax

The rule! macro follows these rules:

Syntax Description Expanded to Operator Precedence
TOKEN Matches a token by kind. match_token(TOKEN) -
"(" Matches a token by its text. match_text("(") -
#fn_name Calls an external nom parser function fn_name. fn_name -
#fn_name(a, b, c) Calls an external nom parser function fn_name with arguments. fn_name(a, b, c) -
a ~ b ~ c Sequences parsers a, b, and c. nom::sequence::tuple((a, b, c)) 3 (Left Associative)
a+ One or more repetitions. nom::multi::many1(a) 4 (Postfix)
a* Zero or more repetitions. nom::multi::many0(a) 4 (Postfix)
a? Optional parser. nom::combinator::opt(a) 4 (Postfix)
a | b | c Choice between parsers a, b, and c. nom::branch::alt((a, b, c)) 1 (Left Associative)
&a Peeks at parser a without consuming input. nom::combinator::peek(a) 5 (Prefix)
!a Negative lookahead for parser a. nom::combinator::not(a) 5 (Prefix)
^a Cuts the parser a. nom::combinator::cut(a) 5 (Prefix)
... : "description" Adds a context description for error reporting. nom::error::context("description", a) 2 (Postfix)

Example

See the sqlparser.rs file for a complete example parsing a simplified SQL CREATE TABLE statement.

Dependencies

~1–1.7MB
~34K SLoC