Try generating named functions via proc macros

This commit is contained in:
2025-05-24 21:26:07 -07:00
parent 59392ccad2
commit 1d8c939400
5 changed files with 145 additions and 6 deletions
+1
View File
@@ -8,3 +8,4 @@ proc-macro = true
[dependencies]
quote = "1.0.40"
syn = "2.0.101"
+53 -1
View File
@@ -1,8 +1,39 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{
Ident, Token,
parse::{Parse, ParseStream},
parse_macro_input,
punctuated::Punctuated,
};
struct Grammar {
rules: Punctuated<Rule, Token![;]>,
}
struct Rule {
name: Ident,
}
impl Parse for Grammar {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Grammar {
rules: Punctuated::parse_terminated(input)?,
})
}
}
impl Parse for Rule {
fn parse(input: ParseStream) -> syn::Result<Self> {
let result = Self {
name: input.parse()?,
};
Ok(result)
}
}
#[proc_macro]
pub fn grammar(ts: TokenStream) -> TokenStream {
pub fn grammar_old(ts: TokenStream) -> TokenStream {
let token = ts.into_iter().next().expect("must have at least one token");
let result = match token {
proc_macro::TokenTree::Literal(literal) => {
@@ -25,3 +56,24 @@ pub fn grammar(ts: TokenStream) -> TokenStream {
quote! { println!("Hello, world! {:?}", #result); }.into()
}
#[proc_macro]
pub fn grammar(ts: TokenStream) -> TokenStream {
let input = parse_macro_input!(ts as Grammar);
let fns: Vec<_> = input
.rules
.iter()
.map(|r| {
let fn_name = &r.name;
quote! {
fn #fn_name() -> String {
"I'm a generated function!".into()
}
}
})
.collect();
quote! {
#(#fns)*
}
.into()
}