//! `tt` crate defines a `TokenTree` data structure: this is the interface (both
//! input and output) of macros. It closely mirrors `proc_macro` crate's
//! `TokenTree`.
-use std::{
- fmt::{self, Debug},
- panic::RefUnwindSafe,
-};
+use std::fmt;
use stdx::impl_from;
Ok(())
}
-impl Debug for Subtree {
+impl fmt::Debug for Subtree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
print_debug_subtree(f, self, 0)
}
}
}
+impl Subtree {
+ /// A simple line string used for debugging
+ pub fn as_debug_string(&self) -> String {
+ let delim = match self.delimiter_kind() {
+ Some(DelimiterKind::Brace) => ("{", "}"),
+ Some(DelimiterKind::Bracket) => ("[", "]"),
+ Some(DelimiterKind::Parenthesis) => ("(", ")"),
+ None => (" ", " "),
+ };
+
+ let mut res = String::new();
+ res.push_str(delim.0);
+ let mut iter = self.token_trees.iter();
+ let mut last = None;
+ while let Some(child) = iter.next() {
+ let s = match child {
+ TokenTree::Leaf(it) => {
+ let s = match it {
+ Leaf::Literal(it) => it.text.to_string(),
+ Leaf::Punct(it) => it.char.to_string(),
+ Leaf::Ident(it) => it.text.to_string(),
+ };
+ match (it, last) {
+ (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
+ " ".to_string() + &s
+ }
+ (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => {
+ if punct.spacing == Spacing::Alone {
+ " ".to_string() + &s
+ } else {
+ s
+ }
+ }
+ _ => s,
+ }
+ }
+ TokenTree::Subtree(it) => it.as_debug_string(),
+ };
+ res.push_str(&s);
+ last = Some(child);
+ }
+
+ res.push_str(delim.1);
+ res
+ }
+}
+
pub mod buffer;
#[derive(Debug, PartialEq, Eq, Clone)]
ExpansionError(String),
}
-pub trait TokenExpander: Debug + Send + Sync + RefUnwindSafe {
- fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>)
- -> Result<Subtree, ExpansionError>;
+impl fmt::Display for ExpansionError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ ExpansionError::IOError(e) => write!(f, "I/O error: {}", e),
+ ExpansionError::JsonError(e) => write!(f, "JSON decoding error: {}", e),
+ ExpansionError::Unknown(e) => e.fmt(f),
+ ExpansionError::ExpansionError(e) => write!(f, "proc macro returned error: {}", e),
+ }
+ }
}