blob: e6132e4d70268303c6fa5a1b04b3431604cdbeae [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
2
Alex Crichton62a0a592017-05-22 13:58:53 -07003ast_struct! {
4 /// Represents a macro invocation. The Path indicates which macro
5 /// is being invoked, and the vector of token-trees contains the source
6 /// of the macro invocation.
7 ///
8 /// NB: the additional ident for a `macro_rules`-style macro is actually
9 /// stored in the enclosing item. Oog.
10 pub struct Mac {
11 pub path: Path,
12 pub tts: Vec<TokenTree>,
13 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070014}
15
Alex Crichton62a0a592017-05-22 13:58:53 -070016ast_enum! {
17 /// When the main rust parser encounters a syntax-extension invocation, it
18 /// parses the arguments to the invocation as a token-tree. This is a very
19 /// loose structure, such that all sorts of different AST-fragments can
20 /// be passed to syntax extensions using a uniform type.
21 ///
22 /// If the syntax extension is an MBE macro, it will attempt to match its
23 /// LHS token tree against the provided token tree, and if it finds a
24 /// match, will transcribe the RHS token tree, splicing in any captured
25 /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
26 ///
27 /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
28 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
29 pub enum TokenTree {
30 /// A single token
31 Token(Token),
32 /// A delimited sequence of token trees
33 Delimited(Delimited),
34 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070035}
36
Alex Crichton62a0a592017-05-22 13:58:53 -070037ast_struct! {
38 pub struct Delimited {
39 /// The type of delimiter
40 pub delim: DelimToken,
41 /// The delimited sequence of token trees
42 pub tts: Vec<TokenTree>,
43 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070044}
45
Alex Crichton62a0a592017-05-22 13:58:53 -070046ast_enum! {
47 pub enum Token {
48 // Expression-operator symbols.
49 Eq,
50 Lt,
51 Le,
52 EqEq,
53 Ne,
54 Ge,
55 Gt,
56 AndAnd,
57 OrOr,
58 Not,
59 Tilde,
60 BinOp(BinOpToken),
61 BinOpEq(BinOpToken),
David Tolnayf4bbbd92016-09-23 14:41:55 -070062
Alex Crichton62a0a592017-05-22 13:58:53 -070063 // Structural symbols
64 At,
65 Dot,
66 DotDot,
67 DotDotDot,
68 Comma,
69 Semi,
70 Colon,
71 ModSep,
72 RArrow,
73 LArrow,
74 FatArrow,
75 Pound,
76 Dollar,
77 Question,
David Tolnayf4bbbd92016-09-23 14:41:55 -070078
Alex Crichton62a0a592017-05-22 13:58:53 -070079 // Literals
80 Literal(Lit),
David Tolnayf4bbbd92016-09-23 14:41:55 -070081
Alex Crichton62a0a592017-05-22 13:58:53 -070082 // Name components
83 Ident(Ident),
84 Underscore,
85 Lifetime(Ident),
David Tolnayf4bbbd92016-09-23 14:41:55 -070086
Alex Crichton62a0a592017-05-22 13:58:53 -070087 DocComment(String),
88 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070089}
90
Alex Crichton62a0a592017-05-22 13:58:53 -070091ast_enum! {
92 #[derive(Copy)]
93 pub enum BinOpToken {
94 Plus,
95 Minus,
96 Star,
97 Slash,
98 Percent,
99 Caret,
100 And,
101 Or,
102 Shl,
103 Shr,
104 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700105}
106
Alex Crichton62a0a592017-05-22 13:58:53 -0700107ast_enum! {
108 /// A delimiter token
109 #[derive(Copy)]
110 pub enum DelimToken {
111 /// A round parenthesis: `(` or `)`
112 Paren,
113 /// A square bracket: `[` or `]`
114 Bracket,
115 /// A curly brace: `{` or `}`
116 Brace,
117 }
David Tolnay84aa0752016-10-02 23:01:13 -0700118}
119
120#[cfg(feature = "parsing")]
121pub mod parsing {
122 use super::*;
123 use Lifetime;
124 use generics::parsing::lifetime;
David Tolnay5d55ef72016-12-21 20:20:04 -0500125 use ident::parsing::word;
David Tolnay84aa0752016-10-02 23:01:13 -0700126 use lit::parsing::lit;
David Tolnay5fe14fc2017-01-27 16:22:08 -0800127 use synom::space::{block_comment, whitespace};
David Tolnay5d55ef72016-12-21 20:20:04 -0500128 use ty::parsing::path;
David Tolnay84aa0752016-10-02 23:01:13 -0700129
130 named!(pub mac -> Mac, do_parse!(
David Tolnay5d55ef72016-12-21 20:20:04 -0500131 what: path >>
David Tolnay84aa0752016-10-02 23:01:13 -0700132 punct!("!") >>
133 body: delimited >>
134 (Mac {
David Tolnay5d55ef72016-12-21 20:20:04 -0500135 path: what,
David Tolnay84aa0752016-10-02 23:01:13 -0700136 tts: vec![TokenTree::Delimited(body)],
137 })
138 ));
139
David Tolnayf5fdfa02016-10-23 15:25:17 -0700140 named!(pub token_trees -> Vec<TokenTree>, many0!(token_tree));
Simon Sapin095a42b2016-10-20 15:54:23 +0200141
David Tolnay84aa0752016-10-02 23:01:13 -0700142 named!(pub delimited -> Delimited, alt!(
143 delimited!(
144 punct!("("),
David Tolnayeea28d62016-10-25 20:44:08 -0700145 token_trees,
David Tolnay84aa0752016-10-02 23:01:13 -0700146 punct!(")")
147 ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
148 |
149 delimited!(
150 punct!("["),
David Tolnayeea28d62016-10-25 20:44:08 -0700151 token_trees,
David Tolnay84aa0752016-10-02 23:01:13 -0700152 punct!("]")
153 ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
154 |
155 delimited!(
156 punct!("{"),
David Tolnayeea28d62016-10-25 20:44:08 -0700157 token_trees,
David Tolnay84aa0752016-10-02 23:01:13 -0700158 punct!("}")
159 ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
160 ));
161
David Tolnay5fe14fc2017-01-27 16:22:08 -0800162 named!(pub token_tree -> TokenTree, alt!(
David Tolnay84aa0752016-10-02 23:01:13 -0700163 map!(token, TokenTree::Token)
164 |
165 map!(delimited, TokenTree::Delimited)
166 ));
167
168 named!(token -> Token, alt!(
David Tolnayf7922e32016-10-08 22:16:04 -0700169 keyword!("_") => { |_| Token::Underscore }
David Tolnay59b23c52016-10-02 23:17:55 -0700170 |
David Tolnaye6042a62016-10-08 22:22:10 -0700171 punct!("&&") => { |_| Token::AndAnd } // must be before BinOp
David Tolnay2165b042016-10-08 00:04:23 -0700172 |
David Tolnaye6042a62016-10-08 22:22:10 -0700173 punct!("||") => { |_| Token::OrOr } // must be before BinOp
174 |
175 punct!("->") => { |_| Token::RArrow } // must be before BinOp
176 |
177 punct!("<-") => { |_| Token::LArrow } // must be before Lt
178 |
179 punct!("=>") => { |_| Token::FatArrow } // must be before Eq
180 |
181 punct!("...") => { |_| Token::DotDotDot } // must be before DotDot
182 |
183 punct!("..") => { |_| Token::DotDot } // must be before Dot
184 |
185 punct!(".") => { |_| Token::Dot }
David Tolnay2165b042016-10-08 00:04:23 -0700186 |
David Tolnay29833aa2016-10-25 21:08:03 -0700187 map!(doc_comment, Token::DocComment) // must be before bin_op
188 |
189 map!(bin_op_eq, Token::BinOpEq) // must be before bin_op
David Tolnay84aa0752016-10-02 23:01:13 -0700190 |
191 map!(bin_op, Token::BinOp)
192 |
David Tolnay59b23c52016-10-02 23:17:55 -0700193 map!(lit, Token::Literal)
David Tolnay84aa0752016-10-02 23:01:13 -0700194 |
David Tolnay05f462f2016-10-24 22:19:42 -0700195 map!(word, Token::Ident)
David Tolnay59b23c52016-10-02 23:17:55 -0700196 |
197 map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
198 |
David Tolnay84aa0752016-10-02 23:01:13 -0700199 punct!("<=") => { |_| Token::Le }
200 |
201 punct!("==") => { |_| Token::EqEq }
202 |
203 punct!("!=") => { |_| Token::Ne }
204 |
205 punct!(">=") => { |_| Token::Ge }
206 |
David Tolnay84aa0752016-10-02 23:01:13 -0700207 punct!("::") => { |_| Token::ModSep }
208 |
David Tolnay59b23c52016-10-02 23:17:55 -0700209 punct!("=") => { |_| Token::Eq }
210 |
211 punct!("<") => { |_| Token::Lt }
212 |
213 punct!(">") => { |_| Token::Gt }
214 |
215 punct!("!") => { |_| Token::Not }
216 |
217 punct!("~") => { |_| Token::Tilde }
218 |
219 punct!("@") => { |_| Token::At }
220 |
221 punct!(",") => { |_| Token::Comma }
222 |
223 punct!(";") => { |_| Token::Semi }
224 |
225 punct!(":") => { |_| Token::Colon }
226 |
David Tolnay84aa0752016-10-02 23:01:13 -0700227 punct!("#") => { |_| Token::Pound }
228 |
229 punct!("$") => { |_| Token::Dollar }
230 |
231 punct!("?") => { |_| Token::Question }
David Tolnay84aa0752016-10-02 23:01:13 -0700232 ));
233
234 named!(bin_op -> BinOpToken, alt!(
235 punct!("+") => { |_| BinOpToken::Plus }
236 |
237 punct!("-") => { |_| BinOpToken::Minus }
238 |
239 punct!("*") => { |_| BinOpToken::Star }
240 |
241 punct!("/") => { |_| BinOpToken::Slash }
242 |
243 punct!("%") => { |_| BinOpToken::Percent }
244 |
245 punct!("^") => { |_| BinOpToken::Caret }
246 |
247 punct!("&") => { |_| BinOpToken::And }
248 |
249 punct!("|") => { |_| BinOpToken::Or }
250 |
251 punct!("<<") => { |_| BinOpToken::Shl }
252 |
253 punct!(">>") => { |_| BinOpToken::Shr }
254 ));
255
256 named!(bin_op_eq -> BinOpToken, alt!(
257 punct!("+=") => { |_| BinOpToken::Plus }
258 |
259 punct!("-=") => { |_| BinOpToken::Minus }
260 |
261 punct!("*=") => { |_| BinOpToken::Star }
262 |
263 punct!("/=") => { |_| BinOpToken::Slash }
264 |
265 punct!("%=") => { |_| BinOpToken::Percent }
266 |
267 punct!("^=") => { |_| BinOpToken::Caret }
268 |
269 punct!("&=") => { |_| BinOpToken::And }
270 |
271 punct!("|=") => { |_| BinOpToken::Or }
272 |
273 punct!("<<=") => { |_| BinOpToken::Shl }
274 |
275 punct!(">>=") => { |_| BinOpToken::Shr }
276 ));
277
278 named!(doc_comment -> String, alt!(
279 do_parse!(
280 punct!("//!") >>
281 content: take_until!("\n") >>
282 (format!("//!{}", content))
283 )
284 |
285 do_parse!(
286 option!(whitespace) >>
287 peek!(tag!("/*!")) >>
288 com: block_comment >>
289 (com.to_owned())
290 )
291 |
292 do_parse!(
293 punct!("///") >>
David Tolnay1f16b602017-02-07 20:06:55 -0500294 not!(tag!("/")) >>
David Tolnay84aa0752016-10-02 23:01:13 -0700295 content: take_until!("\n") >>
296 (format!("///{}", content))
297 )
298 |
299 do_parse!(
300 option!(whitespace) >>
301 peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
302 com: block_comment >>
303 (com.to_owned())
304 )
305 ));
David Tolnayf4bbbd92016-09-23 14:41:55 -0700306}
David Tolnayf8cf9632016-10-02 23:15:25 -0700307
308#[cfg(feature = "printing")]
309mod printing {
310 use super::*;
311 use quote::{Tokens, ToTokens};
312
313 impl ToTokens for Mac {
314 fn to_tokens(&self, tokens: &mut Tokens) {
315 self.path.to_tokens(tokens);
316 tokens.append("!");
317 for tt in &self.tts {
318 tt.to_tokens(tokens);
319 }
320 }
321 }
322
323 impl ToTokens for TokenTree {
324 fn to_tokens(&self, tokens: &mut Tokens) {
325 match *self {
326 TokenTree::Token(ref token) => token.to_tokens(tokens),
327 TokenTree::Delimited(ref delimited) => delimited.to_tokens(tokens),
328 }
329 }
330 }
331
332 impl DelimToken {
333 fn open(&self) -> &'static str {
334 match *self {
335 DelimToken::Paren => "(",
336 DelimToken::Bracket => "[",
337 DelimToken::Brace => "{",
338 }
339 }
340
341 fn close(&self) -> &'static str {
342 match *self {
343 DelimToken::Paren => ")",
344 DelimToken::Bracket => "]",
345 DelimToken::Brace => "}",
346 }
347 }
348 }
349
350 impl ToTokens for Delimited {
351 fn to_tokens(&self, tokens: &mut Tokens) {
352 tokens.append(self.delim.open());
353 for tt in &self.tts {
354 tt.to_tokens(tokens);
355 }
356 tokens.append(self.delim.close());
357 }
358 }
359
360 impl ToTokens for Token {
361 fn to_tokens(&self, tokens: &mut Tokens) {
362 match *self {
363 Token::Eq => tokens.append("="),
364 Token::Lt => tokens.append("<"),
365 Token::Le => tokens.append("<="),
366 Token::EqEq => tokens.append("=="),
367 Token::Ne => tokens.append("!="),
368 Token::Ge => tokens.append(">="),
369 Token::Gt => tokens.append(">"),
370 Token::AndAnd => tokens.append("&&"),
371 Token::OrOr => tokens.append("||"),
372 Token::Not => tokens.append("!"),
373 Token::Tilde => tokens.append("~"),
374 Token::BinOp(binop) => tokens.append(binop.op()),
375 Token::BinOpEq(binop) => tokens.append(binop.assign_op()),
376 Token::At => tokens.append("@"),
377 Token::Dot => tokens.append("."),
378 Token::DotDot => tokens.append(".."),
379 Token::DotDotDot => tokens.append("..."),
380 Token::Comma => tokens.append(","),
381 Token::Semi => tokens.append(";"),
382 Token::Colon => tokens.append(":"),
383 Token::ModSep => tokens.append("::"),
384 Token::RArrow => tokens.append("->"),
385 Token::LArrow => tokens.append("<-"),
386 Token::FatArrow => tokens.append("=>"),
387 Token::Pound => tokens.append("#"),
388 Token::Dollar => tokens.append("$"),
389 Token::Question => tokens.append("?"),
390 Token::Literal(ref lit) => lit.to_tokens(tokens),
David Tolnay58f6f672016-10-19 08:44:25 -0700391 Token::Ident(ref ident) |
David Tolnayf8cf9632016-10-02 23:15:25 -0700392 Token::Lifetime(ref ident) => ident.to_tokens(tokens),
David Tolnay58f6f672016-10-19 08:44:25 -0700393 Token::Underscore => tokens.append("_"),
David Tolnayf8cf9632016-10-02 23:15:25 -0700394 Token::DocComment(ref com) => {
395 tokens.append(&format!("{}\n", com));
396 }
397 }
398 }
399 }
400
401 impl BinOpToken {
402 fn op(&self) -> &'static str {
403 match *self {
404 BinOpToken::Plus => "+",
405 BinOpToken::Minus => "-",
406 BinOpToken::Star => "*",
407 BinOpToken::Slash => "/",
408 BinOpToken::Percent => "%",
409 BinOpToken::Caret => "^",
410 BinOpToken::And => "&",
411 BinOpToken::Or => "|",
412 BinOpToken::Shl => "<<",
413 BinOpToken::Shr => ">>",
414 }
415 }
416
417 fn assign_op(&self) -> &'static str {
418 match *self {
419 BinOpToken::Plus => "+=",
420 BinOpToken::Minus => "-=",
421 BinOpToken::Star => "*=",
422 BinOpToken::Slash => "/=",
423 BinOpToken::Percent => "%=",
424 BinOpToken::Caret => "^=",
425 BinOpToken::And => "&=",
426 BinOpToken::Or => "|=",
427 BinOpToken::Shl => "<<=",
428 BinOpToken::Shr => ">>=",
429 }
430 }
431 }
432
433 impl ToTokens for BinOpToken {
434 fn to_tokens(&self, tokens: &mut Tokens) {
435 tokens.append(self.op());
436 }
437 }
438}