< 返回版块

快睡觉吧 发表于 2021-12-09 23:23

Tags:过程宏

【求助】属性宏想要实现如#[hello(name = "Rust", order = 1)]这样的效果,该怎么做呢

我通过类属性宏的方式去实现类似的效果,但是不知道下面的问题怎么解决

1、如何定义nameorder,或者如何获取nameorder

2、定义成类属性宏不能作用在struct的字段上?会出现expected non-macro attribute, found attribute macro excel_col not a non-macro attribute这样的错误。

评论区

写评论
作者 快睡觉吧 2021-12-10 17:37

非常感谢,我晚上试一试

--
👇
Grobycn: ``` use proc_macro::TokenStream; use syn::{LitStr, LitInt, Token, parse::{Parse, ParseStream}}; use syn::parse_macro_input;

mod kw { use syn::custom_keyword;

custom_keyword!(name);
custom_keyword!(order);

}

#[derive(Debug)] struct Hello { name: LitStr, order: LitInt }

impl Parse for Hello { fn parse(input: ParseStream<'>) -> syn::Result { let (mut name, mut order) = (None, None); loop { let lookahead = input.lookahead1(); if lookahead.peek(kw::name) { input.parse::kw::name()?; input.parse::<Token![=]>()?; name = Some(input.parse::()?); } else if lookahead.peek(kw::order) { input.parse::kw::order()?; input.parse::<Token![=]>()?; order = Some(input.parse::()?); } else { return Err(input.error("invalid argument")); } if let Err() = input.parse::<Token![,]>() { break; } } match (name, order) { (Some(name), Some(order)) => Ok(Self { name, order }), _ => Err(input.error("missing some argument")), } } }

#[proc_macro_attribute] pub fn hello(args: TokenStream, input: TokenStream) -> TokenStream { let hello = parse_macro_input!(args as Hello); // do what you want with hello and input stream unimplemented!() }


Grobycn 2021-12-10 15:46
use proc_macro::TokenStream;
use syn::{LitStr, LitInt, Token, parse::{Parse, ParseStream}};
use syn::parse_macro_input;

mod kw {
    use syn::custom_keyword;

    custom_keyword!(name);
    custom_keyword!(order);
}

#[derive(Debug)]
struct Hello {
    name: LitStr,
    order: LitInt
}

impl Parse for Hello {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        let (mut name, mut order) = (None, None);
        loop {
            let lookahead = input.lookahead1();
            if lookahead.peek(kw::name) {
                input.parse::<kw::name>()?;
                input.parse::<Token![=]>()?;
                name = Some(input.parse::<LitStr>()?);
            } else if lookahead.peek(kw::order) {
                input.parse::<kw::order>()?;
                input.parse::<Token![=]>()?;
                order = Some(input.parse::<LitInt>()?);
            } else {
                return Err(input.error("invalid argument"));
            }
            if let Err(_) = input.parse::<Token![,]>() {
                break;
            }
        }
        match (name, order) {
            (Some(name), Some(order)) => Ok(Self { name, order }),
            _ => Err(input.error("missing some argument")),
        }
    }
}

#[proc_macro_attribute]
pub fn hello(args: TokenStream, input: TokenStream) -> TokenStream {
    let hello = parse_macro_input!(args as Hello);
    // do what you want with hello and input stream
    unimplemented!()
}
1 共 2 条评论, 1 页