diff options
author | Melody Horn <melody@boringcactus.com> | 2021-03-31 23:04:09 -0600 |
---|---|---|
committer | Melody Horn <melody@boringcactus.com> | 2021-03-31 23:04:09 -0600 |
commit | 24207feb7726bd2db97693eb8fdd155d33612574 (patch) | |
tree | aa0ee9c2deb20105db7239c2de75593f8b25256f /bird-machine-macros | |
download | bird-machine-24207feb7726bd2db97693eb8fdd155d33612574.tar.gz bird-machine-24207feb7726bd2db97693eb8fdd155d33612574.zip |
basic sketch of general vibe
Diffstat (limited to 'bird-machine-macros')
-rw-r--r-- | bird-machine-macros/Cargo.toml | 15 | ||||
-rw-r--r-- | bird-machine-macros/src/lib.rs | 179 | ||||
-rw-r--r-- | bird-machine-macros/src/nfa.rs | 15 |
3 files changed, 209 insertions, 0 deletions
diff --git a/bird-machine-macros/Cargo.toml b/bird-machine-macros/Cargo.toml new file mode 100644 index 0000000..e45569b --- /dev/null +++ b/bird-machine-macros/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "bird-machine-macros" +version = "0.1.0" +authors = ["boringcactus / Melody Horn <melody@boringcactus.com>"] +description = "proc macros for bird-machine" +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +regex-syntax = "0.6" +proc-macro2 = "1.0" +quote = "1" +syn = "1.0" diff --git a/bird-machine-macros/src/lib.rs b/bird-machine-macros/src/lib.rs new file mode 100644 index 0000000..628ee91 --- /dev/null +++ b/bird-machine-macros/src/lib.rs @@ -0,0 +1,179 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +use syn::{parse_macro_input, DeriveInput, LitStr}; +use quote::{quote, ToTokens}; + +mod nfa; + +#[proc_macro_attribute] +pub fn bird_machine(args: TokenStream, input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let input_regex = parse_macro_input!(args as LitStr); + + let input_type_name = &input.ident; + let input_lifetimes: Vec<_> = input.generics.lifetimes().collect(); + let lifetime = match input_lifetimes.as_slice() { + [] => quote!{ 'unrestricted }, + [lt] => quote!{ #lt }, + _ => panic!("multiple lifetime generics, what is this, pls to halp"), + }; + + let machine = build_machine(&input_regex); + dbg!(&machine); + + let (_, ty_generics, where_clause) = input.generics.split_for_impl(); + + let impl_decl = quote! { + impl<#lifetime> ::bird_machine::Machine<#lifetime> for #input_type_name #ty_generics #where_clause + }; + let original_regex = quote! { + const ORIGINAL_REGEX: &'static str = #input_regex; + }; + let captures = quote! { + fn captures(text: &#lifetime str) -> Option<Self> { + todo!() + } + }; + let captures_iter = quote! { + type CaptureIterator = ::std::iter::Empty<Self>; + fn captures_iter(text: &#lifetime str) -> Self::CaptureIterator { + todo!() + } + }; + let find = quote! { + fn find(text: &#lifetime str) -> Option<::bird_machine::Match<#lifetime>> { + todo!() + } + }; + let find_at = quote! { + fn find_at(text: &#lifetime str, start: usize) -> Option<::bird_machine::Match<#lifetime>> { + todo!() + } + }; + let find_iter = quote! { + type FindIterator = ::std::iter::Empty<::bird_machine::Match<#lifetime>>; + fn find_iter(text: &#lifetime str) -> Self::FindIterator { + todo!() + } + }; + let is_match = quote! { + fn is_match(text: &#lifetime str) -> bool { + todo!() + } + }; + let is_match_at = quote! { + fn is_match_at(text: &#lifetime str, start: usize) -> bool { + todo!() + } + }; + let replace = quote! { + fn replace( + text: &#lifetime str, + rep: impl ::bird_machine::Replacer<#lifetime, Self>, + ) -> ::std::borrow::Cow<#lifetime, str> { + todo!() + } + }; + let replace_all = quote! { + fn replace_all( + text: &#lifetime str, + rep: impl ::bird_machine::Replacer<#lifetime, Self>, + ) -> ::std::borrow::Cow<#lifetime, str> { + todo!() + } + }; + let replacen = quote! { + fn replacen( + text: &#lifetime str, + limit: usize, + rep: impl ::bird_machine::Replacer<#lifetime, Self>, + ) -> ::std::borrow::Cow<#lifetime, str> { + todo!() + } + }; + let split = quote! { + type SplitIterator = ::std::iter::Empty<&#lifetime str>; + fn split(text: &#lifetime str) -> Self::SplitIterator { + todo!() + } + }; + let splitn = quote! { + type SplitNIterator = ::std::iter::Empty<&#lifetime str>; + fn splitn(text: &#lifetime str, limit: usize) -> Self::SplitNIterator { + todo!() + } + }; + + let tokens = quote! { + #input + + #machine + + #impl_decl { + #original_regex + #captures + #captures_iter + #find + #find_at + #find_iter + #is_match + #is_match_at + #replace + #replace_all + #replacen + #split + #splitn + } + }; + + eprintln!( + "{impl_decl} {{\n\n\ + {original_regex}\n\n\ + {captures}\n\n\ + {captures_iter}\n\n\ + {find}\n\n\ + {find_at}\n\n\ + {find_iter}\n\n\ + {is_match}\n\n\ + {is_match_at}\n\n\ + {replace}\n\n\ + {replace_all}\n\n\ + {replacen}\n\n\ + {split}\n\n\ + {splitn}\n\n\ + }}", + impl_decl = impl_decl, + original_regex = original_regex, + captures = captures, + captures_iter = captures_iter, + find = find, + find_at = find_at, + find_iter = find_iter, + is_match = is_match, + is_match_at = is_match_at, + replace = replace, + replace_all = replace_all, + replacen = replacen, + split = split, + splitn = splitn, + ); + + tokens.into() +} + +fn build_machine(regex: &LitStr) -> proc_macro2::TokenStream { + let regex_text = regex.value(); + let regex_ir = regex_syntax::Parser::new() + .parse(®ex_text); + let regex_ir = match regex_ir { + Ok(x) => x, + Err(err ) => panic!("error compiling regex {}: {}", regex.to_token_stream(), err), + }; + dbg!(®ex_ir); + + // shout out to all the professors who've taught me how to do this + let mut built_nfa = nfa::NFA::default(); + + todo!() +} diff --git a/bird-machine-macros/src/nfa.rs b/bird-machine-macros/src/nfa.rs new file mode 100644 index 0000000..b7b3612 --- /dev/null +++ b/bird-machine-macros/src/nfa.rs @@ -0,0 +1,15 @@ +use std::collections::{HashMap, HashSet}; + +#[derive(Default)] +pub struct NFA { + state_count: usize, + transition_table: HashMap<Option<char>, HashSet<usize>>, +} + +impl NFA { + pub fn new_state(&mut self) -> usize { + let result = self.state_count; + self.state_count += 1; + result + } +} |