#![doc = include_str!("../README.md")]
#[allow(clippy::wildcard_imports)]
use unsynn::*;
mod expand;
mod xmacro;
mod xtoken;
use crate::xmacro::{XMacro, XMacroItem};
pub fn xmacro_expand(input: TokenStream) -> Result<TokenStream> {
let xtokens = XMacro::parse_all(&mut input.into_token_iter())?.expand();
let mut output = TokenStream::new();
output.extend(xtokens.into_iter().map(|xtoken| xtoken.to_token_stream()));
Ok(output)
}
pub fn xmacro_expand_items(input: TokenStream) -> Result<TokenStream> {
let mut input = input.into_token_iter();
let mut output = TokenStream::new();
while Except::<EndOfStream>::parse(&mut input).is_ok() {
let xtokens = XMacroItem::parse(&mut input)?.0.expand();
output.extend(xtokens.map(|xtoken| xtoken.to_token_stream()));
}
Ok(output)
}
#[doc(hidden)] #[macro_export]
macro_rules! xpand {
($($in:tt)*) => {
xmacro_lib::xmacro_expand(stringify!{ $($in)* }.to_token_stream()).unwrap().tokens_to_string()
}
}
#[doc(hidden)] #[macro_export]
macro_rules! xpect {
($($out:tt)*) => {
stringify!{ $($out)* }.tokens_to_string()
}
}
#[doc(hidden)] #[macro_export]
macro_rules! CHECK_EXPAND {
($($explanation:literal)? {$($in:tt)*} == {$($out:tt)*}) => {
{
use unsynn::ToTokens;
use xmacro_lib::*;
assert_eq!(
xpand!($($in)*),
xpect!($($out)*)
$(, $explanation)?
);
};
};
}
#[doc(hidden)] #[macro_export]
macro_rules! doctest_ignore {
($($tt:tt)*) => {};
}