gpt4 book ai didi

rust - 如何区分macro_rules宏中的不同种类的项目?

转载 作者:行者123 更新时间:2023-12-03 11:45:10 26 4
gpt4 key购买 nike

我想编写一个基于macro_rules的宏,该宏将用于包装一系列类型别名和结构定义。我可以使用$e:item在“items”上进行匹配,但这将同时匹配别名和结构。我想分别对待两者(我需要在结构上添加一些#[derive(...)])。我是否必须通过匹配诸如type $name:ident = $type:ty;之类的方法直接模仿它们的语法,还是有更好的方法?由于常规与元组之类的关系,这条路线对于结构来说似乎很烦人。如果我也想区分一些功能,那将是非常痛苦的,因为它们在语法上有很多差异。

最佳答案

我相信,对于这个问题,可以使用macro_rules!解决一些简单的情况,但是这种情况可能会受到限制(您不能超前)并且容易出错。我仅介绍类型的示例,希望可以说服自己避免macro_rules!。考虑一下这个简单的宏:

macro_rules! traverse_types {
($(type $tp:ident = $alias:ident;)*) => {
$(type $tp = $alias;)*
}
}

traverse_types!(
type T = i32;
type Y = Result<i32, u64>;
);
对于普通别名来说,这很好用。在某些时候,您可能还想处理通用类型别名(即 type R<Y> = ...形式)。好的,您仍然可以将宏重写为递归形式(并且这已经是一个不平凡的任务)来处理所有情况。然后,您会发现泛型可能很复杂(类型界限,生存期参数,where子句,默认类型等):
type W<A: Send + Sync> = Option<A>;
type X<A: Iterator<Item = usize>> where A: 'static = Option<A>;
type Y<'a, X, Y: for<'t> Trait<'t>> = Result<&'a X, Y>;
type Z<A, B = u64> = Result<A, B>;
可能所有这些情况仍然可以使用几乎不可读的 macro_rules!处理。然而,这将是 真的很难理解(即使是撰写它的人),这是怎么回事。此外,很难支持新的语法(例如 impl-trait alias type T = impl K),甚至可能需要完全重写宏。我只介绍了 type aliases部分,还有更多需要处理的 struct
我的观点是:更好地避免针对(和类似)问题的 macro_rules!procedural macros是解决该问题的一种更好的工具。如果维护了 synquote crate ,则更容易阅读(并因此扩展)并免费处理新语法。对于类型别名,这可以很简单地完成:
extern crate proc_macro;

use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream};

struct TypeAliases {
aliases: Vec<syn::ItemType>,
}

impl Parse for TypeAliases {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut aliases = vec![];
while !input.is_empty() {
aliases.push(input.parse()?);
}
Ok(Self { aliases })
}
}

#[proc_macro]
pub fn traverse_types(token: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(token as TypeAliases);

// do smth with input here

// You may remove this binding by implementing a `Deref` or `quote::ToTokens` for `TypeAliases`
let aliases = input.aliases;
let gen = quote::quote! {
#(#aliases)*
};

TokenStream::from(gen)
}
因为 struct的解析代码与 ItemStruct类型相同,并且还需要先行确定它是类型别名还是结构,所以 example at syn非常相似。

关于rust - 如何区分macro_rules宏中的不同种类的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62808267/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com