gramma 0.2.24

Generate a scannerless parser by declaring types.
Documentation
Define AST rules by declaring `struct`s and `enum`s.

# Basic Example
```rust
// Define Ident, LParen, RParen, Whitespace here:
gramma::define_token! {
    /* ... */
#    #[pattern(matcher = word_boundary() + !precedes(ascii_digit()) + word().repeat(1..).simple() )]
#    struct Ident;
#    #[pattern(exact = "(")]
#    struct LParen;
#    #[pattern(exact = ")")]
#    struct RParen;
#    #[pattern(matcher = whitespace().repeat(..).simple())]
#    struct Whitespace;
}
gramma::define_rule! {
 struct Group {
     l_paren: LParen,
     exprs: Vec<Expr>,
     r_paren: RParen,
 }
 // Enum rules may only have struct-like variants:
 #[transform(ignore_around<Whitespace>)]
 enum Expr {
     Group { group: Group },
     Ident { ident: Ident },
 }
}

let src = "
(list
    (add a b)
    (mul (sub c d) e)
)
";

let expr: Expr = gramma::parse_tree::<_, 1>(src).unwrap();

let display = format!("{:#}", gramma::display_tree(src, &expr));
assert_eq!(display, r#"Group -> {
    "(",
    [
        <Ident "list">,
        Group -> {
            "(",
            [
                <Ident "add">,
                <Ident "a">,
                <Ident "b">,
            ],
            ")",
        },
        Group -> {
            "(",
            [
                <Ident "mul">,
                Group -> {
                    "(",
                    [
                        <Ident "sub">,
                        <Ident "c">,
                        <Ident "d">,
                    ],
                    ")",
                },
                <Ident "e">,
            ],
            ")",
        },
    ],
    ")",
}"#);
```
# Transformations
In the example above, `Expr` was given the attribute
`#[transform(ignore_around<Whitespace>)]`.
Transformations, denoted by the `#[transform(...)]` attribute,
modify the way a rule is parsed.
All built-in transformations are declared as types in the
[ast::transform](crate::ast::transform) module.
Some of the more common transformations are:
<table>
<thead><tr><th>Transformation</th><th>Description</th></tr></thead>
<tr><td>

[`ignore_before<S>`](ignore_before)
</td><td>

Parse an _optional_ `S` before the target rule and discard the result if found.
Useful for ignoring optional whitespace before the target rule.
</td></tr><tr><td>

[`ignore_after<S>`](ignore_after)
</td><td>


Parse an _optional_ `S` after the target rule and discard the result if found.
Useful for ignoring optional whitespace after the target rule.
</td></tr><tr><td>

[`ignore_around<S1, S2 = S1>`](ignore_around)
</td><td>


Parse an _optional_ `S1` before and `S2` after the target rule and discard the results if found.
Useful for ignoring optional whitespace around the target rule.
</td></tr><tr><td>

[`discard_before<S>`](discard_before)
</td><td>

Parse a _required_ `S` before the target rule and discard the result.
Useful for matching punctuation before the target rule.
</td></tr><tr><td>

[`discard_after<S>`](discard_after)
</td><td>

Parse a _required_ `S` after the target rule and discard the result.
Useful for matching punctuation after the target rule.
</td></tr><tr><td>

[`discard_around<S1, S2 = S1>`](discard_around)
</td><td>

Parse a _required_ `S1` before and `S2` after the target rule and discard the results.
Useful for matching punctuation around the target rule.
</td></tr><tr><td>

[`not<Invalid>`](not)
</td><td>

Rejects if the section matched by the target rule starts with `Invalid`.
</td></tr><tr><td>

[`for_each<X>`](for_each)
</td><td>

Apply the transformation `X` to each item in the target rule.
Useful when matching a `Vec` of rules.
</td></tr>
</table>

A `#[transform(...)]` can be applied to the entirety of a `struct` or `enum` rule,
an `enum` variant, or an individual field.