Hacking on grammar! proc macro

- Generated functions take parser state as input
- Start of code generation
- WIP modeling of sequences
This commit is contained in:
2025-05-25 18:43:36 -07:00
parent 6933ae47b4
commit 2305e6453f
4 changed files with 30 additions and 6 deletions
Generated
+3 -2
View File
@@ -131,6 +131,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
name = "peg_macro" name = "peg_macro"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2",
"quote", "quote",
"syn", "syn",
] ]
@@ -168,9 +169,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.94" version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
+1
View File
@@ -7,5 +7,6 @@ edition = "2024"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "1.0.95"
quote = "1.0.40" quote = "1.0.40"
syn = "2.0.101" syn = "2.0.101"
+23 -2
View File
@@ -17,8 +17,9 @@ struct Rule {
} }
enum Term { enum Term {
Rule(Ident),
Literal(LitStr), Literal(LitStr),
Rule(Ident),
Sequence(Vec<Term>),
} }
impl Parse for Grammar { 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] #[proc_macro]
pub fn grammar_old(ts: TokenStream) -> TokenStream { pub fn grammar_old(ts: TokenStream) -> TokenStream {
let token = ts.into_iter().next().expect("must have at least one token"); 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 { .map(|t| match t {
Term::Rule(ident) => format!("rule {}", ident.to_string()), Term::Rule(ident) => format!("rule {}", ident.to_string()),
Term::Literal(lit_str) => format!("literal \"{}\"", lit_str.value()), Term::Literal(lit_str) => format!("literal \"{}\"", lit_str.value()),
Term::Sequence(terms) => todo!(),
}) })
.collect(); .collect();
let text = format!("I'm generated! ({})", term_strs.join(", ")); let text = format!("I'm generated! ({})", term_strs.join(", "));
let generated: Vec<_> = r.terms.iter().map(|t| t.generate_code()).collect();
quote! { quote! {
fn #fn_name() -> String { fn #fn_name(p: &mut crate::peg::ParseState) -> String {
#(#generated)*
#text.into() #text.into()
} }
} }
+3 -2
View File
@@ -85,7 +85,8 @@ mod tests {
#[test] #[test]
fn test_generated() { fn test_generated() {
assert_snapshot!(generated_this(), @"I'm generated! (rule foo)"); let mut p = ParseState::new("");
assert_snapshot!(generated_that(), @r#"I'm generated! (literal "bar", rule baz)"#); 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)"#);
} }
} }