Skip to content
Permalink
Tree: 4e6d2504cf
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
194 lines (176 sloc) 4.22 KB
//! This example demonstrates a tt-call macro for parsing comma-separated
//! applications of an arbitrary given tt-call element. The way it is invoked
//! here, the elements are Rust types parsed by the built-in `parse_type!`
//! macro.
#![recursion_limit = "256"]
extern crate tt_call;
use tt_call::{parse_type, tt_call, tt_return};
/// Parse comma-separated elements.
/// <sup>**[tt-call]**</sup>
///
/// Trailing comma is accepted but optional.
///
/// # Input
///
/// - `parser = [{` the parser macro with which to parse each element `}]`
/// - `input = [{` arbitrary input tokens to parse `}]`
///
/// # Output
///
/// - `element = [{` parsed element (repeated zero or more times) `}]`
///
/// # Example
///
/// ```rust
/// tt_call! {
/// macro = [{ comma_separated }]
/// parser = [{ parse_type }]
/// input = [{
/// std::fs::File,
/// &'a mut str,
/// }]
/// ~~> tt_debug
/// }
/// ```
///
/// ```
/// element = [{ std :: fs :: File }]
/// element = [{ & 'a mut str }]
/// ```
macro_rules! comma_separated {
{
$caller:tt
parser = [{ $parser:ident }]
input = [{ $($input:tt)* }]
} => {
tt_call! {
macro = [{ $parser }]
input = [{ $($input)* }]
~~> private_comma_separated! {
$caller
parser = [{ $parser }]
elements = [{ }]
}
}
};
}
#[doc(hidden)]
macro_rules! private_comma_separated {
// Finished without trailing comma.
{
$caller:tt
parser = [{ $parser:ident }]
elements = [{ $($elements:tt)* }]
$name:ident = [{ $($current:tt)* }]
rest = [{ }]
} => {
tt_return! {
$caller
$($elements)*
element = [{ $($current)* }]
}
};
// Finished after ignoring trailing comma.
{
$caller:tt
parser = [{ $parser:ident }]
elements = [{ $($elements:tt)* }]
$name:ident = [{ $($current:tt)* }]
rest = [{ , }]
} => {
tt_return! {
$caller
$($elements)*
element = [{ $($current)* }]
}
};
// Parse next element after comma.
{
$caller:tt
parser = [{ $parser:ident }]
elements = [{ $($elements:tt)* }]
$name:ident = [{ $($current:tt)* }]
rest = [{ , $($rest:tt)+ }]
} => {
tt_call! {
macro = [{ $parser }]
input = [{ $($rest)* }]
~~> private_comma_separated! {
$caller
parser = [{ $parser }]
elements = [{
$($elements)*
element = [{ $($current)* }]
}]
}
}
};
}
/// Parses a comma-separated sequence of Rust types and expands to a `&'static
/// [&'static str]` containing a basic mangled name for each input type.
macro_rules! mangle_type_names {
($($input:tt)*) => {
tt_call! {
macro = [{ comma_separated }]
parser = [{ parse_type }]
input = [{ $($input)* }]
~~> private_mangle_type_names
}
};
}
#[doc(hidden)]
macro_rules! private_mangle_type_names {
{
$(
element = [{ $($element:tt)* }]
)*
} => {
&[
$(
concat!(
$(
mangle_token!($element),
)*
),
)*
]
};
}
#[doc(hidden)]
macro_rules! mangle_token {
($ident:ident) => {
concat!("_", stringify!($ident))
};
(&) => {
"_ref"
};
(->) => {
"_to"
};
(($($parenthesized:tt)*)) => {
concat!(
$(
mangle_token!($parenthesized),
)*
)
};
/* more sorts of tokens may be handled here if necessary */
($other:tt) => {
""
};
}
fn main() {
static MANGLED: &[&str] = mangle_type_names! {
std::fs::File,
&'a mut str,
impl Display,
fn(s: &str) -> String,
};
assert_eq!(MANGLED, [
"_std_fs_File",
"_ref_mut_str",
"_impl_Display",
"_fn_s_ref_str_to_String",
]);
println!("{:#?}", MANGLED);
}
You can’t perform that action at this time.