//! `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`. macro_rules! impl_froms { ($e:ident: $($v:ident), *) => { $( impl From<$v> for $e { fn from(it: $v) -> $e { $e::$v(it) } } )* } } use std::fmt; use smol_str::SmolStr; /// Represents identity of the token. /// /// For hygiene purposes, we need to track which expanded tokens originated from /// which source tokens. We do it by assigning an distinct identity to each /// source token and making sure that identities are preserved during macro /// expansion. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TokenId(u32, u32); impl TokenId { pub fn new(token_id: u32, map_id: u32) -> TokenId { TokenId(token_id, map_id) } pub const fn unspecified() -> TokenId { TokenId(!0, !0) } pub fn token_id(&self) -> u32 { self.0 } pub fn map_id(&self) -> u32 { self.1 } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum TokenTree { Leaf(Leaf), Subtree(Subtree), } impl_froms!(TokenTree: Leaf, Subtree); #[derive(Debug, Clone, PartialEq, Eq)] pub enum Leaf { Literal(Literal), Punct(Punct), Ident(Ident), } impl_froms!(Leaf: Literal, Punct, Ident); #[derive(Debug, Clone, PartialEq, Eq)] pub struct Subtree { pub delimiter: Delimiter, pub token_trees: Vec, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Delimiter { Parenthesis, Brace, Bracket, None, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Literal { pub text: SmolStr, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Punct { pub char: char, pub spacing: Spacing, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Spacing { Alone, Joint, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Ident { pub text: SmolStr, pub id: TokenId, } impl fmt::Display for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenTree::Leaf(it) => fmt::Display::fmt(it, f), TokenTree::Subtree(it) => fmt::Display::fmt(it, f), } } } impl fmt::Display for Subtree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (l, r) = match self.delimiter { Delimiter::Parenthesis => ("(", ")"), Delimiter::Brace => ("{", "}"), Delimiter::Bracket => ("[", "]"), Delimiter::None => ("", ""), }; f.write_str(l)?; let mut needs_space = false; for tt in self.token_trees.iter() { if needs_space { f.write_str(" ")?; } needs_space = true; match tt { TokenTree::Leaf(Leaf::Punct(p)) => { needs_space = p.spacing == Spacing::Alone; fmt::Display::fmt(p, f)? } tt => fmt::Display::fmt(tt, f)?, } } f.write_str(r)?; Ok(()) } } impl fmt::Display for Leaf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Leaf::Ident(it) => fmt::Display::fmt(it, f), Leaf::Literal(it) => fmt::Display::fmt(it, f), Leaf::Punct(it) => fmt::Display::fmt(it, f), } } } impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.text, f) } } impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.text, f) } } impl fmt::Display for Punct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.char, f) } } impl Subtree { /// Count the number of tokens recursively pub fn count(&self) -> usize { let children_count = self .token_trees .iter() .map(|c| match c { TokenTree::Subtree(c) => c.count(), _ => 0, }) .sum::(); self.token_trees.len() + children_count } } pub mod buffer;