diff --git a/Cargo.lock b/Cargo.lock index 93c2900..ad13ad1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,7 @@ dependencies = [ "codepage-437", "insta", "nom", + "peg_macro", "pest", ] @@ -126,6 +127,13 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "peg_macro" +version = "0.1.0" +dependencies = [ + "quote", +] + [[package]] name = "pest" version = "2.8.0" diff --git a/Cargo.toml b/Cargo.toml index ca7c051..0628280 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" [dependencies] anyhow = "1.0.86" codepage-437 = "0.1.0" +peg_macro = { path = "./peg_macro"} insta = "1.39.0" nom = "7.1.3" pest = "2.7.15" @@ -22,3 +23,6 @@ similar.opt-level = 3 [[bin]] name = "zasm" path = "src/main.rs" + +[workspace] +members = [".", "peg_macro"] diff --git a/peg_macro/.gitignore b/peg_macro/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/peg_macro/.gitignore @@ -0,0 +1 @@ +/target diff --git a/peg_macro/Cargo.toml b/peg_macro/Cargo.toml new file mode 100644 index 0000000..5307907 --- /dev/null +++ b/peg_macro/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "peg_macro" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.40" diff --git a/peg_macro/src/lib.rs b/peg_macro/src/lib.rs new file mode 100644 index 0000000..548de23 --- /dev/null +++ b/peg_macro/src/lib.rs @@ -0,0 +1,27 @@ +use proc_macro::TokenStream; +use quote::quote; + +#[proc_macro] +pub fn grammar(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) => { + let s = literal.to_string(); + let c = s.chars().next().unwrap_or('\0'); + match c { + '0'..'9' => { + let val: usize = s.parse().unwrap(); + quote! { Some(crate::peg::Foo::Bar(#val)) } + } + '"' => { + let inner = &s[1..s.len() - 1]; + quote! { Some(crate::peg::Foo::Baz(#inner.into())) } + } + _ => quote! { None }, + } + } + _ => quote! { None }, + }; + + quote! { println!("Hello, world! {:?}", #result); }.into() +} diff --git a/src/main.rs b/src/main.rs index aae65d2..2f9c7f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,20 @@ mod encoding; mod labels; +mod peg; mod preprocess; mod world; use anyhow::anyhow; use labels::labels::print_labels; +use peg_macro::grammar; use preprocess::eval::Context; use std::{env, error::Error, fs, path::PathBuf, process::exit}; use world::World; fn main() -> Result<(), Box> { + grammar!(123); + grammar!("abc"); + let args: Vec = env::args().collect(); if args.len() != 2 { eprintln!("Usage: {} WORLD_FILE", args[0]); diff --git a/src/peg/mod.rs b/src/peg/mod.rs new file mode 100644 index 0000000..ad85da9 --- /dev/null +++ b/src/peg/mod.rs @@ -0,0 +1,3 @@ +pub mod peg; + +pub use peg::*; diff --git a/src/peg/peg.rs b/src/peg/peg.rs new file mode 100644 index 0000000..e081159 --- /dev/null +++ b/src/peg/peg.rs @@ -0,0 +1,6 @@ +#[derive(Debug)] +#[allow(dead_code)] +pub enum Foo { + Bar(usize), + Baz(String), +}