blob: a5d781fc93bcef8b8b1db3268c2c4fc3c42fc17e [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
2
3/// Represents a macro invocation. The Path indicates which macro
4/// is being invoked, and the vector of token-trees contains the source
5/// of the macro invocation.
6///
David Tolnayaed77b02016-09-23 20:50:31 -07007/// NB: the additional ident for a `macro_rules`-style macro is actually
David Tolnayf4bbbd92016-09-23 14:41:55 -07008/// stored in the enclosing item. Oog.
David Tolnay9bf4af82017-01-07 11:17:46 -08009#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -070010pub struct Mac {
11 pub path: Path,
12 pub tts: Vec<TokenTree>,
13}
14
15/// When the main rust parser encounters a syntax-extension invocation, it
16/// parses the arguments to the invocation as a token-tree. This is a very
17/// loose structure, such that all sorts of different AST-fragments can
18/// be passed to syntax extensions using a uniform type.
19///
20/// If the syntax extension is an MBE macro, it will attempt to match its
21/// LHS token tree against the provided token tree, and if it finds a
22/// match, will transcribe the RHS token tree, splicing in any captured
David Tolnayaed77b02016-09-23 20:50:31 -070023/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
David Tolnayf4bbbd92016-09-23 14:41:55 -070024///
25/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
26/// Nothing special happens to misnamed or misplaced `SubstNt`s.
David Tolnay9bf4af82017-01-07 11:17:46 -080027#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -070028pub enum TokenTree {
29 /// A single token
30 Token(Token),
31 /// A delimited sequence of token trees
32 Delimited(Delimited),
David Tolnayf4bbbd92016-09-23 14:41:55 -070033}
34
David Tolnay9bf4af82017-01-07 11:17:46 -080035#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -070036pub struct Delimited {
37 /// The type of delimiter
38 pub delim: DelimToken,
39 /// The delimited sequence of token trees
40 pub tts: Vec<TokenTree>,
41}
42
David Tolnay9bf4af82017-01-07 11:17:46 -080043#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -070044pub enum Token {
David Tolnaydaaf7742016-10-03 11:11:43 -070045 // Expression-operator symbols.
David Tolnayf4bbbd92016-09-23 14:41:55 -070046 Eq,
47 Lt,
48 Le,
49 EqEq,
50 Ne,
51 Ge,
52 Gt,
53 AndAnd,
54 OrOr,
55 Not,
56 Tilde,
57 BinOp(BinOpToken),
58 BinOpEq(BinOpToken),
59
David Tolnaydaaf7742016-10-03 11:11:43 -070060 // Structural symbols
David Tolnayf4bbbd92016-09-23 14:41:55 -070061 At,
62 Dot,
63 DotDot,
64 DotDotDot,
65 Comma,
66 Semi,
67 Colon,
68 ModSep,
69 RArrow,
70 LArrow,
71 FatArrow,
72 Pound,
73 Dollar,
74 Question,
David Tolnayf4bbbd92016-09-23 14:41:55 -070075
David Tolnaydaaf7742016-10-03 11:11:43 -070076 // Literals
David Tolnay84aa0752016-10-02 23:01:13 -070077 Literal(Lit),
David Tolnayf4bbbd92016-09-23 14:41:55 -070078
David Tolnaydaaf7742016-10-03 11:11:43 -070079 // Name components
David Tolnayf4bbbd92016-09-23 14:41:55 -070080 Ident(Ident),
81 Underscore,
82 Lifetime(Ident),
83
David Tolnayf4bbbd92016-09-23 14:41:55 -070084 DocComment(String),
David Tolnayf4bbbd92016-09-23 14:41:55 -070085}
86
David Tolnay9bf4af82017-01-07 11:17:46 -080087#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -070088pub enum BinOpToken {
89 Plus,
90 Minus,
91 Star,
92 Slash,
93 Percent,
94 Caret,
95 And,
96 Or,
97 Shl,
98 Shr,
99}
100
101/// A delimiter token
David Tolnay9bf4af82017-01-07 11:17:46 -0800102#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700103pub enum DelimToken {
104 /// A round parenthesis: `(` or `)`
105 Paren,
106 /// A square bracket: `[` or `]`
107 Bracket,
108 /// A curly brace: `{` or `}`
109 Brace,
David Tolnay84aa0752016-10-02 23:01:13 -0700110}
111
112#[cfg(feature = "parsing")]
113pub mod parsing {
114 use super::*;
115 use Lifetime;
116 use generics::parsing::lifetime;
David Tolnay5d55ef72016-12-21 20:20:04 -0500117 use ident::parsing::word;
David Tolnay84aa0752016-10-02 23:01:13 -0700118 use lit::parsing::lit;
David Tolnay5d55ef72016-12-21 20:20:04 -0500119 use ty::parsing::path;
Michael Layzell416724e2017-05-24 21:12:34 -0400120 use attr::parsing::{inner_doc_comment, outer_doc_comment};
David Tolnay84aa0752016-10-02 23:01:13 -0700121
122 named!(pub mac -> Mac, do_parse!(
David Tolnay5d55ef72016-12-21 20:20:04 -0500123 what: path >>
David Tolnay84aa0752016-10-02 23:01:13 -0700124 punct!("!") >>
125 body: delimited >>
126 (Mac {
David Tolnay5d55ef72016-12-21 20:20:04 -0500127 path: what,
David Tolnay84aa0752016-10-02 23:01:13 -0700128 tts: vec![TokenTree::Delimited(body)],
129 })
130 ));
131
David Tolnayf5fdfa02016-10-23 15:25:17 -0700132 named!(pub token_trees -> Vec<TokenTree>, many0!(token_tree));
Simon Sapin095a42b2016-10-20 15:54:23 +0200133
David Tolnay84aa0752016-10-02 23:01:13 -0700134 named!(pub delimited -> Delimited, alt!(
Michael Layzell416724e2017-05-24 21:12:34 -0400135 delim!(
136 Parenthesis,
137 token_trees
David Tolnay84aa0752016-10-02 23:01:13 -0700138 ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
139 |
Michael Layzell416724e2017-05-24 21:12:34 -0400140 delim!(
141 Bracket,
142 token_trees
David Tolnay84aa0752016-10-02 23:01:13 -0700143 ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
144 |
Michael Layzell416724e2017-05-24 21:12:34 -0400145 delim!(
146 Brace,
147 token_trees
David Tolnay84aa0752016-10-02 23:01:13 -0700148 ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
149 ));
150
David Tolnay5fe14fc2017-01-27 16:22:08 -0800151 named!(pub token_tree -> TokenTree, alt!(
David Tolnay84aa0752016-10-02 23:01:13 -0700152 map!(token, TokenTree::Token)
153 |
154 map!(delimited, TokenTree::Delimited)
155 ));
156
157 named!(token -> Token, alt!(
David Tolnayf7922e32016-10-08 22:16:04 -0700158 keyword!("_") => { |_| Token::Underscore }
David Tolnay59b23c52016-10-02 23:17:55 -0700159 |
David Tolnaye6042a62016-10-08 22:22:10 -0700160 punct!("&&") => { |_| Token::AndAnd } // must be before BinOp
David Tolnay2165b042016-10-08 00:04:23 -0700161 |
David Tolnaye6042a62016-10-08 22:22:10 -0700162 punct!("||") => { |_| Token::OrOr } // must be before BinOp
163 |
164 punct!("->") => { |_| Token::RArrow } // must be before BinOp
165 |
166 punct!("<-") => { |_| Token::LArrow } // must be before Lt
167 |
168 punct!("=>") => { |_| Token::FatArrow } // must be before Eq
169 |
170 punct!("...") => { |_| Token::DotDotDot } // must be before DotDot
171 |
172 punct!("..") => { |_| Token::DotDot } // must be before Dot
173 |
174 punct!(".") => { |_| Token::Dot }
David Tolnay2165b042016-10-08 00:04:23 -0700175 |
David Tolnay29833aa2016-10-25 21:08:03 -0700176 map!(doc_comment, Token::DocComment) // must be before bin_op
177 |
178 map!(bin_op_eq, Token::BinOpEq) // must be before bin_op
David Tolnay84aa0752016-10-02 23:01:13 -0700179 |
180 map!(bin_op, Token::BinOp)
181 |
David Tolnay59b23c52016-10-02 23:17:55 -0700182 map!(lit, Token::Literal)
David Tolnay84aa0752016-10-02 23:01:13 -0700183 |
David Tolnay05f462f2016-10-24 22:19:42 -0700184 map!(word, Token::Ident)
David Tolnay59b23c52016-10-02 23:17:55 -0700185 |
186 map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
187 |
David Tolnay84aa0752016-10-02 23:01:13 -0700188 punct!("<=") => { |_| Token::Le }
189 |
190 punct!("==") => { |_| Token::EqEq }
191 |
192 punct!("!=") => { |_| Token::Ne }
193 |
194 punct!(">=") => { |_| Token::Ge }
195 |
David Tolnay84aa0752016-10-02 23:01:13 -0700196 punct!("::") => { |_| Token::ModSep }
197 |
David Tolnay59b23c52016-10-02 23:17:55 -0700198 punct!("=") => { |_| Token::Eq }
199 |
200 punct!("<") => { |_| Token::Lt }
201 |
202 punct!(">") => { |_| Token::Gt }
203 |
204 punct!("!") => { |_| Token::Not }
205 |
206 punct!("~") => { |_| Token::Tilde }
207 |
208 punct!("@") => { |_| Token::At }
209 |
210 punct!(",") => { |_| Token::Comma }
211 |
212 punct!(";") => { |_| Token::Semi }
213 |
214 punct!(":") => { |_| Token::Colon }
215 |
David Tolnay84aa0752016-10-02 23:01:13 -0700216 punct!("#") => { |_| Token::Pound }
217 |
218 punct!("$") => { |_| Token::Dollar }
219 |
220 punct!("?") => { |_| Token::Question }
David Tolnay84aa0752016-10-02 23:01:13 -0700221 ));
222
223 named!(bin_op -> BinOpToken, alt!(
224 punct!("+") => { |_| BinOpToken::Plus }
225 |
226 punct!("-") => { |_| BinOpToken::Minus }
227 |
228 punct!("*") => { |_| BinOpToken::Star }
229 |
230 punct!("/") => { |_| BinOpToken::Slash }
231 |
232 punct!("%") => { |_| BinOpToken::Percent }
233 |
234 punct!("^") => { |_| BinOpToken::Caret }
235 |
236 punct!("&") => { |_| BinOpToken::And }
237 |
238 punct!("|") => { |_| BinOpToken::Or }
239 |
240 punct!("<<") => { |_| BinOpToken::Shl }
241 |
242 punct!(">>") => { |_| BinOpToken::Shr }
243 ));
244
245 named!(bin_op_eq -> BinOpToken, alt!(
246 punct!("+=") => { |_| BinOpToken::Plus }
247 |
248 punct!("-=") => { |_| BinOpToken::Minus }
249 |
250 punct!("*=") => { |_| BinOpToken::Star }
251 |
252 punct!("/=") => { |_| BinOpToken::Slash }
253 |
254 punct!("%=") => { |_| BinOpToken::Percent }
255 |
256 punct!("^=") => { |_| BinOpToken::Caret }
257 |
258 punct!("&=") => { |_| BinOpToken::And }
259 |
260 punct!("|=") => { |_| BinOpToken::Or }
261 |
262 punct!("<<=") => { |_| BinOpToken::Shl }
263 |
264 punct!(">>=") => { |_| BinOpToken::Shr }
265 ));
266
267 named!(doc_comment -> String, alt!(
Michael Layzell416724e2017-05-24 21:12:34 -0400268 inner_doc_comment
David Tolnay84aa0752016-10-02 23:01:13 -0700269 |
Michael Layzell416724e2017-05-24 21:12:34 -0400270 outer_doc_comment
David Tolnay84aa0752016-10-02 23:01:13 -0700271 ));
David Tolnayf4bbbd92016-09-23 14:41:55 -0700272}
David Tolnayf8cf9632016-10-02 23:15:25 -0700273
274#[cfg(feature = "printing")]
275mod printing {
276 use super::*;
277 use quote::{Tokens, ToTokens};
278
279 impl ToTokens for Mac {
280 fn to_tokens(&self, tokens: &mut Tokens) {
281 self.path.to_tokens(tokens);
282 tokens.append("!");
283 for tt in &self.tts {
284 tt.to_tokens(tokens);
285 }
286 }
287 }
288
289 impl ToTokens for TokenTree {
290 fn to_tokens(&self, tokens: &mut Tokens) {
291 match *self {
292 TokenTree::Token(ref token) => token.to_tokens(tokens),
293 TokenTree::Delimited(ref delimited) => delimited.to_tokens(tokens),
294 }
295 }
296 }
297
298 impl DelimToken {
299 fn open(&self) -> &'static str {
300 match *self {
301 DelimToken::Paren => "(",
302 DelimToken::Bracket => "[",
303 DelimToken::Brace => "{",
304 }
305 }
306
307 fn close(&self) -> &'static str {
308 match *self {
309 DelimToken::Paren => ")",
310 DelimToken::Bracket => "]",
311 DelimToken::Brace => "}",
312 }
313 }
314 }
315
316 impl ToTokens for Delimited {
317 fn to_tokens(&self, tokens: &mut Tokens) {
318 tokens.append(self.delim.open());
319 for tt in &self.tts {
320 tt.to_tokens(tokens);
321 }
322 tokens.append(self.delim.close());
323 }
324 }
325
326 impl ToTokens for Token {
327 fn to_tokens(&self, tokens: &mut Tokens) {
328 match *self {
329 Token::Eq => tokens.append("="),
330 Token::Lt => tokens.append("<"),
331 Token::Le => tokens.append("<="),
332 Token::EqEq => tokens.append("=="),
333 Token::Ne => tokens.append("!="),
334 Token::Ge => tokens.append(">="),
335 Token::Gt => tokens.append(">"),
336 Token::AndAnd => tokens.append("&&"),
337 Token::OrOr => tokens.append("||"),
338 Token::Not => tokens.append("!"),
339 Token::Tilde => tokens.append("~"),
340 Token::BinOp(binop) => tokens.append(binop.op()),
341 Token::BinOpEq(binop) => tokens.append(binop.assign_op()),
342 Token::At => tokens.append("@"),
343 Token::Dot => tokens.append("."),
344 Token::DotDot => tokens.append(".."),
345 Token::DotDotDot => tokens.append("..."),
346 Token::Comma => tokens.append(","),
347 Token::Semi => tokens.append(";"),
348 Token::Colon => tokens.append(":"),
349 Token::ModSep => tokens.append("::"),
350 Token::RArrow => tokens.append("->"),
351 Token::LArrow => tokens.append("<-"),
352 Token::FatArrow => tokens.append("=>"),
353 Token::Pound => tokens.append("#"),
354 Token::Dollar => tokens.append("$"),
355 Token::Question => tokens.append("?"),
356 Token::Literal(ref lit) => lit.to_tokens(tokens),
David Tolnay58f6f672016-10-19 08:44:25 -0700357 Token::Ident(ref ident) |
David Tolnayf8cf9632016-10-02 23:15:25 -0700358 Token::Lifetime(ref ident) => ident.to_tokens(tokens),
David Tolnay58f6f672016-10-19 08:44:25 -0700359 Token::Underscore => tokens.append("_"),
David Tolnayf8cf9632016-10-02 23:15:25 -0700360 Token::DocComment(ref com) => {
361 tokens.append(&format!("{}\n", com));
362 }
363 }
364 }
365 }
366
367 impl BinOpToken {
368 fn op(&self) -> &'static str {
369 match *self {
370 BinOpToken::Plus => "+",
371 BinOpToken::Minus => "-",
372 BinOpToken::Star => "*",
373 BinOpToken::Slash => "/",
374 BinOpToken::Percent => "%",
375 BinOpToken::Caret => "^",
376 BinOpToken::And => "&",
377 BinOpToken::Or => "|",
378 BinOpToken::Shl => "<<",
379 BinOpToken::Shr => ">>",
380 }
381 }
382
383 fn assign_op(&self) -> &'static str {
384 match *self {
385 BinOpToken::Plus => "+=",
386 BinOpToken::Minus => "-=",
387 BinOpToken::Star => "*=",
388 BinOpToken::Slash => "/=",
389 BinOpToken::Percent => "%=",
390 BinOpToken::Caret => "^=",
391 BinOpToken::And => "&=",
392 BinOpToken::Or => "|=",
393 BinOpToken::Shl => "<<=",
394 BinOpToken::Shr => ">>=",
395 }
396 }
397 }
398
399 impl ToTokens for BinOpToken {
400 fn to_tokens(&self, tokens: &mut Tokens) {
401 tokens.append(self.op());
402 }
403 }
404}