Rust Fragment specifiers — Kind of patterns


Example

In $e:expr, the expr is called the fragment specifier. It tells the parser what kind of tokens the parameter $e is expecting. Rust provides a variety of fragment specifiers to, allowing the input to be very flexible.

SpecifierDescriptionExamples
identIdentifierx, foo
pathQualified namestd::collection::HashSet, Vec::new
tyTypei32, &T, Vec<(char, String)>
exprExpression2+2, f(42), if true { 1 } else { 2 }
patPattern_, c @ 'a' ... 'z', (true, &x), Badger { age, .. }
stmtStatementlet x = 3, return 42
blockBrace-delimited block{ foo(); bar(); }, { x(); y(); z() }
itemItemfn foo() {}, struct Bar;, use std::io;
metaInside of attributecfg!(windows), doc="comment"
ttToken tree+, foo, 5, [?!(???)]

Note that a doc comment /// comment is treated the same as #[doc="comment"] to a macro.

macro_rules! declare_const_option_type {
    (
        $(#[$attr:meta])*
        const $name:ident: $ty:ty as optional;
    ) => {
        $(#[$attr])*
        const $name: Option<$ty> = None;
    }
}

declare_const_option_type! {
    /// some doc comment
    const OPT_INT: i32 as optional;
}

// The above will be expanded to:
#[doc="some doc comment"]
const OPT_INT: Option<i32> = None;

Follow set

Some fragment specifiers requires the token following it must be one of a restricted set, called the "follow set". This allows some flexibility for Rust's syntax to evolve without breaking existing macros.

SpecifierFollow set
expr, stmt=> , ;
ty, path=> , = | ; : > [ { as where
pat=> , = | if in
ident, block, item, meta, ttany token
macro_rules! invalid_macro {
    ($e:expr + $f:expr) => { $e + $f };
//           ^
//           `+` is not in the follow set of `expr`,
//           and thus the compiler will not accept this macro definition.
    ($($e:expr)/+) => { $($e)/+ };
//             ^
//             The separator `/` is not in the follow set of `expr`
//             and thus the compiler will not accept this macro definition.
}