Skip to content

Commit

Permalink
Reorganize macro code
Browse files Browse the repository at this point in the history
  • Loading branch information
AZWN committed Nov 23, 2023
1 parent 04e3967 commit 9139389
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 72 deletions.
77 changes: 5 additions & 72 deletions scopegraphs-macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,18 @@
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 {
let input = parse_macro_input!(input as DeriveInput);
impl_label(input)
}

struct RegexInput {
attrs: Vec<Attribute>,
_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<Self> {
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:
///
Expand All @@ -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()
}
79 changes: 79 additions & 0 deletions scopegraphs-macros/src/regex.rs
Original file line number Diff line number Diff line change
@@ -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<Attribute>,
_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<Self> {
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()
}
}

0 comments on commit 9139389

Please sign in to comment.