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"
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",
]
+1
View File
@@ -7,5 +7,6 @@ edition = "2024"
proc-macro = true
[dependencies]
proc-macro2 = "1.0.95"
quote = "1.0.40"
syn = "2.0.101"
+23 -2
View File
@@ -17,8 +17,9 @@ struct Rule {
}
enum Term {
Rule(Ident),
Literal(LitStr),
Rule(Ident),
Sequence(Vec<Term>),
}
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()
}
}
+3 -2
View File
@@ -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)"#);
}
}