1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
extern crate proc_macro2;
use proc_macro2::{
Delimiter, Ident, Literal, Punct, Span, TokenStream, TokenTree,
};
#[derive(Clone, Debug)]
pub enum FlatToken {
Delim(char, Span),
Ident(Ident),
Punct(Punct),
Literal(Literal),
}
impl FlatToken {
pub fn span(&self) -> Span {
match self {
&FlatToken::Delim(_, span) => span,
FlatToken::Ident(tt) => tt.span(),
FlatToken::Punct(tt) => tt.span(),
FlatToken::Literal(tt) => tt.span(),
}
}
}
fn explicit_delimiters(delim: Delimiter) -> Option<(char, char)> {
match delim {
Delimiter::Parenthesis => Some(('(', ')')),
Delimiter::Brace => Some(('{', '}')),
Delimiter::Bracket => Some(('[', ']')),
Delimiter::None => None
}
}
pub fn flatten(stream: TokenStream, out: &mut Vec<FlatToken>) {
for tt in stream {
let flat = match tt {
TokenTree::Group(tt) => {
let stream = tt.stream();
let spans = (tt.span_open(), tt.span_close());
let delimiters = explicit_delimiters(tt.delimiter());
if let Some((open, _)) = delimiters {
out.push(FlatToken::Delim(open, spans.0));
}
flatten(stream, out);
if let Some((_, close)) = delimiters {
FlatToken::Delim(close, spans.1)
} else {
continue;
}
}
TokenTree::Ident(tt) => FlatToken::Ident(tt),
TokenTree::Punct(tt) => FlatToken::Punct(tt),
TokenTree::Literal(tt) => FlatToken::Literal(tt),
};
out.push(flat);
}
}