Rust 声明式宏中的 Metavariables 有哪些
2023/6/15 1:23:35
本文主要是介绍Rust 声明式宏中的 Metavariables 有哪些,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Metavariables
官方文档确实写得很好,但是缺少一些风味,容易催眠😵💫
还是直接看例子更爽一些,通常我们可以从示例代码中之间看出官方文档要表达的意思,而且很多时候我们可以直接在示例代码的基础上改一改,就能满足我们自己的定制化需求。越抽象的东西,越是如此😄
item
An item is a component of a crate. Items are organized within a crate by a nested set of modules. Every crate has a single "outermost" anonymous module; all further items within the crate have paths within the module tree of the crate.
There are several kinds of items:
- modules
- extern crate declarations
- use declarations
- function definitions
- type definitions
- struct definitions
- enumeration definitions
- union definitions
- constant items
- static items
- trait definitions
- implementations
- extern blocks
可以把整个 crate 比作一个 struct,这个 struct 里面的每一个 field 都是一个 item
这些 item 包括每一个 struct
, fn
, mod
的定义...
macro_rules! test_item { ($x: item) => { // #[derive(Debug)] $x } } test_item!(#[derive(Debug)] struct A{a: i32}); test_item!(fn foo(){println!("foo");}); test_item!(mod ma{}); let a = A{ a: 9}; println!("a: {:?}", a); // 输出 a: A { a: 9 } foo(); // 输出 foo
block
block 是匿名的命名空间作用域(anonymous namespace scope),就是以 {
开始 以 }
结束的整个块
macro_rules! test_block { ($x: block) => { $x } } test_block!({ println!("block"); });
stmt
A statement is a component of a block, which is in turn a component of an outer expression or function
一个 stmt 可以是一个前面的 [item](## item), 或是 let statement
, 或是 expression statement
, 或是宏调用
macro_rules! test_stmt { ($x: stmt) => { $x } } // let statement test_stmt!(let state = 8); println!("state: {}", state); // item test_stmt!(#[derive(Debug)] struct B{b: i32}); // expression statement test_stmt!{ if true { 1 } else { 2 } }; // Macro Invocation test_stmt!{ println!("Macro Invocation") };
pat_param
用来 pattern match 的 param, 匹配一个 pattern, 像 match 内 =>
左边的那些东西
pat_param 默认不匹配 or-pattern
: 0 | 1 | 2
macro_rules! test_pat_param { ($x: pat_param) => { $x } } struct Person { car: Option<String>, age: u8, name: String, gender: u8, gfs: [String; 3], } let person = Person { car: Some("bmw".into()), age: 18, name: "hansomeboy".into(), gender: 1, gfs: ["Lisa".into(), "Jennie".into(), "Rosé".into()], }; if let test_pat_param!( Person { car: Some(_), age: person_age @ 13..=19, name: ref person_name, gfs: ref whole @ [.., ref last], .. } ) = person { println!("{} has a car and is {} years old, and his last GF is {}.", person_name, person_age, last); } macro_rules! test_or_pattern { ($($x: pat_param)*) => (); } test_or_pattern!{ Some(_) Foo{x} // error: no rules expected the token `|` // 0 | 1 | 2 }
输出: hansomeboy has a car and is 18 years old, and his last GF is Rosé.
pat
用来匹配任意类型的 pattern, 包括 or-pattern
: 0 | 1 | 2
macro_rules! test_pat { ($($pat:pat)*) => (); } test_pat! { "literal" _ 0..5 ref mut PatternsAreNice 0 | 1 | 2 | 3 }
expr
一个表达式 Expression
macro_rules! test_expr { ($($x: expr)*) => (); } test_expr!{ "hello" // LiteralExpression 42 // LiteralExpression a::b::c // PathExpression a * b + c // OperatorExpression &a *a -a a = b a += b a || b && c a & b | c (a+b) - c ["a"] // ArrayExpression a[b][c] // IndexExpression ("world", 42) // TupleExpression tuple.0 // TupleIndexingExpression Point {x: 1.0, y: 2.0} // StructExpression foo() // CallExpression "3.14".parse() // MethodCallExpression foo().await // AwaitExpression bar.await hello.world // FieldExpression move|x,y| -> () {} // ClosureExpression async move {} // AsyncBlockExpression 0..10 // RangeExpression (_, a) // UnderscoreExpression vec![1,2,3] // MacroInvocation continue 'hello // ContinueExpression break 'hello // BreakExpression return 42 // ReturnExpression {} // BlockExpression #[cfg("hello")]{} unsafe {} // UnsafeExpression if condition {} // IfExpression if let a=b {} // IfLetExpression match x {} // MatchExpression }
ty
一个类型 Type
macro_rules! test_ty { ($($x: ty)*) => (); } test_ty! { u32 bool char str String [u8; 128] (u32, bool) &[u8] Hello // User-defined types fn(u8, u8) -> () &mut reference *mut pointer *const pointer dyn Trait // Trait Object impl Trait // Impl Trait }
ident
一个标识符(用来标识变量、函数、类、对象或其他程序实体的名称) an IDENTIFIER_OR_KEYWORD or RAW_IDENTIFIER
macro_rules! test_ident { ($($x: ident)*) => (); } test_ident! { foo _identifier r#true // raw identifier 深圳 }
path
macro_rules! test_path { ($($x: path)*) => (); } test_path! { a::b::c self::a::<b>::c ::std::time::Instant::now() }
tt
标记树(token tree) 是一种介于标记 (token) 与 AST(abstract syntax tree) 之间的东西
几乎所有的 token 都是 token tree 的叶子节点(leaf node), 只有被 (...)
, [...]
和 {...}
包裹在一起的一组一组的 tokens 不是叶子节点
a + b + (c + d[0]) + e
会被解析成下面的 token tree:
«a» «+» «b» «+» «( )» «+» «e» ╭────────┴──────────╮ «c» «+» «d» «[ ]» ╭─┴─╮ «0»
可以看出 token tree 的 root 节点其实是第一行的这一整组 token: «a» «+» «b» «+» «( )» «+» «e»
, 而不是单一的 node
而 AST 会生成下面这种只有一个 root 节点的数状结构:
┌─────────┐ │ BinOp │ │ op: Add │ ┌╴│ lhs: ◌ │ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ Var │╶┘ └─────────┘ └╴│ BinOp │ │ name: a │ │ op: Add │ └─────────┘ ┌╴│ lhs: ◌ │ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ Var │╶┘ └─────────┘ └╴│ BinOp │ │ name: b │ │ op: Add │ └─────────┘ ┌╴│ lhs: ◌ │ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ BinOp │╶┘ └─────────┘ └╴│ Var │ │ op: Add │ │ name: e │ ┌╴│ lhs: ◌ │ └─────────┘ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ Var │╶┘ └─────────┘ └╴│ Index │ │ name: c │ ┌╴│ arr: ◌ │ └─────────┘ ┌─────────┐ │ │ ind: ◌ │╶┐ ┌─────────┐ │ Var │╶┘ └─────────┘ └╴│ LitInt │ │ name: d │ │ val: 0 │ └─────────┘ └─────────┘
macro_rules! test_tt { ($($x: tt)*) => { println!("test_tt:"); $( println!("{:?}", stringify!($x)); )* } } test_tt! { (a + b + (c + d[0]) + e) [a + b + (c + d[0]) + e] {a + b + (c + d[0]) + e} } test_tt! { a + b + (c + d[2]) + e }
输出:
test_tt: "(a + b + (c + d [0]) + e)" "[a + b + (c + d [0]) + e]" "{ a + b + (c + d [0]) + e }" test_tt: "a" "+" "b" "+" "(c + d [2])" "+" "e"
meta
用来匹配 attribute 属性
就是那些写在 struct/enum/fn 前面的 #[...]
#![...]
macro_rules! test_meta { ($(#$(!)?[$meta: meta])*) => (); } test_meta! { #[hello] #![world] #[a="b"] }
lifetime
macro_rules! test_lifetime { ($($x: lifetime)*) => (); } test_lifetime! { 'a '_ 'static }
vis
visibility-and-privacy
macro_rules! test_vis { // ∨~~Note this comma, since we cannot repeat a `vis` fragment on its own ($($x: vis,)*) => (); } test_vis! { , pub, pub(crate), pub(super), pub(self), pub(in crate::a::b), }
literal
macro_rules! test_literal { ($($x: literal)*) => (); } test_literal! { 0 b'x' 'x' "hello" true }
这篇关于Rust 声明式宏中的 Metavariables 有哪些的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-0601-电商商品中心解密:仅凭SKU真的足够吗?
- 2024-05-01为什么公共事业机构会偏爱 TiDB :TiDB 数据库在某省妇幼健康管理系统的应用
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能