//! `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, panic::RefUnwindSafe};
+use std::fmt;
use stdx::impl_from;
}
fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usize) -> fmt::Result {
- let align = std::iter::repeat(" ").take(level).collect::<String>();
+ let align = " ".repeat(level);
let aux = match subtree.delimiter.map(|it| (it.kind, it.id.0)) {
None => "$".to_string(),
}
fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize) -> fmt::Result {
- let align = std::iter::repeat(" ").take(level).collect::<String>();
+ let align = " ".repeat(level);
match tkn {
TokenTree::Leaf(leaf) => match leaf {
}
}
+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 last = None;
+ for child in &self.token_trees {
+ 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)]
pub enum ExpansionError {
- IOError(String),
- JsonError(String),
Unknown(String),
ExpansionError(String),
}
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),
}
}
}
-
-pub trait TokenExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
- fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>)
- -> Result<Subtree, ExpansionError>;
-}