# nom-rule [![Documentation](https://docs.rs/nom-rule/badge.svg)](https://docs.rs/nom-rule/) [![Crates.io](https://img.shields.io/crates/v/nom-rule.svg)](https://crates.io/crates/nom-rule) [![LICENSE](https://img.shields.io/github/license/andylokandy/nom-rule.svg)](https://github.com/andylokandy/nom-rule/blob/master/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 ```rust use nom_rule::rule; // Define your match functions fn match_text<'a>(text: &'a str) -> impl FnMut(Input<'a>) -> IResult, &'a Token<'a>> { // Implementation } fn match_token<'a>(kind: TokenKind) -> impl FnMut(Input<'a>) -> IResult, &'a Token<'a>> { // Implementation } fn ident<'a>(input: Input<'a>) -> IResult, &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`](examples/sqlparser.rs) file for a complete example parsing a simplified SQL `CREATE TABLE` statement.