standalone_syn/
mac.rs

1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use 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    /// A macro invocation: `println!("{}", mac)`.
20    ///
21    /// *This type is available if Syn is built with the `"derive"` or `"full"`
22    /// feature.*
23    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    /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
33    ///
34    /// *This type is available if Syn is built with the `"derive"` or `"full"`
35    /// feature.*
36    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}