Generating a macro in a procedural macro


#1

I’m trying to generate a procedural macro using syn and quote, and I’m struggling with how to build a macro for my output. I need to iterate over a list of paths, and generate a 2-tuple of paths and include_str!() macros. Here’s what I have so far:

let pathtokens: Vec<_> = paths.iter().map(|path| {
    let key = Token::Literal(Lit::Str(path.to_str().unwrap().to_owned(), StrStyle::Cooked));
    let val = syn::Mac {
        path: "include_str".into(),
        tts: vec![syn::TokenTree::Token(key.clone())],
    };
    let tokens = syn::Delimited {
        delim: syn::DelimToken::Paren,
        tts: vec![syn::TokenTree::Token(key), syn::TokenTree::Token(val)]
    };
    tokens
}).collect();

The problem is that syn::Mac is not actually a Token, and I can’t figure out what building blocks I need to create a macro invocation from the tokens that are available. It would be an Ident for “include_str”, and a Delimited for the argument list, but I’m not sure where the ! comes from, or how to put them together. Or is there a wrapper I can put around the syn::Mac object?


#2

From memory when I was doing this, Mac doesn’t include the parentheses so try

let val = syn::Mac {
        path: "include_str".into(),
        tts: vec![
             TokenTree::Delimited(Delimited {
                 delim: DelimToken::Paren,
                 tts: vec![syn::TokenTree::Token(key.clone())],
             }),
        ],
    };

#3

Or for readability use quote, something like

let pathtokens: Vec<_> = paths.iter().map(|path| {
    let key = path.to_str().unwrap().to_owned();
    quote! {(#key, include_str!(#key))}
}).collect();