用声明式宏解析 Rust 语法

今天尝试解析一下 Rust 中的几种 item。我们知道一个 crate 是由 item 组成的,每一个 fn struct enum impl mod 等定义都是一个 item,
这篇文章就简单解析一下 Function 和 struct

Function

先看一个最简单的函数

 
fn foo() {}

这个 foo 函数由关键字 fn 开头,后面跟一个函数名($function_name: ident), 然后是一对 (), 再跟一个函数体 block

 
macro_rules! function_item_matcher {
(fn $name: ident () $block: block) => {
fn $name() $block
};
}
function_item_matcher! {
fn hello(){
println!("hello");
}
}

再复杂一点,给我们的 foo 函数加点料

 
#[allow(unused_variables)]
pub async fn foo(arg1: u8) -> u8 { arg1 }

我们的 foo 函数已经具备了常见函数的基本形态,除了没有泛型等比较复杂的部分,这里了解分析方法就行,有需要的话再继续抽丝剥茧即可。
完整的 Function 的语法定义看这里: Functions - The Rust Reference

 
macro_rules! function_item_matcher {
(
#[$meta: meta]
$vis: vis async fn $name: ident ($arg: ident : $ty: ty) -> $ret:ty $block: block
) => {
#[$meta]
$vis async fn $name($arg: $ty) -> $ret $block
};
}

如果 meta 的个数和 argument 的个数都不确定呢

 
#[allow(unused_variables)]
#[allow(dead_code)]
pub async fn foo(arg1: u8, arg2: u32, ) -> u8 { arg1 }

好,那就再改一改:

 
macro_rules! function_item_matcher {
(
$(#[$meta: meta])*
$vis: vis async fn $name: ident ($($arg: ident : $ty: ty),* $(,)?) -> $ret:ty $block: block
) => {
$(#[$meta])*
$vis async fn $name($($arg: $ty),*) -> $ret $block
};
}

还有个问题,这个 async 直接写下来的,要是没有 async 呢? 只需要加一个分支就好

 
macro_rules! function_item_matcher {
(
$(#[$meta: meta])*
$vis: vis async fn $name: ident ($($arg: ident : $ty: ty),* $(,)?) -> $ret:ty $block: block
) => {
$(#[$meta])*
$vis async fn $name($($arg: $ty),*) -> $ret $block
};
(
$(#[$meta: meta])*
$vis: vis fn $name: ident ($($arg: ident : $ty: ty),* $(,)?) -> $ret:ty $block: block
) => {
$(#[$meta])*
$vis fn $name($($arg: $ty),*) -> $ret $block
};
}

这样做不过是把我定义的函数照搬下来,有什么好处呢?好处就是你可以随意插入自己的代码

 
macro_rules! function_item_matcher {
(
$(#[$meta: meta])*
$vis: vis fn $name: ident ($($arg: ident : $ty: ty),* $(,)?) -> $ret:ty $block: block
) => {
println!("definition: {}({})", stringify!($name), stringify!($($arg: $ty),*));
$(#[$meta])*
$vis fn $name($($arg: $ty),*) -> $ret {
print!("calling: {}(", stringify!($name));
$(print!("{},", $arg);)*
println!(")");
$block
}
};
}
function_item_matcher!{
#[allow(unused_variables)]
#[allow(dead_code)]
pub fn foo(arg1: u8, arg2: u32, ) -> u8 { arg1 }
}
foo(9, 8);

输出

 
definition: foo(arg1 : u8, arg2 : u32)
calling: foo(9,8,)

struct

struct 有两种

 
// struct struct
#[...]
struct A {
...
}
// tuple struct
#[...]
struct B(...);

所以对于第一种:

 
macro_rules! struct_item_matcher {
(
$(#[$meta: meta])*
$vis: vis struct $name: ident {
$(
$(#[$field_meta: meta])*
$field_vis: vis $field_name: ident : $field_ty: ty
),*
$(,)?
}
) => {
$(#[$meta])*
$vis struct $name {
$(
$(#[$field_meta])*
$field_vis $field_name: $field_ty
),*
}
};
// 针对 struct A; 的情况
(
$(#[$meta: meta])*
$vis: vis struct $name: ident;
) => {
$(#[$meta])*
$vis struct $name;
}
}

对于第二种 tuple struct 的情况处理起来大同小异,我就不写了 😂

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值