• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! `tt` crate defines a `TokenTree` data structure: this is the interface (both
2 //! input and output) of macros. It closely mirrors `proc_macro` crate's
3 //! `TokenTree`.
4 
5 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
6 
7 use std::fmt;
8 
9 use stdx::impl_from;
10 
11 pub use smol_str::SmolStr;
12 
13 /// Represents identity of the token.
14 ///
15 /// For hygiene purposes, we need to track which expanded tokens originated from
16 /// which source tokens. We do it by assigning an distinct identity to each
17 /// source token and making sure that identities are preserved during macro
18 /// expansion.
19 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
20 pub struct TokenId(pub u32);
21 
22 impl fmt::Debug for TokenId {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result23     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24         self.0.fmt(f)
25     }
26 }
27 
28 impl TokenId {
29     pub const UNSPECIFIED: TokenId = TokenId(!0);
unspecified() -> TokenId30     pub const fn unspecified() -> TokenId {
31         Self::UNSPECIFIED
32     }
33 }
34 
35 pub mod token_id {
36     pub use crate::{DelimiterKind, Spacing, TokenId};
37     pub type Span = crate::TokenId;
38     pub type Subtree = crate::Subtree<Span>;
39     pub type Punct = crate::Punct<Span>;
40     pub type Delimiter = crate::Delimiter<Span>;
41     pub type Leaf = crate::Leaf<Span>;
42     pub type Ident = crate::Ident<Span>;
43     pub type Literal = crate::Literal<Span>;
44     pub type TokenTree = crate::TokenTree<Span>;
45     pub mod buffer {
46         pub type TokenBuffer<'a> = crate::buffer::TokenBuffer<'a, super::Span>;
47         pub type Cursor<'a> = crate::buffer::Cursor<'a, super::Span>;
48         pub type TokenTreeRef<'a> = crate::buffer::TokenTreeRef<'a, super::Span>;
49     }
50 
51     impl Delimiter {
52         pub const UNSPECIFIED: Self = Self {
53             open: TokenId::UNSPECIFIED,
54             close: TokenId::UNSPECIFIED,
55             kind: DelimiterKind::Invisible,
56         };
unspecified() -> Self57         pub const fn unspecified() -> Self {
58             Self::UNSPECIFIED
59         }
60     }
61     impl Subtree {
empty() -> Self62         pub const fn empty() -> Self {
63             Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] }
64         }
65     }
66     impl TokenTree {
empty() -> Self67         pub const fn empty() -> Self {
68             Self::Subtree(Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] })
69         }
70     }
71 }
72 
73 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74 pub struct SyntaxContext(pub u32);
75 
76 // #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
77 // pub struct Span {
78 //     pub id: TokenId,
79 //     pub ctx: SyntaxContext,
80 // }
81 // pub type Span = (TokenId, SyntaxContext);
82 
83 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
84 pub enum TokenTree<Span> {
85     Leaf(Leaf<Span>),
86     Subtree(Subtree<Span>),
87 }
88 impl_from!(Leaf<Span>, Subtree<Span> for TokenTree);
89 
90 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
91 pub enum Leaf<Span> {
92     Literal(Literal<Span>),
93     Punct(Punct<Span>),
94     Ident(Ident<Span>),
95 }
96 
97 impl<Span> Leaf<Span> {
span(&self) -> &Span98     pub fn span(&self) -> &Span {
99         match self {
100             Leaf::Literal(it) => &it.span,
101             Leaf::Punct(it) => &it.span,
102             Leaf::Ident(it) => &it.span,
103         }
104     }
105 }
106 impl_from!(Literal<Span>, Punct<Span>, Ident<Span> for Leaf);
107 
108 #[derive(Clone, PartialEq, Eq, Hash)]
109 pub struct Subtree<Span> {
110     // FIXME, this should not be Option
111     pub delimiter: Delimiter<Span>,
112     pub token_trees: Vec<TokenTree<Span>>,
113 }
114 
115 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
116 pub struct Delimiter<Span> {
117     pub open: Span,
118     pub close: Span,
119     pub kind: DelimiterKind,
120 }
121 
122 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
123 pub enum DelimiterKind {
124     Parenthesis,
125     Brace,
126     Bracket,
127     Invisible,
128 }
129 
130 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
131 pub struct Literal<Span> {
132     pub text: SmolStr,
133     pub span: Span,
134 }
135 
136 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
137 pub struct Punct<Span> {
138     pub char: char,
139     pub spacing: Spacing,
140     pub span: Span,
141 }
142 
143 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144 pub enum Spacing {
145     Alone,
146     Joint,
147 }
148 
149 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
150 /// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
151 pub struct Ident<Span> {
152     pub text: SmolStr,
153     pub span: Span,
154 }
155 
156 impl<S> Ident<S> {
new(text: impl Into<SmolStr>, span: S) -> Self157     pub fn new(text: impl Into<SmolStr>, span: S) -> Self {
158         Ident { text: text.into(), span }
159     }
160 }
161 
print_debug_subtree<Span: fmt::Debug>( f: &mut fmt::Formatter<'_>, subtree: &Subtree<Span>, level: usize, ) -> fmt::Result162 fn print_debug_subtree<Span: fmt::Debug>(
163     f: &mut fmt::Formatter<'_>,
164     subtree: &Subtree<Span>,
165     level: usize,
166 ) -> fmt::Result {
167     let align = "  ".repeat(level);
168 
169     let Delimiter { kind, open, close } = &subtree.delimiter;
170     let aux = match kind {
171         DelimiterKind::Invisible => format!("$$ {:?} {:?}", open, close),
172         DelimiterKind::Parenthesis => format!("() {:?} {:?}", open, close),
173         DelimiterKind::Brace => format!("{{}} {:?} {:?}", open, close),
174         DelimiterKind::Bracket => format!("[] {:?} {:?}", open, close),
175     };
176 
177     if subtree.token_trees.is_empty() {
178         write!(f, "{align}SUBTREE {aux}")?;
179     } else {
180         writeln!(f, "{align}SUBTREE {aux}")?;
181         for (idx, child) in subtree.token_trees.iter().enumerate() {
182             print_debug_token(f, child, level + 1)?;
183             if idx != subtree.token_trees.len() - 1 {
184                 writeln!(f)?;
185             }
186         }
187     }
188 
189     Ok(())
190 }
191 
print_debug_token<Span: fmt::Debug>( f: &mut fmt::Formatter<'_>, tkn: &TokenTree<Span>, level: usize, ) -> fmt::Result192 fn print_debug_token<Span: fmt::Debug>(
193     f: &mut fmt::Formatter<'_>,
194     tkn: &TokenTree<Span>,
195     level: usize,
196 ) -> fmt::Result {
197     let align = "  ".repeat(level);
198 
199     match tkn {
200         TokenTree::Leaf(leaf) => match leaf {
201             Leaf::Literal(lit) => write!(f, "{}LITERAL {} {:?}", align, lit.text, lit.span)?,
202             Leaf::Punct(punct) => write!(
203                 f,
204                 "{}PUNCH   {} [{}] {:?}",
205                 align,
206                 punct.char,
207                 if punct.spacing == Spacing::Alone { "alone" } else { "joint" },
208                 punct.span
209             )?,
210             Leaf::Ident(ident) => write!(f, "{}IDENT   {} {:?}", align, ident.text, ident.span)?,
211         },
212         TokenTree::Subtree(subtree) => {
213             print_debug_subtree(f, subtree, level)?;
214         }
215     }
216 
217     Ok(())
218 }
219 
220 impl<Span: fmt::Debug> fmt::Debug for Subtree<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result221     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222         print_debug_subtree(f, self, 0)
223     }
224 }
225 
226 impl<Span> fmt::Display for TokenTree<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result227     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228         match self {
229             TokenTree::Leaf(it) => fmt::Display::fmt(it, f),
230             TokenTree::Subtree(it) => fmt::Display::fmt(it, f),
231         }
232     }
233 }
234 
235 impl<Span> fmt::Display for Subtree<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result236     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237         let (l, r) = match self.delimiter.kind {
238             DelimiterKind::Parenthesis => ("(", ")"),
239             DelimiterKind::Brace => ("{", "}"),
240             DelimiterKind::Bracket => ("[", "]"),
241             DelimiterKind::Invisible => ("", ""),
242         };
243         f.write_str(l)?;
244         let mut needs_space = false;
245         for tt in &self.token_trees {
246             if needs_space {
247                 f.write_str(" ")?;
248             }
249             needs_space = true;
250             match tt {
251                 TokenTree::Leaf(Leaf::Punct(p)) => {
252                     needs_space = p.spacing == Spacing::Alone;
253                     fmt::Display::fmt(p, f)?;
254                 }
255                 tt => fmt::Display::fmt(tt, f)?,
256             }
257         }
258         f.write_str(r)?;
259         Ok(())
260     }
261 }
262 
263 impl<Span> fmt::Display for Leaf<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result264     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265         match self {
266             Leaf::Ident(it) => fmt::Display::fmt(it, f),
267             Leaf::Literal(it) => fmt::Display::fmt(it, f),
268             Leaf::Punct(it) => fmt::Display::fmt(it, f),
269         }
270     }
271 }
272 
273 impl<Span> fmt::Display for Ident<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result274     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275         fmt::Display::fmt(&self.text, f)
276     }
277 }
278 
279 impl<Span> fmt::Display for Literal<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result280     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281         fmt::Display::fmt(&self.text, f)
282     }
283 }
284 
285 impl<Span> fmt::Display for Punct<Span> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result286     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287         fmt::Display::fmt(&self.char, f)
288     }
289 }
290 
291 impl<Span> Subtree<Span> {
292     /// Count the number of tokens recursively
count(&self) -> usize293     pub fn count(&self) -> usize {
294         let children_count = self
295             .token_trees
296             .iter()
297             .map(|c| match c {
298                 TokenTree::Subtree(c) => c.count(),
299                 TokenTree::Leaf(_) => 0,
300             })
301             .sum::<usize>();
302 
303         self.token_trees.len() + children_count
304     }
305 }
306 
307 impl<Span> Subtree<Span> {
308     /// A simple line string used for debugging
as_debug_string(&self) -> String309     pub fn as_debug_string(&self) -> String {
310         let delim = match self.delimiter.kind {
311             DelimiterKind::Brace => ("{", "}"),
312             DelimiterKind::Bracket => ("[", "]"),
313             DelimiterKind::Parenthesis => ("(", ")"),
314             DelimiterKind::Invisible => ("$", "$"),
315         };
316 
317         let mut res = String::new();
318         res.push_str(delim.0);
319         let mut last = None;
320         for child in &self.token_trees {
321             let s = match child {
322                 TokenTree::Leaf(it) => {
323                     let s = match it {
324                         Leaf::Literal(it) => it.text.to_string(),
325                         Leaf::Punct(it) => it.char.to_string(),
326                         Leaf::Ident(it) => it.text.to_string(),
327                     };
328                     match (it, last) {
329                         (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
330                             " ".to_string() + &s
331                         }
332                         (Leaf::Punct(_), Some(TokenTree::Leaf(Leaf::Punct(punct)))) => {
333                             if punct.spacing == Spacing::Alone {
334                                 " ".to_string() + &s
335                             } else {
336                                 s
337                             }
338                         }
339                         _ => s,
340                     }
341                 }
342                 TokenTree::Subtree(it) => it.as_debug_string(),
343             };
344             res.push_str(&s);
345             last = Some(child);
346         }
347 
348         res.push_str(delim.1);
349         res
350     }
351 }
352 
353 pub mod buffer;
354 
pretty<Span>(tkns: &[TokenTree<Span>]) -> String355 pub fn pretty<Span>(tkns: &[TokenTree<Span>]) -> String {
356     fn tokentree_to_text<Span>(tkn: &TokenTree<Span>) -> String {
357         match tkn {
358             TokenTree::Leaf(Leaf::Ident(ident)) => ident.text.clone().into(),
359             TokenTree::Leaf(Leaf::Literal(literal)) => literal.text.clone().into(),
360             TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char),
361             TokenTree::Subtree(subtree) => {
362                 let content = pretty(&subtree.token_trees);
363                 let (open, close) = match subtree.delimiter.kind {
364                     DelimiterKind::Brace => ("{", "}"),
365                     DelimiterKind::Bracket => ("[", "]"),
366                     DelimiterKind::Parenthesis => ("(", ")"),
367                     DelimiterKind::Invisible => ("", ""),
368                 };
369                 format!("{open}{content}{close}")
370             }
371         }
372     }
373 
374     tkns.iter()
375         .fold((String::new(), true), |(last, last_to_joint), tkn| {
376             let s = [last, tokentree_to_text(tkn)].join(if last_to_joint { "" } else { " " });
377             let mut is_joint = false;
378             if let TokenTree::Leaf(Leaf::Punct(punct)) = tkn {
379                 if punct.spacing == Spacing::Joint {
380                     is_joint = true;
381                 }
382             }
383             (s, is_joint)
384         })
385         .0
386 }
387