From 913938934f3bfd9cb232a498987d01955fc0ae89 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Thu, 23 Nov 2023 14:06:49 +0100 Subject: [PATCH] Reorganize macro code --- scopegraphs-macros/src/lib.rs | 77 +++----------------------------- scopegraphs-macros/src/regex.rs | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 72 deletions(-) create mode 100644 scopegraphs-macros/src/regex.rs diff --git a/scopegraphs-macros/src/lib.rs b/scopegraphs-macros/src/lib.rs index c2d056d..327c8ab 100644 --- a/scopegraphs-macros/src/lib.rs +++ b/scopegraphs-macros/src/lib.rs @@ -1,17 +1,11 @@ use crate::label::impl_label; -use proc_macro::TokenStream; -use quote::quote_spanned; -use scopegraphs_regular_expressions::Regex; -use syn::parse::{Parse, ParseStream}; -use syn::spanned::Spanned; -use syn::{parse_macro_input, Attribute, DeriveInput, Ident, Meta, Token, Type}; +use crate::regex::RegexInput; -#[cfg(feature = "dot")] -use std::fs::File; -#[cfg(feature = "dot")] -use syn::{Expr, ExprLit, Lit, MetaNameValue}; +use proc_macro::TokenStream; +use syn::{parse_macro_input, DeriveInput}; mod label; +mod regex; #[proc_macro_derive(Label)] pub fn label_derive(input: TokenStream) -> TokenStream { @@ -19,32 +13,6 @@ pub fn label_derive(input: TokenStream) -> TokenStream { impl_label(input) } -struct RegexInput { - attrs: Vec, - _type: Token![type], - name: Ident, - _open: Token![<], - alphabet_type: Type, - _close: Token![>], - _equals: Token![=], - regex: Regex, -} - -impl Parse for RegexInput { - fn parse(input: ParseStream) -> syn::Result { - Ok(Self { - attrs: input.call(Attribute::parse_outer)?, - _type: input.parse()?, - name: input.parse()?, - _open: input.parse()?, - alphabet_type: input.parse()?, - _close: input.parse()?, - _equals: input.parse()?, - regex: input.parse()?, - }) - } -} - /// Syntax: `$attrs type $type<$alphabet_type> = regex`. /// For example: /// @@ -68,40 +36,5 @@ impl Parse for RegexInput { #[proc_macro] pub fn compile_regex(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as RegexInput); - - #[cfg(feature = "dot")] - let mut graph = None; - - for i in input.attrs { - match i.meta { - #[cfg(feature = "dot")] - Meta::NameValue(MetaNameValue { - path, - value: - Expr::Lit(ExprLit { - lit: Lit::Str(s), .. - }), - .. - }) if path.is_ident("graph") => { - graph = Some(s); - } - i => { - return quote_spanned!(i.span() => compile_error!("unexpected attribute");).into(); - } - } - } - - let compiled = input.regex.compile(); - - #[cfg(feature = "dot")] - if let Some(path) = graph { - let path = path.value(); - let mut f = File::create(&path) - .unwrap_or_else(|e| panic!("can't open dot file for graphing at {path}: {e}")); - compiled - .output_dot(&mut f) - .unwrap_or_else(|e| panic!("failed while graphing at {path}: {e}")); - } - - compiled.emit(&input.name, &input.alphabet_type).into() + input.compile() } diff --git a/scopegraphs-macros/src/regex.rs b/scopegraphs-macros/src/regex.rs new file mode 100644 index 0000000..2638555 --- /dev/null +++ b/scopegraphs-macros/src/regex.rs @@ -0,0 +1,79 @@ +use proc_macro::TokenStream; +use quote::quote_spanned; +use scopegraphs_regular_expressions::Regex; +use syn::parse::{Parse, ParseStream}; +use syn::spanned::Spanned; +use syn::{Attribute, Ident, Meta, Token, Type}; + +#[cfg(feature = "dot")] +use std::fs::File; +#[cfg(feature = "dot")] +use syn::{Expr, ExprLit, Lit, MetaNameValue}; + +pub(crate) struct RegexInput { + attrs: Vec, + _type: Token![type], + name: Ident, + _open: Token![<], + alphabet_type: Type, + _close: Token![>], + _equals: Token![=], + regex: Regex, +} + +impl Parse for RegexInput { + fn parse(input: ParseStream) -> syn::Result { + Ok(Self { + attrs: input.call(Attribute::parse_outer)?, + _type: input.parse()?, + name: input.parse()?, + _open: input.parse()?, + alphabet_type: input.parse()?, + _close: input.parse()?, + _equals: input.parse()?, + regex: input.parse()?, + }) + } +} + +impl RegexInput { + pub fn compile(self) -> TokenStream { + #[cfg(feature = "dot")] + let mut graph = None; + + for i in self.attrs { + let attr = i.meta.clone(); + match attr { + #[cfg(feature = "dot")] + Meta::NameValue(MetaNameValue { + path, + value: + Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }), + .. + }) if path.is_ident("graph") => { + graph = Some(s); + } + i => { + return quote_spanned!(i.span() => compile_error!("unexpected attribute");) + .into(); + } + } + } + + let compiled = self.regex.compile(); + + #[cfg(feature = "dot")] + if let Some(path) = graph { + let path = path.value(); + let mut f = File::create(&path) + .unwrap_or_else(|e| panic!("can't open dot file for graphing at {path}: {e}")); + compiled + .output_dot(&mut f) + .unwrap_or_else(|e| panic!("failed while graphing at {path}: {e}")); + } + + compiled.emit(&self.name, &self.alphabet_type).into() + } +}