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

macro nom-rule

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

9 releases

0.4.0 Sep 19, 2024
0.3.1 Jul 9, 2024
0.3.0 May 8, 2022
0.2.2 Apr 27, 2022
0.1.1 Jan 31, 2022

#1851 in Procedural macros

Download history 971/week @ 2024-08-26 1493/week @ 2024-09-02 1188/week @ 2024-09-09 1156/week @ 2024-09-16 1330/week @ 2024-09-23 247/week @ 2024-09-30 1088/week @ 2024-10-07 959/week @ 2024-10-14 1252/week @ 2024-10-21 1484/week @ 2024-10-28 982/week @ 2024-11-04 1310/week @ 2024-11-11 1203/week @ 2024-11-18 1684/week @ 2024-11-25 1541/week @ 2024-12-02 1186/week @ 2024-12-09

5,700 downloads per month
Used in 2 crates (via databend-common-ast)

MIT license

30KB
542 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
}

// 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.8MB
~35K SLoC