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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use super::*;
use proc_macro2::TokenStream;
use token::{Brace, Bracket, Paren};
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
#[cfg(feature = "extra-traits")]
use tt::TokenStreamHelper;
ast_struct! {
pub struct Macro #manual_extra_traits {
pub path: Path,
pub bang_token: Token![!],
pub delimiter: MacroDelimiter,
pub tts: TokenStream,
}
}
ast_enum! {
pub enum MacroDelimiter {
Paren(Paren),
Brace(Brace),
Bracket(Bracket),
}
}
#[cfg(feature = "extra-traits")]
impl Eq for Macro {}
#[cfg(feature = "extra-traits")]
impl PartialEq for Macro {
fn eq(&self, other: &Self) -> bool {
self.path == other.path
&& self.bang_token == other.bang_token
&& self.delimiter == other.delimiter
&& TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
}
}
#[cfg(feature = "extra-traits")]
impl Hash for Macro {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.path.hash(state);
self.bang_token.hash(state);
self.delimiter.hash(state);
TokenStreamHelper(&self.tts).hash(state);
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use synom::Synom;
impl Synom for Macro {
named!(parse -> Self, do_parse!(
what: call!(Path::parse_mod_style) >>
bang: punct!(!) >>
body: call!(tt::delimited) >>
(Macro {
path: what,
bang_token: bang,
delimiter: body.0,
tts: body.1,
})
));
fn description() -> Option<&'static str> {
Some("macro invocation")
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::TokenStream;
use quote::ToTokens;
impl ToTokens for Macro {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.bang_token.to_tokens(tokens);
match self.delimiter {
MacroDelimiter::Paren(ref paren) => {
paren.surround(tokens, |tokens| self.tts.to_tokens(tokens));
}
MacroDelimiter::Brace(ref brace) => {
brace.surround(tokens, |tokens| self.tts.to_tokens(tokens));
}
MacroDelimiter::Bracket(ref bracket) => {
bracket.surround(tokens, |tokens| self.tts.to_tokens(tokens));
}
}
}
}
}