blob: a486d7c9b34673c763290091518544724a8eb3cd [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// 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
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnayab919512017-12-30 23:31:51 -050010use proc_macro2::TokenStream;
David Tolnay61037c62018-01-05 16:21:03 -080011use token::{Brace, Bracket, Paren};
David Tolnay9c76bcb2017-12-26 23:14:59 -050012
13#[cfg(feature = "extra-traits")]
14use std::hash::{Hash, Hasher};
David Tolnayc43b44e2017-12-30 23:55:54 -050015#[cfg(feature = "extra-traits")]
16use tt::TokenStreamHelper;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070017
Alex Crichton62a0a592017-05-22 13:58:53 -070018ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -080019 /// A macro invocation: `println!("{}", mac)`.
David Tolnay461d98e2018-01-07 11:07:19 -080020 ///
21 /// *This type is available if Syn is built with the `"derive"` or `"full"`
22 /// feature.*
David Tolnay9c76bcb2017-12-26 23:14:59 -050023 pub struct Macro #manual_extra_traits {
Alex Crichton62a0a592017-05-22 13:58:53 -070024 pub path: Path,
David Tolnayf8db7ba2017-11-11 22:52:16 -080025 pub bang_token: Token![!],
David Tolnayab919512017-12-30 23:31:51 -050026 pub delimiter: MacroDelimiter,
27 pub tts: TokenStream,
28 }
29}
30
31ast_enum! {
David Tolnay05658502018-01-07 09:56:37 -080032 /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
David Tolnay461d98e2018-01-07 11:07:19 -080033 ///
34 /// *This type is available if Syn is built with the `"derive"` or `"full"`
35 /// feature.*
David Tolnayab919512017-12-30 23:31:51 -050036 pub enum MacroDelimiter {
David Tolnayab919512017-12-30 23:31:51 -050037 Paren(Paren),
David Tolnayab919512017-12-30 23:31:51 -050038 Brace(Brace),
David Tolnayab919512017-12-30 23:31:51 -050039 Bracket(Bracket),
Alex Crichton62a0a592017-05-22 13:58:53 -070040 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070041}
42
David Tolnay9c76bcb2017-12-26 23:14:59 -050043#[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 {
David Tolnay51382052017-12-27 13:46:21 -050049 self.path == other.path && self.bang_token == other.bang_token
David Tolnayab919512017-12-30 23:31:51 -050050 && self.delimiter == other.delimiter
51 && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
David Tolnay9c76bcb2017-12-26 23:14:59 -050052 }
53}
54
55#[cfg(feature = "extra-traits")]
56impl Hash for Macro {
57 fn hash<H>(&self, state: &mut H)
David Tolnay51382052017-12-27 13:46:21 -050058 where
59 H: Hasher,
David Tolnay9c76bcb2017-12-26 23:14:59 -050060 {
61 self.path.hash(state);
62 self.bang_token.hash(state);
David Tolnayab919512017-12-30 23:31:51 -050063 self.delimiter.hash(state);
64 TokenStreamHelper(&self.tts).hash(state);
David Tolnay9c76bcb2017-12-26 23:14:59 -050065 }
66}
Alex Crichtonccbb45d2017-05-23 10:58:24 -070067
David Tolnay84aa0752016-10-02 23:01:13 -070068#[cfg(feature = "parsing")]
69pub mod parsing {
70 use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071
David Tolnayc5ab8c62017-12-26 16:43:39 -050072 use synom::Synom;
David Tolnay84aa0752016-10-02 23:01:13 -070073
David Tolnaydecf28d2017-11-11 11:56:45 -080074 impl Synom for Macro {
Michael Layzell92639a52017-06-01 00:07:44 -040075 named!(parse -> Self, do_parse!(
David Tolnayd69fc2b2018-01-23 09:39:14 -080076 what: call!(Path::parse_mod_style) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -080077 bang: punct!(!) >>
David Tolnaye0824032017-12-27 15:25:56 -050078 body: call!(tt::delimited) >>
David Tolnaydecf28d2017-11-11 11:56:45 -080079 (Macro {
Michael Layzell92639a52017-06-01 00:07:44 -040080 path: what,
81 bang_token: bang,
David Tolnayab919512017-12-30 23:31:51 -050082 delimiter: body.0,
83 tts: body.1,
Michael Layzell92639a52017-06-01 00:07:44 -040084 })
85 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -080086
87 fn description() -> Option<&'static str> {
88 Some("macro invocation")
89 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070090 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070091}
David Tolnayf8cf9632016-10-02 23:15:25 -070092
93#[cfg(feature = "printing")]
94mod printing {
95 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -070096 use quote::ToTokens;
97 use proc_macro2::TokenStream;
David Tolnayf8cf9632016-10-02 23:15:25 -070098
David Tolnaydecf28d2017-11-11 11:56:45 -080099 impl ToTokens for Macro {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700100 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8cf9632016-10-02 23:15:25 -0700101 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700102 self.bang_token.to_tokens(tokens);
David Tolnayab919512017-12-30 23:31:51 -0500103 match self.delimiter {
104 MacroDelimiter::Paren(ref paren) => {
105 paren.surround(tokens, |tokens| self.tts.to_tokens(tokens));
106 }
107 MacroDelimiter::Brace(ref brace) => {
108 brace.surround(tokens, |tokens| self.tts.to_tokens(tokens));
109 }
110 MacroDelimiter::Bracket(ref bracket) => {
111 bracket.surround(tokens, |tokens| self.tts.to_tokens(tokens));
112 }
113 }
David Tolnayf8cf9632016-10-02 23:15:25 -0700114 }
115 }
David Tolnayf8cf9632016-10-02 23:15:25 -0700116}