Rust宏:捕获完全匹配的令牌

Rust宏:捕获完全匹配的令牌,rust,rust-macros,Rust,Rust Macros,我的目标是编写一个宏展开以便: 结构A; 结构B; 结构Mut; 扩大() => () 扩大(A) =>(A,) 扩大(mut A)=>(mut,) 扩大(A,mut B)=>(A,mut,) //等 [Edit]为一致元组语法添加了尾随逗号 到目前为止,我编写了这个宏: macro\u规则!to_类型{ ($ty:ty)=>{$ty}; (mut$ty:ty)=>{mut}; } 宏规则!扩展{ ($($(mut)?$ty:ty),*)=>{ ( $(to_type!($ty

我的目标是编写一个宏
展开以便:

结构A;
结构B;
结构Mut;
扩大()         => ()
扩大(A) =>(A,)
扩大(mut A)=>(mut,)
扩大(A,mut B)=>(A,mut,)
//等
[Edit]为一致元组语法添加了尾随逗号

到目前为止,我编写了这个宏:

macro\u规则!to_类型{
($ty:ty)=>{$ty};
(mut$ty:ty)=>{mut};
}
宏规则!扩展{
($($(mut)?$ty:ty),*)=>{
(
$(to_type!($ty))*
,)
};
}
我正在努力的是捕获
mut
标记。如何将其分配给变量并在宏体中重用?一次可以使用多个令牌吗?

类似于

macro\u规则!扩展{
(@phase2($($ty_final:ty),*),)=>{
($($TYU最终版本,)*)
};
(@phase2($($ty_final:ty),*),mut$ty:ty,$($rest:tt)*)=>{
展开!(@phase2($($ty_final,)*Mut::),$($rest)*)
};
(@phase2($($ty\u final:ty),*),$ty:ty,$($rest:tt)*)=>{
展开!(@phase2($($ty_final,)*$ty),$($rest)*)
};
($($t:tt)*)=>{
展开!(@phase2(),$($t)*)
};
}
结构A;
结构B;
struct Mut(std::marker::PhantomData);
fn main(){
#[允许(未使用的参数)]
让我们展开!()=();
#[允许(未使用的参数)]
让我们展开!(A,)=(A,);
#[允许(未使用的参数)]
让我们展开!(mut B,)=(mut::(Default::Default()),);
#[允许(未使用的参数)]
让我们展开!(A,mut B,)=(A,mut::(Default::Default());
}

如果宏调用中只有一种类型,您是要扩展到包含单个元素的元组,还是要扩展到裸类型?好问题,我想您提出这个问题是因为1元素元组的
(值,)
语法。假设结果总是一个元组。由于允许使用尾随逗号,因此不应使规则复杂化。谢谢!你能详细解释一下为什么需要模式匹配一个新引入的符号
@phase2(types)
?换句话说,为什么两个简单的匹配臂
$ty:ty,$($rest:tt)*
mut$ty:ty,$($rest:tt)*
不起作用?而且,它看起来像是
展开中的尾随逗号!(A,)
展开!(A,mut B,)
仍然需要调用,我还没有找到一种简单的方法来删除它?
macro_rules! expand {
    (@phase2($($ty_final:ty),*),) => {
        ($($ty_final,)*)
    };
    (@phase2($($ty_final:ty),*), mut $ty:ty, $($rest:tt)*) => {
        expand!(@phase2($($ty_final,)* Mut::<$ty>), $($rest)*)
    };
    (@phase2($($ty_final:ty),*), $ty:ty, $($rest:tt)*) => {
        expand!(@phase2($($ty_final,)* $ty), $($rest)*)
    };
    ($($t:tt)*) => {
        expand!(@phase2(), $($t)*)
    };
}

struct A;
struct B;
struct Mut<T>(std::marker::PhantomData<T>);

fn main() {
    #[allow(unused_parens)]
    let _: expand!() = ();
    #[allow(unused_parens)]
    let _: expand!(A,) = (A,);
    #[allow(unused_parens)]
    let _: expand!(mut B,)    = (Mut::<B>(Default::default()),);
    #[allow(unused_parens)]
    let _: expand!(A, mut B,) = (A, Mut::<B>(Default::default()));
}