diff --git a/Chapter09/Cargo.toml b/Chapter09/Cargo.toml index 9ac979d..bd377eb 100644 --- a/Chapter09/Cargo.toml +++ b/Chapter09/Cargo.toml @@ -8,6 +8,7 @@ rand = "0.4.2" requests = "0.0.30" rusty-machine = "0.5.4" procmacro = { path = "procmacro" } +procmacro2 = { path = "procmacro2" } [[bin]] name = "performance_release_mode" @@ -96,3 +97,7 @@ path = "metaprogramming_ebnf.rs" [[bin]] name = "metaprogramming_procmacro" path = "metaprogramming_procmacro.rs" + +[[bin]] +name = "metaprogramming_procmacro2" +path = "metaprogramming_procmacro2.rs" diff --git a/Chapter09/metaprogramming_procmacro2.rs b/Chapter09/metaprogramming_procmacro2.rs new file mode 100644 index 0000000..577724d --- /dev/null +++ b/Chapter09/metaprogramming_procmacro2.rs @@ -0,0 +1,9 @@ +#![feature(proc_macro_non_items)] +#![feature(use_extern_macros)] +extern crate procmacro2; + +fn main() { + procmacro2::misc_syntax!( + where while abcd : u64 >> 1 + 2 * 3; where T: 'x + A;[M];A::f + ); +} diff --git a/Chapter09/procmacro2/.gitignore b/Chapter09/procmacro2/.gitignore new file mode 100644 index 0000000..fa8d85a --- /dev/null +++ b/Chapter09/procmacro2/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target diff --git a/Chapter09/procmacro2/Cargo.toml b/Chapter09/procmacro2/Cargo.toml new file mode 100644 index 0000000..e5ca0af --- /dev/null +++ b/Chapter09/procmacro2/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "procmacro2" +version = "1.0.0" + +[dependencies] +syn = "0.12" +quote = "0.4" + +[lib] +proc-macro = true diff --git a/Chapter09/procmacro2/src/lib.rs b/Chapter09/procmacro2/src/lib.rs new file mode 100644 index 0000000..36d4f60 --- /dev/null +++ b/Chapter09/procmacro2/src/lib.rs @@ -0,0 +1,48 @@ +#![feature(proc_macro)] +#![crate_type = "proc-macro"] +extern crate proc_macro; +#[macro_use] extern crate syn; +#[macro_use] extern crate quote; + +use proc_macro::TokenStream; +use syn::{Ident, Type, Expr, WhereClause, TypeSlice, Path}; +use syn::synom::Synom; + +struct MiscSyntax { + id: Ident, + ty: Type, + expr: Expr, + where_clause: WhereClause, + type_slice: TypeSlice, + path: Path +} + +impl Synom for MiscSyntax { + named!(parse -> Self, do_parse!( + keyword!(where) >> + keyword!(while) >> + id: syn!(Ident) >> + punct!(:) >> + ty: syn!(Type) >> + punct!(>>) >> + expr: syn!(Expr) >> + punct!(;) >> + where_clause: syn!(WhereClause) >> + punct!(;) >> + type_slice: syn!(TypeSlice) >> + punct!(;) >> + path: syn!(Path) >> + (MiscSyntax { id, ty, expr, where_clause, type_slice, path }) + )); +} + +#[proc_macro] +pub fn misc_syntax(input: TokenStream) -> TokenStream { + let m: MiscSyntax = syn::parse(input).expect("expected Miscellaneous Syntax"); + let MiscSyntax { id, ty, expr, where_clause, type_slice, path } = m; + + (quote! { + let #id: #ty = #expr; + println!("variable = {}", #id); + }).into() +}