Function like macro with multiple arguments

Hello,

I'm trying to make a macro,

extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro]
pub fn add(args: TokenStream) -> TokenStream {
    format!("{} + {}", args[0], args[1]).parse().unwrap()
}

It needs to be function-like, and I need to access the nth parameter, is there a way to do that?

You'll have to decide what kind of syntax you're parsing between the commas in the input first.

syn is useful for parsing proc macro input without too much work.

1 Like

Sorry for getting back so late; what would be the appropriate syn call to make here?

Something like

use proc_macro::TokenStream;
use proc_macro2::Literal;
use quote::{quote, ToTokens};
use syn::{parse::Parse, parse_macro_input, punctuated::Punctuated, Expr, Token};

struct MacroInput {
    a: Expr,
    comma: Token![,],
    b: Expr,
}

impl Parse for MacroInput {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Self {
            a: input.parse()?,
            comma: input.parse()?,
            b: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn add(tokens: TokenStream) -> TokenStream {
    let input = parse_macro_input!(tokens as MacroInput);

    let a = &input.a;
    let b = &input.b;

    quote! {
        #a + #b
    }
    .into()
}

for the case of two inputs. If you want variable number of inputs you could use Punctuated instead.

1 Like