mod args;
mod regex_code;
use {
crate::{
args::*,
regex_code::*,
},
proc_macro::TokenStream,
quote::quote,
syn::parse_macro_input,
};
#[proc_macro]
pub fn regex(input: TokenStream) -> TokenStream {
let lit_str = syn::parse::<syn::LitStr>(input).unwrap();
let regex_build = RegexCode::from(lit_str).build;
let q = quote! {{
static RE: lazy_regex::Lazy<lazy_regex::Regex> = #regex_build;
&RE
}};
q.into()
}
#[proc_macro]
pub fn lazy_regex(input: TokenStream) -> TokenStream {
let lit_str = syn::parse::<syn::LitStr>(input).unwrap();
let regex_build = RegexCode::from(lit_str).build;
regex_build.into()
}
#[proc_macro]
pub fn regex_is_match(input: TokenStream) -> TokenStream {
let regex_and_expr_args = parse_macro_input!(input as RexValArgs);
let regex_build = RegexCode::from(regex_and_expr_args.regex_str).build;
let value = regex_and_expr_args.value;
let q = quote! {{
static RE: lazy_regex::Lazy<lazy_regex::Regex> = #regex_build;
RE.is_match(#value)
}};
q.into()
}
#[proc_macro]
pub fn regex_find(input: TokenStream) -> TokenStream {
let regex_and_expr_args = parse_macro_input!(input as RexValArgs);
let regex_code = RegexCode::from(regex_and_expr_args.regex_str);
let regex_build = regex_code.build;
let value = regex_and_expr_args.value;
let q = quote! {{
static RE: lazy_regex::Lazy<lazy_regex::Regex> = #regex_build;
RE.find(#value).map(|mat| mat.as_str())
}};
q.into()
}
#[proc_macro]
pub fn regex_captures(input: TokenStream) -> TokenStream {
let regex_and_expr_args = parse_macro_input!(input as RexValArgs);
let regex_code = RegexCode::from(regex_and_expr_args.regex_str);
let regex_build = regex_code.build;
let value = regex_and_expr_args.value;
let n = regex_code.regex.captures_len();
let groups = (0..n).map(|i| {
quote! {
caps.get(#i).map_or("", |c| c.as_str())
}
});
let q = quote! {{
static RE: lazy_regex::Lazy<lazy_regex::Regex> = #regex_build;
RE.captures(#value)
.map(|caps| (
#(#groups),*
))
}};
q.into()
}
fn replacen(input: TokenStream, limit: usize) -> TokenStream {
let args = parse_macro_input!(input as RexValFunArgs);
let regex_code = RegexCode::from(args.regex_str);
let regex_build = regex_code.build;
let value = args.value;
let fun = args.fun;
let n = regex_code.regex.captures_len();
let groups = (0..n).map(|i| {
quote! {
caps.get(#i).map_or("", |c| c.as_str())
}
});
let q = quote! {{
static RE: lazy_regex::Lazy<lazy_regex::Regex> = #regex_build;
RE.replacen(
#value,
#limit,
|caps: &lazy_regex::Captures<'_>| {
let fun = #fun;
fun(
#(#groups),*
)
})
}};
q.into()
}
#[proc_macro]
pub fn regex_replace(input: TokenStream) -> TokenStream {
replacen(input, 1)
}
#[proc_macro]
pub fn regex_replace_all(input: TokenStream) -> TokenStream {
replacen(input, 0)
}