blob: 55b33cff6bfc92722decc81014226a0c97604dd9 [file] [log] [blame]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001#[cfg(feature = "extra-traits")]
2use std::fmt;
3
David Tolnayf4bbbd92016-09-23 14:41:55 -07004use super::*;
5
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -07006use proc_macro2::{TokenNode, Delimiter};
Alex Crichtonccbb45d2017-05-23 10:58:24 -07007
Alex Crichton62a0a592017-05-22 13:58:53 -07008ast_struct! {
9 /// Represents a macro invocation. The Path indicates which macro
10 /// is being invoked, and the vector of token-trees contains the source
11 /// of the macro invocation.
Alex Crichton62a0a592017-05-22 13:58:53 -070012 pub struct Mac {
13 pub path: Path,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070014 pub bang_token: tokens::Bang,
David Tolnay570695e2017-06-03 16:15:13 -070015 /// The `example` in `macro_rules! example { ... }`.
16 pub ident: Option<Ident>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070017 pub tokens: Vec<TokenTree>,
Alex Crichton62a0a592017-05-22 13:58:53 -070018 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070019}
20
Alex Crichtonccbb45d2017-05-23 10:58:24 -070021#[cfg_attr(feature = "clone-impls", derive(Clone))]
22pub struct TokenTree(pub proc_macro2::TokenTree);
23
24impl Mac {
25 pub fn is_braced(&self) -> bool {
26 match self.tokens.last() {
27 Some(t) => t.is_braced(),
28 None => false,
29 }
Alex Crichton62a0a592017-05-22 13:58:53 -070030 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070031}
32
Alex Crichtonccbb45d2017-05-23 10:58:24 -070033impl TokenTree {
34 pub fn is_braced(&self) -> bool {
35 match self.0.kind {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070036 TokenNode::Group(Delimiter::Brace, _) => true,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070037 _ => false,
38 }
Alex Crichton62a0a592017-05-22 13:58:53 -070039 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070040}
41
Alex Crichtonccbb45d2017-05-23 10:58:24 -070042#[cfg(feature = "extra-traits")]
43impl PartialEq for TokenTree {
44 fn eq(&self, other: &TokenTree) -> bool {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070045 use proc_macro2::Spacing;
David Tolnayf4bbbd92016-09-23 14:41:55 -070046
Alex Crichtonccbb45d2017-05-23 10:58:24 -070047 match (&self.0.kind, &other.0.kind) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070048 (&TokenNode::Group(d1, ref s1), &TokenNode::Group(d2, ref s2)) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070049 match (d1, d2) {
50 (Delimiter::Parenthesis, Delimiter::Parenthesis) |
51 (Delimiter::Brace, Delimiter::Brace) |
52 (Delimiter::Bracket, Delimiter::Bracket) => {}
53 (Delimiter::None, Delimiter::None) => {}
54 _ => return false,
55 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070056
Alex Crichtonccbb45d2017-05-23 10:58:24 -070057 let s1 = s1.clone().into_iter();
58 let mut s2 = s2.clone().into_iter();
David Tolnayf4bbbd92016-09-23 14:41:55 -070059
Alex Crichtonccbb45d2017-05-23 10:58:24 -070060 for item1 in s1 {
61 let item2 = match s2.next() {
62 Some(item) => item,
63 None => return false,
64 };
65 if TokenTree(item1) != TokenTree(item2) {
66 return false
67 }
68 }
69 s2.next().is_none()
70 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070071 (&TokenNode::Op(o1, k1), &TokenNode::Op(o2, k2)) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070072 o1 == o2 && match (k1, k2) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070073 (Spacing::Alone, Spacing::Alone) |
74 (Spacing::Joint, Spacing::Joint) => true,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 _ => false,
76 }
77 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070078 (&TokenNode::Literal(ref l1), &TokenNode::Literal(ref l2)) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070079 l1.to_string() == l2.to_string()
80 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070081 (&TokenNode::Term(ref s1), &TokenNode::Term(ref s2)) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070082 s1.as_str() == s2.as_str()
83 }
84 _ => false,
85 }
Alex Crichton62a0a592017-05-22 13:58:53 -070086 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070087}
88
Alex Crichtonccbb45d2017-05-23 10:58:24 -070089#[cfg(feature = "extra-traits")]
90impl Eq for TokenTree {}
91
92#[cfg(feature = "extra-traits")]
93impl ::std::hash::Hash for TokenTree {
94 fn hash<H: ::std::hash::Hasher>(&self, h: &mut H) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070095 use proc_macro2::Spacing;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070096
97 match self.0.kind {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070098 TokenNode::Group(delim, ref stream) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070099 0u8.hash(h);
100 match delim {
101 Delimiter::Parenthesis => 0u8.hash(h),
102 Delimiter::Brace => 1u8.hash(h),
103 Delimiter::Bracket => 2u8.hash(h),
104 Delimiter::None => 3u8.hash(h),
105 }
106
107 for item in stream.clone().into_iter() {
108 TokenTree(item).hash(h);
109 }
110 0xffu8.hash(h); // terminator w/ a variant we don't normally hash
111 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700112 TokenNode::Op(op, kind) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700113 1u8.hash(h);
114 op.hash(h);
115 match kind {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700116 Spacing::Alone => 0u8.hash(h),
117 Spacing::Joint => 1u8.hash(h),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700118 }
119 }
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700120 TokenNode::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
121 TokenNode::Term(ref word) => (3u8, word.as_str()).hash(h),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700122 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700124}
125
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700126#[cfg(feature = "extra-traits")]
127impl fmt::Debug for TokenTree {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 self.0.to_string().fmt(f)
Alex Crichton62a0a592017-05-22 13:58:53 -0700130 }
David Tolnay84aa0752016-10-02 23:01:13 -0700131}
132
133#[cfg(feature = "parsing")]
134pub mod parsing {
135 use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700136
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700137 use proc_macro2::{TokenNode, TokenTree};
Alex Crichton954046c2017-05-30 21:49:42 -0700138 use synom::tokens::*;
Michael Layzell92639a52017-06-01 00:07:44 -0400139 use synom::{Synom, PResult, Cursor, parse_error};
David Tolnay84aa0752016-10-02 23:01:13 -0700140
Alex Crichton954046c2017-05-30 21:49:42 -0700141 impl Synom for Mac {
Michael Layzell92639a52017-06-01 00:07:44 -0400142 named!(parse -> Self, do_parse!(
143 what: syn!(Path) >>
144 bang: syn!(Bang) >>
145 body: call!(::TokenTree::parse_delimited) >>
146 (Mac {
147 path: what,
148 bang_token: bang,
David Tolnay570695e2017-06-03 16:15:13 -0700149 ident: None,
Michael Layzell92639a52017-06-01 00:07:44 -0400150 tokens: vec![body],
151 })
152 ));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700153 }
154
Alex Crichton954046c2017-05-30 21:49:42 -0700155 impl ::TokenTree {
Michael Layzell92639a52017-06-01 00:07:44 -0400156 pub fn parse_list(input: Cursor) -> PResult<Vec<Self>> {
Michael Layzell589a8f42017-06-02 19:47:01 -0400157 Ok((Cursor::empty(), input.token_stream().into_iter().map(::TokenTree).collect()))
Alex Crichton954046c2017-05-30 21:49:42 -0700158 }
159
Michael Layzell92639a52017-06-01 00:07:44 -0400160 pub fn parse_delimited(input: Cursor) -> PResult<Self> {
Michael Layzell589a8f42017-06-02 19:47:01 -0400161 match input.token_tree() {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700162 Some((rest, token @ TokenTree { kind: TokenNode::Group(..), .. })) => {
Michael Layzell589a8f42017-06-02 19:47:01 -0400163 Ok((rest, ::TokenTree(token)))
Alex Crichton954046c2017-05-30 21:49:42 -0700164 }
Michael Layzell92639a52017-06-01 00:07:44 -0400165 _ => parse_error(),
Alex Crichton954046c2017-05-30 21:49:42 -0700166 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700167 }
168 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700169}
David Tolnayf8cf9632016-10-02 23:15:25 -0700170
171#[cfg(feature = "printing")]
172mod printing {
173 use super::*;
174 use quote::{Tokens, ToTokens};
175
176 impl ToTokens for Mac {
177 fn to_tokens(&self, tokens: &mut Tokens) {
178 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700179 self.bang_token.to_tokens(tokens);
180 tokens.append_all(&self.tokens);
David Tolnayf8cf9632016-10-02 23:15:25 -0700181 }
182 }
183
184 impl ToTokens for TokenTree {
185 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700186 self.0.to_tokens(tokens);
David Tolnayf8cf9632016-10-02 23:15:25 -0700187 }
188 }
189}