Rust编译器将源码进行Tokenization,转换成一个个token tree,这些token tree可以是不符合Rust语法规则的。这些token有不同的类型。
foo, Bambous, self, we_can_dance, LaCaravane, …42, 72u32, 0_______0, 1.0e-40, "ferris was here", …_, fn, self, match, yield, macro, …[, :, ::, ?, ~, @, …需要注意的是self,即是Identifiers,也是Kerwords,大多数情况下是Keywords Macro是Rust的语法扩展
Tokenization后,接下来就是将token stream转换成AST(Abstract Syntax Tree),这一步被称之为**Paprsing,**而宏的处理就是在AST之后开始了。
所有的Token自己就是一个Token Tree,具体点来说他自己就是一个只有一个叶子节点的Token Tree。被**{}、[]、()**包裹的一系列token组成了一个有多个叶子的Token Tree。例如下面这行代码。
a + b + (c + d[0]) + e
转换成Token Tree后如下:
«a» «+» «b» «+» «( )» «+» «e»
╭────────┴──────────╮
«c» «+» «d» «[ ]»
╭─┴─╮
«0»
最终转换出来的是一个具有多个根的token tree,相互嵌套,接着Token tree会被转换成AST,如下:

Token tree中不应该存在不成对的{}、[]、()
Rust的宏,其处理就是在AST构建之后,才开始进行处理,因此调用宏的语法必须是符合Rust语法规则的,属于Rust的语法扩展,下面是宏相关的语法扩展。
# [ $arg ]; e.g. #[derive(Clone)], #[no_mangle], …# ! [ $arg ]; e.g. #![allow(dead_code)], #![crate_name="blang"], …