#![feature(box_patterns)] #![recursion_limit="128"] extern crate proc_macro; #[macro_use] extern crate quote; #[macro_use] extern crate syn; use self::proc_macro::TokenStream; use self::syn::fold::Fold; struct RecursiveDescentFn { } impl Fold for RecursiveDescentFn { fn fold_item_fn(&mut self, mut i: syn::ItemFn) -> syn::ItemFn { let box block = i.block; let ref ident = i.ident; let new_block: syn::Block = parse_quote! { { let next_token_before_parse = self.token_handler.peek(); let record = ParseRecord { production_name: stringify!(#ident).to_string(), next_token: format!("{}", next_token_before_parse.to_string_with_metadata()), level: self.parse_level, }; self.parse_level += 1; self.parse_record.push(record); let result = { #block }; if self.parse_level != 0 { self.parse_level -= 1; } result.map_err(|mut parse_error: ParseError| { parse_error.production_name = Some(stringify!(#ident).to_string()); parse_error }) } }; i.block = Box::new(new_block); i } } #[proc_macro_attribute] pub fn recursive_descent_method(_attr: TokenStream, item: TokenStream) -> TokenStream { let input: syn::ItemFn = parse_macro_input!(item as syn::ItemFn); let mut folder = RecursiveDescentFn {}; let output = folder.fold_item_fn(input); TokenStream::from(quote!(#output)) }