#![warn(missing_docs)]
pub use proc_macro2;
use proc_macro2::TokenStream;
pub trait ToTokens {
fn to_tokens(&self, tokens: &mut TokenStream);
}
impl ToTokens for proc_macro2::Ident {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(proc_macro2::TokenTree::Ident(self.clone())));
}
}
impl ToTokens for proc_macro2::Literal {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(proc_macro2::TokenTree::Literal(
self.clone(),
)));
}
}
impl ToTokens for proc_macro2::Group {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(std::iter::once(proc_macro2::TokenTree::Group(self.clone())));
}
}
impl ToTokens for TokenStream {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.clone());
}
}
#[macro_export]
macro_rules! qemit {
() => {
::qemit::proc_macro2::TokenStream::new()
};
(~ $var:ident) => {{
let mut _s = ::proc_macro2::TokenStream::new();
$crate::ToTokens::to_tokens(&$var, &mut _s);
_s
}};
($($tt:tt)*) => {{
let mut _s = ::qemit::proc_macro2::TokenStream::new();
$crate::qemit_each_token!(_s $($tt)*);
_s
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! qemit_each_token {
($tokens:ident $($tts:tt)*) => {
$crate::qemit_tokens_with_context!{ $tokens
(@ @ @ @ @ @ $($tts)* )
(@ @ @ @ @ $($tts)* @ )
(@ @ @ @ $($tts)* @ @ )
(@ @ @ $(($tts))* @ @ @)
(@ @ $($tts)* @ @ @ @ )
(@ $($tts)* @ @ @ @ @)
( $($tts)* @ @ @ @ @ @)
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! qemit_tokens_with_context {
(
$tokens:ident
($($b3:tt)*)
($($b2:tt)*)
($($b1:tt)*)
($($curr:tt)*)
($($a1:tt)*)
($($a2:tt)*)
($($a3:tt)*)
) => {
$(
$crate::__qemit_token_with_context!(
$tokens $b3 $b2 $b1 $curr $a1 $a2 $a3
);
)*
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __qemit_token_with_context {
($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
($tokens:ident $b3:tt $b2:tt $b1:tt (~) $var:ident $a2:tt $a3:tt) => {
$crate::ToTokens::to_tokens(&$var, &mut $tokens);
};
($tokens:ident $b3:tt $b2:tt ~ ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
($tokens:ident $b3:tt $b2:tt $b1:tt ({ $($inner:tt)* }) $a1:tt $a2:tt $a3:tt) => {
let mut inner_ts = ::qemit::proc_macro2::TokenStream::new();
$crate::qemit_each_token!(inner_ts $($inner)*);
$tokens.extend(std::iter::once(::qemit::proc_macro2::TokenTree::Group(
::qemit::proc_macro2::Group::new(::qemit::proc_macro2::Delimiter::Brace, inner_ts)
)));
};
($tokens:ident $b3:tt $b2:tt $b1:tt (( $($inner:tt)* )) $a1:tt $a2:tt $a3:tt) => {
let mut inner_ts = ::qemit::proc_macro2::TokenStream::new();
$crate::qemit_each_token!(inner_ts $($inner)*);
$tokens.extend(std::iter::once(::qemit::proc_macro2::TokenTree::Group(
::qemit::proc_macro2::Group::new(::qemit::proc_macro2::Delimiter::Parenthesis, inner_ts)
)));
};
($tokens:ident $b3:tt $b2:tt $b1:tt ([ $($inner:tt)* ]) $a1:tt $a2:tt $a3:tt) => {
let mut inner_ts = ::qemit::proc_macro2::TokenStream::new();
$crate::qemit_each_token!(inner_ts $($inner)*);
$tokens.extend(std::iter::once(::qemit::proc_macro2::TokenTree::Group(
::qemit::proc_macro2::Group::new(::qemit::proc_macro2::Delimiter::Bracket, inner_ts)
)));
};
($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {{
let text = stringify!($curr);
let frag: ::proc_macro2::TokenStream = text
.parse()
.expect("qemit: failed to re-parse token, this is a bug");
$tokens.extend(frag);
}};
}