diff --git a/peg_macro/src/lib.rs b/peg_macro/src/lib.rs index 9fc4e5d..e1fd650 100644 --- a/peg_macro/src/lib.rs +++ b/peg_macro/src/lib.rs @@ -1,7 +1,7 @@ use proc_macro::TokenStream; use quote::quote; use syn::{ - Ident, Token, + Ident, LitStr, Token, parse::{Parse, ParseStream}, parse_macro_input, punctuated::Punctuated, @@ -13,6 +13,12 @@ struct Grammar { struct Rule { name: Ident, + terms: Vec, +} + +enum Term { + Rule(Ident), + Literal(LitStr), } impl Parse for Grammar { @@ -25,10 +31,26 @@ impl Parse for Grammar { impl Parse for Rule { fn parse(input: ParseStream) -> syn::Result { - let result = Self { - name: input.parse()?, - }; - Ok(result) + let name = input.parse()?; + input.parse::()?; + let mut terms = vec![]; + while !input.peek(Token![;]) { + terms.push(input.parse()?); + } + Ok(Self { name, terms }) + } +} + +impl Parse for Term { + fn parse(input: ParseStream) -> syn::Result { + let look = input.lookahead1(); + if look.peek(Ident) { + input.parse().map(Term::Rule) + } else if look.peek(LitStr) { + input.parse().map(Term::Literal) + } else { + Err(look.error()) + } } } @@ -65,9 +87,21 @@ pub fn grammar(ts: TokenStream) -> TokenStream { .iter() .map(|r| { let fn_name = &r.name; + + // Generate a string for debugging + let term_strs: Vec = r + .terms + .iter() + .map(|t| match t { + Term::Rule(ident) => format!("rule {}", ident.to_string()), + Term::Literal(lit_str) => format!("literal \"{}\"", lit_str.value()), + }) + .collect(); + let text = format!("I'm generated! ({})", term_strs.join(", ")); + quote! { fn #fn_name() -> String { - "I'm a generated function!".into() + #text.into() } } }) diff --git a/src/peg/peg.rs b/src/peg/peg.rs index 0629f10..d618c51 100644 --- a/src/peg/peg.rs +++ b/src/peg/peg.rs @@ -65,8 +65,8 @@ fn parse_oo(p: &mut ParseState) -> bool { } grammar! { - generated_this; - generated_that; + generated_this = foo; + generated_that = "bar" baz; } #[cfg(test)] @@ -85,7 +85,7 @@ mod tests { #[test] fn test_generated() { - assert_snapshot!(generated_this(), @"I'm a generated function!"); - assert_snapshot!(generated_that(), @"I'm a generated function!"); + assert_snapshot!(generated_this(), @"I'm generated! (rule foo)"); + assert_snapshot!(generated_that(), @r#"I'm generated! (literal "bar", rule baz)"#); } }