在中$e:expr,expr称为片段说明符。它告诉解析器该参数$e期望什么样的令牌。Rust提供了多种片段说明符,使输入非常灵活。
| 说明符 | 描述 | 例子 |
|---|---|---|
| ident | 识别码 | x, foo |
| path | 合格名称 | std::collection::HashSet, Vec::new |
| ty | 类型 | i32,&T,Vec<(char, String)> |
| expr | 表达 | 2+2,f(42),if true { 1 } else { 2 } |
| pat | 模式 | _,c @ 'a' ... 'z',(true, &x),Badger { age, .. } |
| stmt | 声明 | let x = 3, return 42 |
| block | 括号分隔的块 | { foo(); bar(); }, { x(); y(); z() } |
| item | 项目 | fn foo() {},struct Bar;,use std::io; |
| meta | 属性内部 | cfg!(windows), doc="comment" |
| tt | 令牌树 | +,foo,5,[?!(???)] |
请注意,文档注释/// comment的处理方式与#[doc="comment"]宏相同。
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! {
///一些文档评论
const OPT_INT: i32 as optional;
}
// 以上内容将扩展为:
#[doc="some doc comment"]
const OPT_INT: Option<i32> = None;某些片段说明符要求标记,它后面必须是一个受限制的集合之一,称为“跟随集合”。这为Rust的语法发展提供了一定的灵活性,而又不会破坏现有的宏。
| 说明符 | 按照设定 |
|---|---|
| expr, stmt | => , ; |
| ty, path | => , = | ; : > [ { as where |
| pat | => , = | if in |
| ident,block,item,meta,tt | 任何令牌 |
macro_rules! invalid_macro {
($e:expr + $f:expr) => { $e + $f };
// ^
// +不在expr的跟随集中,
// 因此编译器将不接受此宏定义。
($($e:expr)/+) => { $($e)/+ };
// ^
// 分隔符`/`不在`expr`的跟随集中
// 因此编译器将不接受此宏定义。
}