#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)

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

#2117 in Procedural macros

Download history 1211/week @ 2024-11-17 1666/week @ 2024-11-24 1558/week @ 2024-12-01 1228/week @ 2024-12-08 1182/week @ 2024-12-15 1154/week @ 2024-12-22 991/week @ 2024-12-29 1611/week @ 2025-01-05 772/week @ 2025-01-12 758/week @ 2025-01-19 411/week @ 2025-01-26 1025/week @ 2025-02-02 592/week @ 2025-02-09 714/week @ 2025-02-16 639/week @ 2025-02-23 603/week @ 2025-03-02

2,814 downloads per month
Used in 5 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.6MB
~32K SLoC