From 2305e6453fbc4360992c34c9fa6be4171cb5b156 Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Sun, 25 May 2025 18:43:36 -0700 Subject: [PATCH] Hacking on grammar! proc macro - Generated functions take parser state as input - Start of code generation - WIP modeling of sequences --- Cargo.lock | 5 +++-- peg_macro/Cargo.toml | 1 + peg_macro/src/lib.rs | 25 +++++++++++++++++++++++-- src/peg/peg.rs | 5 +++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa010b8..efa3af0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" name = "peg_macro" version = "0.1.0" dependencies = [ + "proc-macro2", "quote", "syn", ] @@ -168,9 +169,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] diff --git a/peg_macro/Cargo.toml b/peg_macro/Cargo.toml index d8360c6..9207d01 100644 --- a/peg_macro/Cargo.toml +++ b/peg_macro/Cargo.toml @@ -7,5 +7,6 @@ edition = "2024" proc-macro = true [dependencies] +proc-macro2 = "1.0.95" quote = "1.0.40" syn = "2.0.101" diff --git a/peg_macro/src/lib.rs b/peg_macro/src/lib.rs index e1fd650..d7c2d14 100644 --- a/peg_macro/src/lib.rs +++ b/peg_macro/src/lib.rs @@ -17,8 +17,9 @@ struct Rule { } enum Term { - Rule(Ident), Literal(LitStr), + Rule(Ident), + Sequence(Vec), } impl Parse for Grammar { @@ -54,6 +55,22 @@ impl Parse for Term { } } +impl Term { + fn generate_code(&self) -> proc_macro2::TokenStream { + match self { + Term::Rule(ident) => quote! { + println!("call subrule"); + // call subrule + }, + Term::Literal(lit_str) => quote! { + println!("parse literal"); + // call p.literal() + }, + Term::Sequence(terms) => todo!(), + } + } +} + #[proc_macro] pub fn grammar_old(ts: TokenStream) -> TokenStream { let token = ts.into_iter().next().expect("must have at least one token"); @@ -95,12 +112,16 @@ pub fn grammar(ts: TokenStream) -> TokenStream { .map(|t| match t { Term::Rule(ident) => format!("rule {}", ident.to_string()), Term::Literal(lit_str) => format!("literal \"{}\"", lit_str.value()), + Term::Sequence(terms) => todo!(), }) .collect(); let text = format!("I'm generated! ({})", term_strs.join(", ")); + let generated: Vec<_> = r.terms.iter().map(|t| t.generate_code()).collect(); + quote! { - fn #fn_name() -> String { + fn #fn_name(p: &mut crate::peg::ParseState) -> String { + #(#generated)* #text.into() } } diff --git a/src/peg/peg.rs b/src/peg/peg.rs index d618c51..00bb441 100644 --- a/src/peg/peg.rs +++ b/src/peg/peg.rs @@ -85,7 +85,8 @@ mod tests { #[test] fn test_generated() { - assert_snapshot!(generated_this(), @"I'm generated! (rule foo)"); - assert_snapshot!(generated_that(), @r#"I'm generated! (literal "bar", rule baz)"#); + let mut p = ParseState::new(""); + assert_snapshot!(generated_this(&mut p), @"I'm generated! (rule foo)"); + assert_snapshot!(generated_that(&mut p), @r#"I'm generated! (literal "bar", rule baz)"#); } }