1use super::*;
10use proc_macro2::TokenStream;
11use token::{Brace, Bracket, Paren};
12
13#[cfg(feature = "extra-traits")]
14use std::hash::{Hash, Hasher};
15#[cfg(feature = "extra-traits")]
16use tt::TokenStreamHelper;
17
18ast_struct! {
19 pub struct Macro #manual_extra_traits {
24 pub path: Path,
25 pub bang_token: Token![!],
26 pub delimiter: MacroDelimiter,
27 pub tts: TokenStream,
28 }
29}
30
31ast_enum! {
32 pub enum MacroDelimiter {
37 Paren(Paren),
38 Brace(Brace),
39 Bracket(Bracket),
40 }
41}
42
43#[cfg(feature = "extra-traits")]
44impl Eq for Macro {}
45
46#[cfg(feature = "extra-traits")]
47impl PartialEq for Macro {
48 fn eq(&self, other: &Self) -> bool {
49 self.path == other.path && self.bang_token == other.bang_token
50 && self.delimiter == other.delimiter
51 && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
52 }
53}
54
55#[cfg(feature = "extra-traits")]
56impl Hash for Macro {
57 fn hash<H>(&self, state: &mut H)
58 where
59 H: Hasher,
60 {
61 self.path.hash(state);
62 self.bang_token.hash(state);
63 self.delimiter.hash(state);
64 TokenStreamHelper(&self.tts).hash(state);
65 }
66}
67
68#[cfg(feature = "parsing")]
69pub mod parsing {
70 use super::*;
71
72 use synom::Synom;
73
74 impl Synom for Macro {
75 named!(parse -> Self, do_parse!(
76 what: call!(Path::parse_mod_style) >>
77 bang: punct!(!) >>
78 body: call!(tt::delimited) >>
79 (Macro {
80 path: what,
81 bang_token: bang,
82 delimiter: body.0,
83 tts: body.1,
84 })
85 ));
86
87 fn description() -> Option<&'static str> {
88 Some("macro invocation")
89 }
90 }
91}
92
93#[cfg(feature = "printing")]
94mod printing {
95 use super::*;
96 use quote::{ToTokens, Tokens};
97
98 impl ToTokens for Macro {
99 fn to_tokens(&self, tokens: &mut Tokens) {
100 self.path.to_tokens(tokens);
101 self.bang_token.to_tokens(tokens);
102 match self.delimiter {
103 MacroDelimiter::Paren(ref paren) => {
104 paren.surround(tokens, |tokens| self.tts.to_tokens(tokens));
105 }
106 MacroDelimiter::Brace(ref brace) => {
107 brace.surround(tokens, |tokens| self.tts.to_tokens(tokens));
108 }
109 MacroDelimiter::Bracket(ref bracket) => {
110 bracket.surround(tokens, |tokens| self.tts.to_tokens(tokens));
111 }
112 }
113 }
114 }
115}