-
-
Notifications
You must be signed in to change notification settings - Fork 310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about parsing args passed to an attribute like macro #86
Comments
As far as I know there is nothing for this currently. We have only recently started thinking about how to support non-derive procedural macro use cases, for example in #81. I think the easiest way to make this work right now is to turn the args into a fake derive input: #[proc_macro_attribute]
pub fn buildmenu(args: TokenStream, input: TokenStream) -> TokenStream {
let derive_input = format!("#[buildmenu{}] struct Dummy;", args);
let attrs = syn::parse_derive_input(&derive_input).unwrap().attrs;
let args = attrs.into_iter().next().unwrap().value;
println!("{:#?}", args);
input
} This gives you List(
Ident(
"buildmenu"
),
[
MetaItem(
NameValue(
Ident(
"file"
),
Str(
"gtk/menu.xml",
Cooked
)
)
)
]
) Then actually doing something useful with that structure is a bit of a pain. I am tracking better ways of doing that in #25. My current thinking would be to build it on top of Serde, so you would have something like this: #[derive(Deserialize)]
struct BuildmenuArgs {
file: String
}
#[proc_macro_attribute]
pub fn buildmenu(args: TokenStream, input: TokenStream) -> TokenStream {
let args: BuildmenuArgs = syn::load_args(&args).unwrap();
/* ... */
} Let me know what you think! |
That's an interesting thought; I love the idea of treating a token stream as a serialization format. It would also be nice to have some form of #[proc_macro_attribute]
pub fn buildmenu(args: TokenStream, input: TokenStream) -> TokenStream {
let args: BuildmenuArgs = syn::load_args(&args).unwrap();
// Return some modified input (I couldn't think of a real example off the top of my head):
args.Iter().Map(|token| -> Token { … }).Remove(matchingtoken)
} Thanks for your help! |
Yes! The TokenStream API is going to be fleshed out some more as follow-ups to the initial proc macro RFC (rust-lang/rfcs#1566).
|
For the sake of completing this thread with a solution, I ended up going ahead and using Serde. Since #[derive(Deserialize, Debug)]
struct BuildmenuArgs {
file: String,
}
#[proc_macro_attribute]
pub fn buildmenu(args: TokenStream, input: TokenStream) -> TokenStream {
let args_string = args.to_string();
let toml_str = args_string.trim_matches(|c| c == ')' || c == '(').trim();
let buildmenuargs: BuildmenuArgs = toml::decode_str(toml_str).unwrap();
input
} Thanks for the idea! |
Thanks!
Is there a similar crate to
syn
but for parsing arguments in an attribute like proc macro? Eg. if I write a macro that looks something like:which is used like:
how can I parse the "file=…" since there's no
TokenStream
API yet?The text was updated successfully, but these errors were encountered: