#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

#1769 in Procedural macros

Download history 1915/week @ 2024-07-24 1895/week @ 2024-07-31 1663/week @ 2024-08-07 1692/week @ 2024-08-14 1106/week @ 2024-08-21 1114/week @ 2024-08-28 1393/week @ 2024-09-04 922/week @ 2024-09-11 1568/week @ 2024-09-18 950/week @ 2024-09-25 283/week @ 2024-10-02 1176/week @ 2024-10-09 1018/week @ 2024-10-16 1448/week @ 2024-10-23 1306/week @ 2024-10-30 1040/week @ 2024-11-06

4,909 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–1.8MB
~36K SLoC