#macro-rules #proc-macro #pattern-matching #syntax

proc-macro-rules

Emulate macro-rules pattern matching in procedural macros

5 unstable releases

0.4.0 Nov 7, 2023
0.2.1 Jan 6, 2019
0.2.0 Jan 6, 2019
0.1.1 Jan 5, 2019
0.1.0 Jan 5, 2019

#70 in Procedural macros

Download history 7272/week @ 2024-01-03 6957/week @ 2024-01-10 7816/week @ 2024-01-17 11274/week @ 2024-01-24 7548/week @ 2024-01-31 12136/week @ 2024-02-07 8143/week @ 2024-02-14 8562/week @ 2024-02-21 12149/week @ 2024-02-28 11514/week @ 2024-03-06 12431/week @ 2024-03-13 7784/week @ 2024-03-20 19494/week @ 2024-03-27 14058/week @ 2024-04-03 10065/week @ 2024-04-10 8108/week @ 2024-04-17

53,020 downloads per month
Used in 50 crates (via deno_ops)

Apache-2.0/MIT

19KB
359 lines

proc-macro-rules

macro_rules-style syntax matching for procedural macros.

This crate is work-in-progress, incomplete, and probably buggy!

Example:

rules!(tokens => {
    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
        for f in found {
            do_something(finish, f, inner, rest[0]);
        }
    }
    (foo $($bar:expr)?) => {
        match bar {
            Some(e) => foo_with_expr(e),
            None => foo_no_expr(),
        }
    }
});

Using proc-macro-rules

Add proc-macro-rules = "0.3.0" (or proc-macro-rules = "0.2.1" for versions between 1.31 and 1.56) to your Cargo.toml.

Import the rules macro with use proc_macro_rules::rules, then use with rules!(tokens => { branches }); where tokens is an expression which evaluates to a TokenStream (such as the argument in the definition of a procedural macro).

Each branch in branches should have the form ( pattern ) => { body } where pattern is a macro-rules-style pattern (using all the same syntax for meta-variables, AST nodes, repetition, etc.) and body is rust code executed when the pattern is matched. Within body, any meta-variables in the pattern are bound to variables of an appropriate type from either the proc_macro2 or syn crates. Where a meta-variable is inside a repetition or option clause, it will be wrapped in a Vec or Option, respectively.

For example, in the first branch in the above example ident has type syn::Ident and inner has type Vec<proc_macro2::TokenTree>.

Building and testing

Use cargo build to build, cargo test --all to test.

Contributing

Contributions are very welcome! It would be great to know things which are missing or incorrect (in general we should have the same behaviour as macro_rules, so anything different is incorrect). Issues, code, docs, tests, and corrections are all welcome.

Dependencies

~0.3–0.8MB
~19K SLoC