blob: 1866ca89c51821277cd3d357c5cd59047d62369a [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 Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay2ae520a2017-12-29 11:19:50 -050014#[cfg(feature = "full")]
15use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
44 /// Expr::IfLet(expr) => {
45 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
58 /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
59 /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
60 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnaya454c8f2018-01-07 01:01:10 -0800219 /// An `if` expression with an optional `else` block: `if expr { ... }
220 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// The `else` branch expression may only be an `If`, `IfLet`, or
223 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800224 ///
225 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400226 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500227 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500228 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700229 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500230 pub then_branch: Block,
231 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500233
David Tolnaya454c8f2018-01-07 01:01:10 -0800234 /// An `if let` expression with an optional `else` block: `if let pat =
235 /// expr { ... } else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// The `else` branch expression may only be an `If`, `IfLet`, or
238 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800239 ///
240 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400241 pub IfLet(ExprIfLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500242 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub if_token: Token![if],
244 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200245 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500247 pub expr: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500248 pub then_branch: Block,
249 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500251
David Tolnaya454c8f2018-01-07 01:01:10 -0800252 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800253 ///
254 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400255 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500256 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500257 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500259 pub cond: Box<Expr>,
260 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500262
David Tolnaya454c8f2018-01-07 01:01:10 -0800263 /// A while-let loop: `while let pat = expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800264 ///
265 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400266 pub WhileLet(ExprWhileLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500267 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500268 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800269 pub while_token: Token![while],
270 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200271 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800272 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500273 pub expr: Box<Expr>,
274 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700275 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500276
David Tolnaya454c8f2018-01-07 01:01:10 -0800277 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800278 ///
279 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400280 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500281 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500282 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500283 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700284 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500285 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700286 pub expr: Box<Expr>,
287 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500295 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500296 pub loop_token: Token![loop],
297 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700298 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500299
David Tolnaya454c8f2018-01-07 01:01:10 -0800300 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800301 ///
302 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400303 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500304 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700306 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500307 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub arms: Vec<Arm>,
309 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500310
David Tolnaya454c8f2018-01-07 01:01:10 -0800311 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400314 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500315 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900316 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200317 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500318 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800319 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500320 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500322 pub output: ReturnType,
323 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500325
David Tolnaya454c8f2018-01-07 01:01:10 -0800326 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500329 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500330 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500331 pub unsafe_token: Token![unsafe],
332 pub block: Block,
333 }),
334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800336 ///
337 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400338 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400340 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700341 pub block: Block,
342 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700343
David Tolnaya454c8f2018-01-07 01:01:10 -0800344 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400347 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700349 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500351 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnaya454c8f2018-01-07 01:01:10 -0800354 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400357 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500358 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700359 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500360 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700361 pub right: Box<Expr>,
362 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500363
David Tolnaya454c8f2018-01-07 01:01:10 -0800364 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500365 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700368 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500370 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500372 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500374
David Tolnay05658502018-01-07 09:56:37 -0800375 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800376 ///
377 /// *This type is available if Syn is built with the `"derive"` or
378 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700379 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500380 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500382 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500383 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500385
David Tolnaya454c8f2018-01-07 01:01:10 -0800386 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400389 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500390 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700392 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500393 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700395
David Tolnaya454c8f2018-01-07 01:01:10 -0800396 /// A path like `std::mem::replace` possibly containing generic
397 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800399 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or
402 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500404 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 pub qself: Option<QSelf>,
406 pub path: Path,
407 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200412 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500415 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub expr: Box<Expr>,
417 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A `break`, with an optional label to break and an optional
420 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800421 ///
422 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400423 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500424 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500425 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700426 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700427 pub expr: Option<Box<Expr>>,
428 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800435 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500436 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700437 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500438
David Tolnaya454c8f2018-01-07 01:01:10 -0800439 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800440 ///
441 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500442 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500443 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800444 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500445 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700447
David Tolnaya454c8f2018-01-07 01:01:10 -0800448 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500451 pub Macro(ExprMacro #full {
452 pub attrs: Vec<Attribute>,
453 pub mac: Macro,
454 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700455
David Tolnaya454c8f2018-01-07 01:01:10 -0800456 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800458 /// The `rest` provides the value of the remaining fields as in `S { a:
459 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800460 ///
461 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400462 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500463 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500465 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500466 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub dot2_token: Option<Token![..]>,
468 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700470
David Tolnaya454c8f2018-01-07 01:01:10 -0800471 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800472 ///
473 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400474 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500475 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500476 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700477 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500478 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800479 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700481
David Tolnaya454c8f2018-01-07 01:01:10 -0800482 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800485 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500487 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500488 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400492 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800493 /// This variant is important for faithfully representing the precedence
494 /// of expressions and is related to `None`-delimited spans in a
495 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800496 ///
497 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500498 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500499 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500500 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500501 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400502 }),
503
David Tolnaya454c8f2018-01-07 01:01:10 -0800504 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800505 ///
506 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400507 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500508 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700509 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800510 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700511 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700512
David Tolnay02a9c6f2018-08-24 18:58:45 -0400513 /// An async block: `async { ... }`.
514 ///
515 /// *This type is available if Syn is built with the `"full"` feature.*
516 pub Async(ExprAsync #full {
517 pub attrs: Vec<Attribute>,
518 pub async_token: Token![async],
519 pub capture: Option<Token![move]>,
520 pub block: Block,
521 }),
522
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400523 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400526 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500527 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400528 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700529 pub block: Block,
530 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700531
David Tolnaya454c8f2018-01-07 01:01:10 -0800532 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800533 ///
534 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700535 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500536 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800537 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700538 pub expr: Option<Box<Expr>>,
539 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500540
David Tolnaya454c8f2018-01-07 01:01:10 -0800541 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800542 ///
543 /// *This type is available if Syn is built with the `"derive"` or
544 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500545 pub Verbatim(ExprVerbatim #manual_extra_traits {
546 pub tts: TokenStream,
547 }),
548 }
549}
550
551#[cfg(feature = "extra-traits")]
552impl Eq for ExprVerbatim {}
553
554#[cfg(feature = "extra-traits")]
555impl PartialEq for ExprVerbatim {
556 fn eq(&self, other: &Self) -> bool {
557 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
558 }
559}
560
561#[cfg(feature = "extra-traits")]
562impl Hash for ExprVerbatim {
563 fn hash<H>(&self, state: &mut H)
564 where
565 H: Hasher,
566 {
567 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700568 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700569}
570
David Tolnay8c91b882017-12-28 23:04:32 -0500571impl Expr {
572 // Not public API.
573 #[doc(hidden)]
David Tolnay096d4982017-12-28 23:18:18 -0500574 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -0500575 pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500576 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800577 Expr::Box(ExprBox { ref mut attrs, .. })
578 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
579 | Expr::Array(ExprArray { ref mut attrs, .. })
580 | Expr::Call(ExprCall { ref mut attrs, .. })
581 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
582 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
583 | Expr::Binary(ExprBinary { ref mut attrs, .. })
584 | Expr::Unary(ExprUnary { ref mut attrs, .. })
585 | Expr::Lit(ExprLit { ref mut attrs, .. })
586 | Expr::Cast(ExprCast { ref mut attrs, .. })
587 | Expr::Type(ExprType { ref mut attrs, .. })
588 | Expr::If(ExprIf { ref mut attrs, .. })
589 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
590 | Expr::While(ExprWhile { ref mut attrs, .. })
591 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
592 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
593 | Expr::Loop(ExprLoop { ref mut attrs, .. })
594 | Expr::Match(ExprMatch { ref mut attrs, .. })
595 | Expr::Closure(ExprClosure { ref mut attrs, .. })
596 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
597 | Expr::Block(ExprBlock { ref mut attrs, .. })
598 | Expr::Assign(ExprAssign { ref mut attrs, .. })
599 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
600 | Expr::Field(ExprField { ref mut attrs, .. })
601 | Expr::Index(ExprIndex { ref mut attrs, .. })
602 | Expr::Range(ExprRange { ref mut attrs, .. })
603 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200604 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800605 | Expr::Break(ExprBreak { ref mut attrs, .. })
606 | Expr::Continue(ExprContinue { ref mut attrs, .. })
607 | Expr::Return(ExprReturn { ref mut attrs, .. })
608 | Expr::Macro(ExprMacro { ref mut attrs, .. })
609 | Expr::Struct(ExprStruct { ref mut attrs, .. })
610 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
611 | Expr::Paren(ExprParen { ref mut attrs, .. })
612 | Expr::Group(ExprGroup { ref mut attrs, .. })
613 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400614 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400615 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800616 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay2ae520a2017-12-29 11:19:50 -0500617 Expr::Verbatim(_) => {
618 // TODO
619 Vec::new()
620 }
David Tolnay8c91b882017-12-28 23:04:32 -0500621 }
622 }
623}
624
David Tolnay85b69a42017-12-27 20:43:10 -0500625ast_enum! {
626 /// A struct or tuple struct field accessed in a struct literal or field
627 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800628 ///
629 /// *This type is available if Syn is built with the `"derive"` or `"full"`
630 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500631 pub enum Member {
632 /// A named field like `self.x`.
633 Named(Ident),
634 /// An unnamed field like `self.0`.
635 Unnamed(Index),
636 }
637}
638
David Tolnay85b69a42017-12-27 20:43:10 -0500639ast_struct! {
640 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800641 ///
642 /// *This type is available if Syn is built with the `"derive"` or `"full"`
643 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500644 pub struct Index #manual_extra_traits {
645 pub index: u32,
646 pub span: Span,
647 }
648}
649
David Tolnay14982012017-12-29 00:49:51 -0500650impl From<usize> for Index {
651 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700652 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500653 Index {
654 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700655 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500656 }
657 }
658}
659
660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl Eq for Index {}
662
David Tolnay14982012017-12-29 00:49:51 -0500663#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500664impl PartialEq for Index {
665 fn eq(&self, other: &Self) -> bool {
666 self.index == other.index
667 }
668}
669
David Tolnay14982012017-12-29 00:49:51 -0500670#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500671impl Hash for Index {
672 fn hash<H: Hasher>(&self, state: &mut H) {
673 self.index.hash(state);
674 }
675}
676
677#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700678ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800679 /// The `::<>` explicit type parameters passed to a method call:
680 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800681 ///
682 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500683 pub struct MethodTurbofish {
684 pub colon2_token: Token![::],
685 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500686 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500687 pub gt_token: Token![>],
688 }
689}
690
691#[cfg(feature = "full")]
692ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800693 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800694 ///
695 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500696 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800697 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500698 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800699 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500700 ///
701 /// NOTE: Identity expressions are represented as Type arguments, as
702 /// they are indistinguishable syntactically.
703 Const(Expr),
704 }
705}
706
707#[cfg(feature = "full")]
708ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800710 ///
711 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700712 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500713 /// Attributes tagged on the field.
714 pub attrs: Vec<Attribute>,
715
716 /// Name or index of the field.
717 pub member: Member,
718
David Tolnay5d7098a2017-12-29 01:35:24 -0500719 /// The colon in `Struct { x: x }`. If written in shorthand like
720 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500721 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500722
Alex Crichton62a0a592017-05-22 13:58:53 -0700723 /// Value of the field.
724 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700725 }
David Tolnay055a7042016-10-02 19:23:54 -0700726}
727
Michael Layzell734adb42017-06-07 16:58:31 -0400728#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700729ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800730 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800731 ///
732 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500733 pub struct Label {
734 pub name: Lifetime,
735 pub colon_token: Token![:],
736 }
737}
738
739#[cfg(feature = "full")]
740ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800742 ///
743 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700744 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500745 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700746 /// Statements in a block
747 pub stmts: Vec<Stmt>,
748 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700749}
750
Michael Layzell734adb42017-06-07 16:58:31 -0400751#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700752ast_enum! {
753 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800754 ///
755 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700756 pub enum Stmt {
757 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
Alex Crichton62a0a592017-05-22 13:58:53 -0700763 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700765
David Tolnaya454c8f2018-01-07 01:01:10 -0800766 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800767 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700768 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700769}
770
Michael Layzell734adb42017-06-07 16:58:31 -0400771#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700772ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800773 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800774 ///
775 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700776 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500777 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800778 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200779 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500780 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500781 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500782 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700783 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700784}
785
Michael Layzell734adb42017-06-07 16:58:31 -0400786#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700787ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800788 /// A pattern in a local binding, function signature, match expression, or
789 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800790 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800791 /// *This type is available if Syn is built with the `"full"` feature.*
792 ///
David Tolnay614a0142018-01-07 10:25:43 -0800793 /// # Syntax tree enum
794 ///
795 /// This type is a [syntax tree enum].
796 ///
797 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700798 // Clippy false positive
799 // https://github.com/Manishearth/rust-clippy/issues/1241
800 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
801 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800802 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800803 ///
804 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700805 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800806 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700807 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700808
David Tolnaya454c8f2018-01-07 01:01:10 -0800809 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800810 ///
811 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500813 pub by_ref: Option<Token![ref]>,
814 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500816 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700817 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700818
David Tolnaya454c8f2018-01-07 01:01:10 -0800819 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800820 ///
821 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700822 pub Struct(PatStruct {
823 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500824 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500825 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800826 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700828
David Tolnaya454c8f2018-01-07 01:01:10 -0800829 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800830 ///
831 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700832 pub TupleStruct(PatTupleStruct {
833 pub path: Path,
834 pub pat: PatTuple,
835 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700836
David Tolnaya454c8f2018-01-07 01:01:10 -0800837 /// A path pattern like `Color::Red`, optionally qualified with a
838 /// self-type.
839 ///
840 /// Unquailfied path patterns can legally refer to variants, structs,
841 /// constants or associated constants. Quailfied path patterns like
842 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
843 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800844 ///
845 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 pub Path(PatPath {
847 pub qself: Option<QSelf>,
848 pub path: Path,
849 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700850
David Tolnaya454c8f2018-01-07 01:01:10 -0800851 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800852 ///
853 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500855 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500857 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500858 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500859 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700860 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800861
862 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800863 ///
864 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800866 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500867 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700868 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800869
870 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800871 ///
872 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700873 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800874 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500875 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500876 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700877 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800878
879 /// A literal pattern: `0`.
880 ///
881 /// This holds an `Expr` rather than a `Lit` because negative numbers
882 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800883 ///
884 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700885 pub Lit(PatLit {
886 pub expr: Box<Expr>,
887 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800888
889 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800890 ///
891 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700892 pub Range(PatRange {
893 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700894 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500895 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700896 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800897
898 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800899 ///
900 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500903 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700904 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500905 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500906 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500907 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700908 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800909
910 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800911 ///
912 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500913 pub Macro(PatMacro {
914 pub mac: Macro,
915 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800916
917 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800918 ///
919 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500920 pub Verbatim(PatVerbatim #manual_extra_traits {
921 pub tts: TokenStream,
922 }),
923 }
924}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl Eq for PatVerbatim {}
928
David Tolnayc43b44e2017-12-30 23:55:54 -0500929#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500930impl PartialEq for PatVerbatim {
931 fn eq(&self, other: &Self) -> bool {
932 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
933 }
934}
935
David Tolnayc43b44e2017-12-30 23:55:54 -0500936#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500937impl Hash for PatVerbatim {
938 fn hash<H>(&self, state: &mut H)
939 where
940 H: Hasher,
941 {
942 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700943 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700944}
945
Michael Layzell734adb42017-06-07 16:58:31 -0400946#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700947ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800948 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700949 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700951 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500952 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500954 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800956 /// 0...10 => {
957 /// return true;
958 /// }
959 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800962 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500963 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800965 ///
966 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700967 pub struct Arm {
968 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200969 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500970 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500971 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200972 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700973 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800974 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700975 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700976}
977
Michael Layzell734adb42017-06-07 16:58:31 -0400978#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700979ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800980 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800981 ///
982 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700983 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700984 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800985 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800986 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800987 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800988 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700989 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700990}
991
Michael Layzell734adb42017-06-07 16:58:31 -0400992#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700993ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800994 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700995 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800996 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
997 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
David Tolnay461d98e2018-01-07 11:07:19 -0800998 ///
999 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -07001000 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -05001001 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -05001002 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001003 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001004 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001005 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001006}
1007
Michael Layzell3936ceb2017-07-08 00:28:36 -04001008#[cfg(any(feature = "parsing", feature = "printing"))]
1009#[cfg(feature = "full")]
Alex Crichton03b30272017-08-28 09:35:24 -07001010fn arm_expr_requires_comma(expr: &Expr) -> bool {
1011 // see https://github.com/rust-lang/rust/blob/eb8f2586e
1012 // /src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001013 match *expr {
1014 Expr::Unsafe(..)
1015 | Expr::Block(..)
1016 | Expr::If(..)
1017 | Expr::IfLet(..)
1018 | Expr::Match(..)
1019 | Expr::While(..)
1020 | Expr::WhileLet(..)
1021 | Expr::Loop(..)
1022 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001023 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001024 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001025 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001026 }
1027}
1028
David Tolnayb9c8e322016-09-23 20:48:37 -07001029#[cfg(feature = "parsing")]
1030pub mod parsing {
1031 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001032 use path;
David Tolnay2ccf32a2017-12-29 00:34:26 -05001033 #[cfg(feature = "full")]
David Tolnay056de302018-01-05 14:29:05 -08001034 use path::parsing::ty_no_eq_after;
David Tolnayb9c8e322016-09-23 20:48:37 -07001035
David Tolnay9389c382018-08-27 09:13:37 -07001036 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001037 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001038 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001039
David Tolnay9389c382018-08-27 09:13:37 -07001040 macro_rules! named2 {
1041 ($name:ident ($($arg:ident : $argty:ty),*) -> $ret:ty, $($rest:tt)*) => {
1042 fn $name(input: ParseStream $(, $arg : $argty)*) -> Result<$ret> {
1043 named!(_synom ($($arg : $argty),*) -> $ret, $($rest)*);
1044 input.step_cursor(|cursor| _synom(*cursor $(, $arg)*))
1045 }
1046 };
1047 ($name:ident -> $ret:ty, $($rest:tt)*) => {
1048 fn $name(input: ParseStream) -> Result<$ret> {
1049 named!(_synom -> $ret, $($rest)*);
1050 input.step_cursor(|cursor| _synom(*cursor))
1051 }
1052 };
1053 }
1054
David Tolnaybcf26022017-12-25 22:10:52 -05001055 // When we're parsing expressions which occur before blocks, like in an if
1056 // statement's condition, we cannot parse a struct literal.
1057 //
1058 // Struct literals are ambiguous in certain positions
1059 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001060 #[derive(Copy, Clone)]
1061 pub struct AllowStruct(bool);
1062
1063 #[derive(Copy, Clone)]
1064 pub struct AllowBlock(bool);
David Tolnayaf2557e2016-10-24 11:52:21 -07001065
David Tolnay9389c382018-08-27 09:13:37 -07001066 impl Parse for Expr {
1067 fn parse(input: ParseStream) -> Result<Self> {
1068 ambiguous_expr(input, AllowStruct(true), AllowBlock(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001069 }
1070 }
1071
Michael Layzell734adb42017-06-07 16:58:31 -04001072 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001073 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
1074 ambiguous_expr(input, AllowStruct(false), AllowBlock(true))
1075 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001076
David Tolnaybcf26022017-12-25 22:10:52 -05001077 // Parse an arbitrary expression.
Michael Layzell734adb42017-06-07 16:58:31 -04001078 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001079 fn ambiguous_expr(
1080 input: ParseStream,
1081 allow_struct: AllowStruct,
1082 allow_block: AllowBlock,
1083 ) -> Result<Expr> {
David Tolnay9389c382018-08-27 09:13:37 -07001084 assign_expr(input, allow_struct, allow_block)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001085 }
1086
Michael Layzell734adb42017-06-07 16:58:31 -04001087 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001088 fn ambiguous_expr(
1089 input: ParseStream,
1090 allow_struct: AllowStruct,
1091 allow_block: AllowBlock,
1092 ) -> Result<Expr> {
David Tolnay8c91b882017-12-28 23:04:32 -05001093 // NOTE: We intentionally skip assign_expr, placement_expr, and
David Tolnay9389c382018-08-27 09:13:37 -07001094 // range_expr as they are only parsed in full mode.
1095 or_expr(input, allow_struct, allow_block)
Michael Layzell734adb42017-06-07 16:58:31 -04001096 }
1097
David Tolnaybcf26022017-12-25 22:10:52 -05001098 // Parse a left-associative binary operator.
Michael Layzellb78f3b52017-06-04 19:03:03 -04001099 macro_rules! binop {
David Tolnay378175c2018-08-27 10:01:12 -07001100 ($name:ident, $next:ident, |$var:ident| $parse_op:expr) => {
David Tolnay60291082018-08-28 09:54:49 -07001101 fn $name(
1102 input: ParseStream,
1103 allow_struct: AllowStruct,
1104 allow_block: AllowBlock,
1105 ) -> Result<Expr> {
David Tolnay378175c2018-08-27 10:01:12 -07001106 let $var = input;
1107 let mut e: Expr = $next(input, allow_struct, allow_block)?;
1108 while let Some(op) = $parse_op {
1109 e = Expr::Binary(ExprBinary {
1110 attrs: Vec::new(),
1111 left: Box::new(e),
1112 op: op,
1113 right: Box::new($next(input, allow_struct, AllowBlock(true))?),
1114 });
David Tolnay9389c382018-08-27 09:13:37 -07001115 }
David Tolnay378175c2018-08-27 10:01:12 -07001116 Ok(e)
David Tolnay9389c382018-08-27 09:13:37 -07001117 }
David Tolnay60291082018-08-28 09:54:49 -07001118 };
David Tolnay54e854d2016-10-24 12:03:30 -07001119 }
David Tolnayb9c8e322016-09-23 20:48:37 -07001120
David Tolnaybcf26022017-12-25 22:10:52 -05001121 // <placement> = <placement> ..
1122 // <placement> += <placement> ..
1123 // <placement> -= <placement> ..
1124 // <placement> *= <placement> ..
1125 // <placement> /= <placement> ..
1126 // <placement> %= <placement> ..
1127 // <placement> ^= <placement> ..
1128 // <placement> &= <placement> ..
1129 // <placement> |= <placement> ..
1130 // <placement> <<= <placement> ..
1131 // <placement> >>= <placement> ..
1132 //
1133 // NOTE: This operator is right-associative.
Michael Layzell734adb42017-06-07 16:58:31 -04001134 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001135 fn assign_expr(
1136 input: ParseStream,
1137 allow_struct: AllowStruct,
1138 allow_block: AllowBlock,
1139 ) -> Result<Expr> {
David Tolnay1d2391c2018-08-27 10:29:28 -07001140 let mut e = placement_expr(input, allow_struct, allow_block)?;
1141 if input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1142 e = Expr::Assign(ExprAssign {
1143 attrs: Vec::new(),
1144 left: Box::new(e),
1145 eq_token: input.parse()?,
Michael Layzellb78f3b52017-06-04 19:03:03 -04001146 // Recurse into self to parse right-associative operator.
David Tolnay1d2391c2018-08-27 10:29:28 -07001147 right: Box::new(assign_expr(input, allow_struct, AllowBlock(true))?),
1148 });
1149 } else if input.peek(Token![+=])
1150 || input.peek(Token![-=])
1151 || input.peek(Token![*=])
1152 || input.peek(Token![/=])
1153 || input.peek(Token![%=])
1154 || input.peek(Token![^=])
1155 || input.peek(Token![&=])
1156 || input.peek(Token![|=])
1157 || input.peek(Token![<<=])
1158 || input.peek(Token![>>=])
1159 {
1160 e = Expr::AssignOp(ExprAssignOp {
1161 attrs: Vec::new(),
1162 left: Box::new(e),
1163 op: BinOp::parse_assign_op(input)?,
Michael Layzellb78f3b52017-06-04 19:03:03 -04001164 // Recurse into self to parse right-associative operator.
David Tolnay1d2391c2018-08-27 10:29:28 -07001165 right: Box::new(assign_expr(input, allow_struct, AllowBlock(true))?),
1166 });
1167 }
1168 Ok(e)
1169 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001170
David Tolnaybcf26022017-12-25 22:10:52 -05001171 // <range> <- <range> ..
1172 //
1173 // NOTE: The `in place { expr }` version of this syntax is parsed in
1174 // `atom_expr`, not here.
1175 //
1176 // NOTE: This operator is right-associative.
Michael Layzell734adb42017-06-07 16:58:31 -04001177 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001178 fn placement_expr(
1179 input: ParseStream,
1180 allow_struct: AllowStruct,
1181 allow_block: AllowBlock,
1182 ) -> Result<Expr> {
David Tolnay1da8c212018-08-27 10:35:50 -07001183 let mut e = range_expr(input, allow_struct, allow_block)?;
1184 if input.peek(Token![<-]) {
1185 e = Expr::InPlace(ExprInPlace {
1186 attrs: Vec::new(),
1187 place: Box::new(e),
1188 arrow_token: input.parse()?,
1189 value: Box::new(placement_expr(input, allow_struct, AllowBlock(true))?),
1190 });
1191 }
1192 Ok(e)
1193 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001194
David Tolnaybcf26022017-12-25 22:10:52 -05001195 // <or> ... <or> ..
1196 // <or> .. <or> ..
1197 // <or> ..
1198 //
1199 // NOTE: This is currently parsed oddly - I'm not sure of what the exact
1200 // rules are for parsing these expressions are, but this is not correct.
1201 // For example, `a .. b .. c` is not a legal expression. It should not
1202 // be parsed as either `(a .. b) .. c` or `a .. (b .. c)` apparently.
1203 //
1204 // NOTE: The form of ranges which don't include a preceding expression are
1205 // parsed by `atom_expr`, rather than by this function.
Michael Layzell734adb42017-06-07 16:58:31 -04001206 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001207 fn range_expr(
1208 input: ParseStream,
1209 allow_struct: AllowStruct,
1210 allow_block: AllowBlock,
1211 ) -> Result<Expr> {
David Tolnayc4c631e2018-08-27 10:44:37 -07001212 let mut e = or_expr(input, allow_struct, allow_block)?;
1213 while input.peek(Token![..]) {
1214 e = Expr::Range(ExprRange {
1215 attrs: Vec::new(),
1216 from: Some(Box::new(e)),
1217 limits: input.parse()?,
1218 to: {
1219 if input.is_empty()
1220 || input.peek(Token![,])
1221 || input.peek(Token![;])
1222 || !allow_struct.0 && input.peek(token::Brace)
1223 {
1224 None
1225 } else {
1226 // We don't want to allow blocks here if we don't allow
David Tolnay60291082018-08-28 09:54:49 -07001227 // structs.
1228 Some(Box::new(or_expr(
1229 input,
1230 allow_struct,
1231 AllowBlock(allow_struct.0),
1232 )?))
David Tolnayc4c631e2018-08-27 10:44:37 -07001233 }
1234 },
1235 });
1236 }
1237 Ok(e)
1238 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001239
David Tolnaybcf26022017-12-25 22:10:52 -05001240 // <and> || <and> ...
David Tolnay60291082018-08-28 09:54:49 -07001241 binop!(or_expr, and_expr, |input| if input.peek(Token![||]) {
1242 Some(BinOp::Or(input.parse()?))
1243 } else {
1244 None
David Tolnay378175c2018-08-27 10:01:12 -07001245 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001246
David Tolnaybcf26022017-12-25 22:10:52 -05001247 // <compare> && <compare> ...
David Tolnay60291082018-08-28 09:54:49 -07001248 binop!(and_expr, compare_expr, |input| if input.peek(Token![&&]) {
1249 Some(BinOp::And(input.parse()?))
1250 } else {
1251 None
David Tolnay378175c2018-08-27 10:01:12 -07001252 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001253
David Tolnaybcf26022017-12-25 22:10:52 -05001254 // <bitor> == <bitor> ...
1255 // <bitor> != <bitor> ...
1256 // <bitor> >= <bitor> ...
1257 // <bitor> <= <bitor> ...
1258 // <bitor> > <bitor> ...
1259 // <bitor> < <bitor> ...
1260 //
1261 // NOTE: This operator appears to be parsed as left-associative, but errors
1262 // if it is used in a non-associative manner.
David Tolnay378175c2018-08-27 10:01:12 -07001263 binop!(compare_expr, bitor_expr, |input| {
1264 if input.peek(Token![==]) {
1265 Some(BinOp::Eq(input.parse()?))
1266 } else if input.peek(Token![!=]) {
1267 Some(BinOp::Ne(input.parse()?))
1268 // must be before `<`
1269 } else if input.peek(Token![<=]) {
1270 Some(BinOp::Le(input.parse()?))
1271 // must be before `>`
1272 } else if input.peek(Token![>=]) {
1273 Some(BinOp::Ge(input.parse()?))
1274 } else if input.peek(Token![<]) && !input.peek(Token![<<]) && !input.peek(Token![<-]) {
1275 Some(BinOp::Lt(input.parse()?))
1276 } else if input.peek(Token![>]) && !input.peek(Token![>>]) {
1277 Some(BinOp::Gt(input.parse()?))
1278 } else {
1279 None
1280 }
1281 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001282
David Tolnaybcf26022017-12-25 22:10:52 -05001283 // <bitxor> | <bitxor> ...
David Tolnay378175c2018-08-27 10:01:12 -07001284 binop!(bitor_expr, bitxor_expr, |input| {
1285 if input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
1286 Some(BinOp::BitOr(input.parse()?))
1287 } else {
1288 None
1289 }
1290 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001291
David Tolnaybcf26022017-12-25 22:10:52 -05001292 // <bitand> ^ <bitand> ...
David Tolnay378175c2018-08-27 10:01:12 -07001293 binop!(bitxor_expr, bitand_expr, |input| {
1294 if input.peek(Token![^]) && !input.peek(Token![^=]) {
1295 Some(BinOp::BitXor(input.parse()?))
1296 } else {
1297 None
1298 }
1299 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001300
David Tolnaybcf26022017-12-25 22:10:52 -05001301 // <shift> & <shift> ...
David Tolnay378175c2018-08-27 10:01:12 -07001302 binop!(bitand_expr, shift_expr, |input| {
1303 if input.peek(Token![&]) && !input.peek(Token![&&]) && !input.peek(Token![&=]) {
1304 Some(BinOp::BitAnd(input.parse()?))
1305 } else {
1306 None
1307 }
1308 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001309
David Tolnaybcf26022017-12-25 22:10:52 -05001310 // <arith> << <arith> ...
1311 // <arith> >> <arith> ...
David Tolnay378175c2018-08-27 10:01:12 -07001312 binop!(shift_expr, arith_expr, |input| {
1313 if input.peek(Token![<<]) && !input.peek(Token![<<=]) {
1314 Some(BinOp::Shl(input.parse()?))
1315 } else if input.peek(Token![>>]) && !input.peek(Token![>>=]) {
1316 Some(BinOp::Shr(input.parse()?))
1317 } else {
1318 None
1319 }
1320 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001321
David Tolnaybcf26022017-12-25 22:10:52 -05001322 // <term> + <term> ...
1323 // <term> - <term> ...
David Tolnay378175c2018-08-27 10:01:12 -07001324 binop!(arith_expr, term_expr, |input| {
1325 if input.peek(Token![+]) && !input.peek(Token![+=]) {
1326 Some(BinOp::Add(input.parse()?))
1327 } else if input.peek(Token![-]) && !input.peek(Token![-=]) {
1328 Some(BinOp::Sub(input.parse()?))
1329 } else {
1330 None
1331 }
1332 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001333
David Tolnaybcf26022017-12-25 22:10:52 -05001334 // <cast> * <cast> ...
1335 // <cast> / <cast> ...
1336 // <cast> % <cast> ...
David Tolnay378175c2018-08-27 10:01:12 -07001337 binop!(term_expr, cast_expr, |input| {
1338 if input.peek(Token![*]) && !input.peek(Token![*=]) {
1339 Some(BinOp::Mul(input.parse()?))
1340 } else if input.peek(Token![/]) && !input.peek(Token![/=]) {
1341 Some(BinOp::Div(input.parse()?))
1342 } else if input.peek(Token![%]) && !input.peek(Token![%=]) {
1343 Some(BinOp::Rem(input.parse()?))
1344 } else {
1345 None
1346 }
1347 });
Michael Layzellb78f3b52017-06-04 19:03:03 -04001348
David Tolnaybcf26022017-12-25 22:10:52 -05001349 // <unary> as <ty>
1350 // <unary> : <ty>
David Tolnay0cf94f22017-12-28 23:46:26 -05001351 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001352 fn cast_expr(
1353 input: ParseStream,
1354 allow_struct: AllowStruct,
1355 allow_block: AllowBlock,
1356 ) -> Result<Expr> {
David Tolnayaf5a8112018-08-27 10:52:20 -07001357 let mut e = unary_expr(input, allow_struct, allow_block)?;
1358 loop {
1359 if input.peek(Token![as]) {
1360 e = Expr::Cast(ExprCast {
1361 attrs: Vec::new(),
1362 expr: Box::new(e),
1363 as_token: input.parse()?,
1364 // We can't accept `A + B` in cast expressions, as it's
1365 // ambiguous with the + expression.
1366 ty: Box::new(input.call(Type::without_plus)?),
1367 });
1368 } else if input.peek(Token![:]) {
1369 e = Expr::Type(ExprType {
1370 attrs: Vec::new(),
1371 expr: Box::new(e),
1372 colon_token: input.parse()?,
1373 // We can't accept `A + B` in cast expressions, as it's
1374 // ambiguous with the + expression.
1375 ty: Box::new(input.call(Type::without_plus)?),
1376 });
1377 } else {
1378 break;
1379 }
1380 }
1381 Ok(e)
1382 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001383
David Tolnay0cf94f22017-12-28 23:46:26 -05001384 // <unary> as <ty>
1385 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001386 fn cast_expr(
1387 input: ParseStream,
1388 allow_struct: AllowStruct,
1389 allow_block: AllowBlock,
1390 ) -> Result<Expr> {
David Tolnayaf5a8112018-08-27 10:52:20 -07001391 let mut e = unary_expr(input, allow_struct, allow_block)?;
1392 while input.peek(Token![as]) {
1393 e = Expr::Cast(ExprCast {
1394 attrs: Vec::new(),
1395 expr: Box::new(e),
1396 as_token: input.parse()?,
1397 // We can't accept `A + B` in cast expressions, as it's
1398 // ambiguous with the + expression.
1399 ty: Box::new(input.call(Type::without_plus)?),
1400 });
1401 }
1402 Ok(e)
1403 }
David Tolnay0cf94f22017-12-28 23:46:26 -05001404
David Tolnaybcf26022017-12-25 22:10:52 -05001405 // <UnOp> <trailer>
1406 // & <trailer>
1407 // &mut <trailer>
1408 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001409 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001410 fn unary_expr(
1411 input: ParseStream,
1412 allow_struct: AllowStruct,
1413 allow_block: AllowBlock,
1414 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001415 let ahead = input.fork();
1416 ahead.call(Attribute::parse_outer)?;
1417 if ahead.peek(Token![&])
1418 || ahead.peek(Token![box])
1419 || ahead.peek(Token![*])
1420 || ahead.peek(Token![!])
1421 || ahead.peek(Token![-])
1422 {
1423 let attrs = input.call(Attribute::parse_outer)?;
1424 if input.peek(Token![&]) {
1425 Ok(Expr::Reference(ExprReference {
1426 attrs: attrs,
1427 and_token: input.parse()?,
1428 mutability: input.parse()?,
1429 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1430 }))
1431 } else if input.peek(Token![box]) {
1432 Ok(Expr::Box(ExprBox {
1433 attrs: attrs,
1434 box_token: input.parse()?,
1435 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1436 }))
1437 } else {
1438 Ok(Expr::Unary(ExprUnary {
1439 attrs: attrs,
1440 op: input.parse()?,
1441 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1442 }))
1443 }
1444 } else {
1445 trailer_expr(input, allow_struct, allow_block)
1446 }
1447 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001448
Michael Layzell734adb42017-06-07 16:58:31 -04001449 // XXX: This duplication is ugly
1450 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001451 fn unary_expr(
1452 input: ParseStream,
1453 allow_struct: AllowStruct,
1454 allow_block: AllowBlock,
1455 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001456 let ahead = input.fork();
1457 ahead.call(Attribute::parse_outer)?;
1458 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1459 Ok(Expr::Unary(ExprUnary {
1460 attrs: input.call(Attribute::parse_outer)?,
1461 op: input.parse()?,
1462 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1463 }))
1464 } else {
1465 trailer_expr(input, allow_struct, allow_block)
1466 }
1467 }
Michael Layzell734adb42017-06-07 16:58:31 -04001468
David Tolnayd997aef2018-07-21 18:42:31 -07001469 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001470 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1471 let mut outer = Vec::new();
1472 let mut inner = Vec::new();
1473 for attr in mem::replace(attrs, Vec::new()) {
1474 match attr.style {
1475 AttrStyle::Outer => outer.push(attr),
1476 AttrStyle::Inner(_) => inner.push(attr),
1477 }
1478 }
1479 *attrs = inner;
1480 outer
1481 }
1482
David Tolnaybcf26022017-12-25 22:10:52 -05001483 // <atom> (..<args>) ...
1484 // <atom> . <ident> (..<args>) ...
1485 // <atom> . <ident> ...
1486 // <atom> . <lit> ...
1487 // <atom> [ <expr> ] ...
1488 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001489 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001490 fn trailer_expr(
1491 input: ParseStream,
1492 allow_struct: AllowStruct,
1493 allow_block: AllowBlock,
1494 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001495 let mut e = atom_expr(input, allow_struct, allow_block)?;
1496
1497 let mut attrs = e.replace_attrs(Vec::new());
1498 let outer_attrs = take_outer(&mut attrs);
1499 e.replace_attrs(attrs);
1500
1501 loop {
1502 if input.peek(token::Paren) {
1503 let content;
1504 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001505 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001506 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001507 paren_token: parenthesized!(content in input),
1508 args: content.parse_terminated(<Expr as Parse>::parse)?,
1509 });
1510 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1511 let dot_token: Token![.] = input.parse()?;
1512 let member: Member = input.parse()?;
1513 let turbofish = if member.is_named() && input.peek(Token![::]) {
1514 Some(MethodTurbofish {
1515 colon2_token: input.parse()?,
1516 lt_token: input.parse()?,
1517 args: {
1518 let mut args = Punctuated::new();
1519 loop {
1520 if input.peek(Token![>]) {
1521 break;
1522 }
1523 let value = input.parse()?;
1524 args.push_value(value);
1525 if input.peek(Token![>]) {
1526 break;
1527 }
1528 let punct = input.parse()?;
1529 args.push_punct(punct);
1530 }
1531 args
1532 },
1533 gt_token: input.parse()?,
1534 })
1535 } else {
1536 None
1537 };
1538
1539 if turbofish.is_some() || input.peek(token::Paren) {
1540 if let Member::Named(method) = member {
1541 let content;
1542 e = Expr::MethodCall(ExprMethodCall {
1543 attrs: Vec::new(),
1544 receiver: Box::new(e),
1545 dot_token: dot_token,
1546 method: method,
1547 turbofish: turbofish,
1548 paren_token: parenthesized!(content in input),
1549 args: content.parse_terminated(<Expr as Parse>::parse)?,
1550 });
1551 continue;
1552 }
1553 }
1554
1555 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001556 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001557 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001558 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001559 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001560 });
1561 } else if input.peek(token::Bracket) {
1562 let content;
1563 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001564 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001565 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001566 bracket_token: bracketed!(content in input),
1567 index: content.parse()?,
1568 });
1569 } else if input.peek(Token![?]) {
1570 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001571 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001572 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001573 question_token: input.parse()?,
1574 });
1575 } else {
1576 break;
1577 }
1578 }
1579
1580 let mut attrs = outer_attrs;
1581 attrs.extend(e.replace_attrs(Vec::new()));
1582 e.replace_attrs(attrs);
1583 Ok(e)
1584 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001585
Michael Layzell734adb42017-06-07 16:58:31 -04001586 // XXX: Duplication == ugly
1587 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001588 fn trailer_expr(
1589 input: ParseStream,
1590 allow_struct: AllowStruct,
1591 allow_block: AllowBlock,
1592 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001593 let mut e = atom_expr(input, allow_struct, allow_block)?;
1594
1595 loop {
1596 if input.peek(token::Paren) {
1597 let content;
1598 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001599 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001600 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001601 paren_token: parenthesized!(content in input),
1602 args: content.parse_terminated(<Expr as Parse>::parse)?,
1603 });
1604 } else if input.peek(Token![.]) {
1605 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001606 attrs: Vec::new(),
1607 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001608 dot_token: input.parse()?,
1609 member: input.parse()?,
1610 });
1611 } else if input.peek(token::Bracket) {
1612 let content;
1613 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001614 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001615 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001616 bracket_token: bracketed!(content in input),
1617 index: content.parse()?,
1618 });
1619 } else {
1620 break;
1621 }
1622 }
1623
1624 Ok(e)
1625 }
Michael Layzell734adb42017-06-07 16:58:31 -04001626
David Tolnaya454c8f2018-01-07 01:01:10 -08001627 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001628 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001629 #[cfg(feature = "full")]
David Tolnay9389c382018-08-27 09:13:37 -07001630 named2!(atom_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, alt!(
David Tolnay8c91b882017-12-28 23:04:32 -05001631 syn!(ExprGroup) => { Expr::Group } // must be placed first
Michael Layzell93c36282017-06-04 20:43:14 -04001632 |
David Tolnay8c91b882017-12-28 23:04:32 -05001633 syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
Michael Layzellb78f3b52017-06-04 19:03:03 -04001634 |
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001635 // must be before ExprStruct
David Tolnay02a9c6f2018-08-24 18:58:45 -04001636 syn!(ExprAsync) => { Expr::Async }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001637 |
David Tolnayf7177052018-08-24 15:31:50 -04001638 // must be before ExprStruct
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001639 syn!(ExprTryBlock) => { Expr::TryBlock }
David Tolnayf7177052018-08-24 15:31:50 -04001640 |
Michael Layzellb78f3b52017-06-04 19:03:03 -04001641 // must be before expr_path
David Tolnay9389c382018-08-27 09:13:37 -07001642 cond_reduce!(allow_struct.0, syn!(ExprStruct)) => { Expr::Struct }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001643 |
David Tolnay8c91b882017-12-28 23:04:32 -05001644 syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
Michael Layzellb78f3b52017-06-04 19:03:03 -04001645 |
David Tolnay8c91b882017-12-28 23:04:32 -05001646 syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001647 |
David Tolnay60291082018-08-28 09:54:49 -07001648 shim!(expr_break, allow_struct) => { Expr::Break } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001649 |
David Tolnay8c91b882017-12-28 23:04:32 -05001650 syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001651 |
David Tolnay60291082018-08-28 09:54:49 -07001652 shim!(expr_ret, allow_struct) => { Expr::Return } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001653 |
David Tolnay8c91b882017-12-28 23:04:32 -05001654 syn!(ExprArray) => { Expr::Array }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001655 |
David Tolnay8c91b882017-12-28 23:04:32 -05001656 syn!(ExprTuple) => { Expr::Tuple }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001657 |
David Tolnay8c91b882017-12-28 23:04:32 -05001658 syn!(ExprIf) => { Expr::If }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001659 |
David Tolnay8c91b882017-12-28 23:04:32 -05001660 syn!(ExprIfLet) => { Expr::IfLet }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001661 |
David Tolnay8c91b882017-12-28 23:04:32 -05001662 syn!(ExprWhile) => { Expr::While }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001663 |
David Tolnay8c91b882017-12-28 23:04:32 -05001664 syn!(ExprWhileLet) => { Expr::WhileLet }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001665 |
David Tolnay8c91b882017-12-28 23:04:32 -05001666 syn!(ExprForLoop) => { Expr::ForLoop }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001667 |
David Tolnay8c91b882017-12-28 23:04:32 -05001668 syn!(ExprLoop) => { Expr::Loop }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001669 |
David Tolnay8c91b882017-12-28 23:04:32 -05001670 syn!(ExprMatch) => { Expr::Match }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001671 |
David Tolnay8c91b882017-12-28 23:04:32 -05001672 syn!(ExprYield) => { Expr::Yield }
Alex Crichtonfe110462017-06-01 12:49:27 -07001673 |
David Tolnay8c91b882017-12-28 23:04:32 -05001674 syn!(ExprUnsafe) => { Expr::Unsafe }
Nika Layzell640832a2017-12-04 13:37:09 -05001675 |
David Tolnay60291082018-08-28 09:54:49 -07001676 shim!(expr_closure, allow_struct) => { Expr::Closure }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001677 |
David Tolnay9389c382018-08-27 09:13:37 -07001678 cond_reduce!(allow_block.0, syn!(ExprBlock)) => { Expr::Block }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001679 |
1680 // NOTE: This is the prefix-form of range
David Tolnay60291082018-08-28 09:54:49 -07001681 shim!(expr_range, allow_struct) => { Expr::Range }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001682 |
David Tolnay8c91b882017-12-28 23:04:32 -05001683 syn!(ExprPath) => { Expr::Path }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001684 |
David Tolnay8c91b882017-12-28 23:04:32 -05001685 syn!(ExprRepeat) => { Expr::Repeat }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001686 ));
1687
Michael Layzell734adb42017-06-07 16:58:31 -04001688 #[cfg(not(feature = "full"))]
David Tolnay9389c382018-08-27 09:13:37 -07001689 named2!(atom_expr(_allow_struct: AllowStruct, _allow_block: AllowBlock) -> Expr, alt!(
David Tolnaye98775f2017-12-28 23:17:00 -05001690 syn!(ExprLit) => { Expr::Lit }
Michael Layzell734adb42017-06-07 16:58:31 -04001691 |
David Tolnay9374bc02018-01-27 18:49:36 -08001692 syn!(ExprParen) => { Expr::Paren }
1693 |
David Tolnay8c91b882017-12-28 23:04:32 -05001694 syn!(ExprPath) => { Expr::Path }
Michael Layzell734adb42017-06-07 16:58:31 -04001695 ));
1696
Michael Layzell734adb42017-06-07 16:58:31 -04001697 #[cfg(feature = "full")]
David Tolnay9389c382018-08-27 09:13:37 -07001698 named2!(expr_nosemi -> Expr, do_parse!(
David Tolnay313a36f2018-04-29 20:13:04 -07001699 nosemi: alt!(
1700 syn!(ExprIf) => { Expr::If }
1701 |
1702 syn!(ExprIfLet) => { Expr::IfLet }
1703 |
1704 syn!(ExprWhile) => { Expr::While }
1705 |
1706 syn!(ExprWhileLet) => { Expr::WhileLet }
1707 |
1708 syn!(ExprForLoop) => { Expr::ForLoop }
1709 |
1710 syn!(ExprLoop) => { Expr::Loop }
1711 |
1712 syn!(ExprMatch) => { Expr::Match }
1713 |
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001714 syn!(ExprTryBlock) => { Expr::TryBlock }
David Tolnay313a36f2018-04-29 20:13:04 -07001715 |
1716 syn!(ExprYield) => { Expr::Yield }
1717 |
1718 syn!(ExprUnsafe) => { Expr::Unsafe }
1719 |
1720 syn!(ExprBlock) => { Expr::Block }
1721 ) >>
1722 // If the next token is a `.` or a `?` it is special-cased to parse
1723 // as an expression instead of a blockexpression.
1724 not!(punct!(.)) >>
1725 not!(punct!(?)) >>
David Tolnay83ddebb2018-05-05 00:29:13 -07001726 (nosemi)
David Tolnay313a36f2018-04-29 20:13:04 -07001727 ));
Michael Layzell35418782017-06-07 09:20:25 -04001728
David Tolnay60291082018-08-28 09:54:49 -07001729 impl Parse for ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001730 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001731 fn parse(input: ParseStream) -> Result<Self> {
1732 Ok(ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001733 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001734 lit: input.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001735 })
David Tolnay60291082018-08-28 09:54:49 -07001736 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001737
1738 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001739 fn parse(input: ParseStream) -> Result<Self> {
1740 Ok(ExprLit {
1741 attrs: input.call(Attribute::parse_outer)?,
1742 lit: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001743 })
David Tolnay60291082018-08-28 09:54:49 -07001744 }
David Tolnay8c91b882017-12-28 23:04:32 -05001745 }
1746
1747 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001748 impl Parse for ExprMacro {
1749 fn parse(input: ParseStream) -> Result<Self> {
1750 Ok(ExprMacro {
1751 attrs: input.call(Attribute::parse_outer)?,
1752 mac: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001753 })
David Tolnay60291082018-08-28 09:54:49 -07001754 }
David Tolnay8c91b882017-12-28 23:04:32 -05001755 }
1756
David Tolnaye98775f2017-12-28 23:17:00 -05001757 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001758 impl Parse for ExprGroup {
1759 fn parse(input: ParseStream) -> Result<Self> {
1760 let content;
1761 Ok(ExprGroup {
David Tolnay8c91b882017-12-28 23:04:32 -05001762 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001763 group_token: grouped!(content in input),
1764 expr: content.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001765 })
David Tolnay60291082018-08-28 09:54:49 -07001766 }
Michael Layzell93c36282017-06-04 20:43:14 -04001767 }
1768
David Tolnay60291082018-08-28 09:54:49 -07001769 impl Parse for ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001770 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001771 fn parse(input: ParseStream) -> Result<Self> {
1772 let content;
1773 Ok(ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001774 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001775 paren_token: parenthesized!(content in input),
1776 expr: content.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001777 })
David Tolnay60291082018-08-28 09:54:49 -07001778 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001779
1780 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001781 fn parse(input: ParseStream) -> Result<Self> {
1782 let outer_attrs = input.call(Attribute::parse_outer)?;
1783
1784 let content;
1785 let paren_token = parenthesized!(content in input);
1786 let inner_attrs = content.call(Attribute::parse_inner)?;
1787 let expr: Expr = content.parse()?;
1788
1789 Ok(ExprParen {
David Tolnay5d314dc2018-07-21 16:40:01 -07001790 attrs: {
1791 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001792 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001793 attrs
1794 },
David Tolnay60291082018-08-28 09:54:49 -07001795 paren_token: paren_token,
1796 expr: Box::new(expr),
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001797 })
David Tolnay60291082018-08-28 09:54:49 -07001798 }
Alex Crichton954046c2017-05-30 21:49:42 -07001799 }
David Tolnay89e05672016-10-02 14:39:42 -07001800
Michael Layzell734adb42017-06-07 16:58:31 -04001801 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001802 impl Parse for ExprArray {
1803 fn parse(input: ParseStream) -> Result<Self> {
1804 let outer_attrs = input.call(Attribute::parse_outer)?;
1805
1806 let content;
1807 let bracket_token = bracketed!(content in input);
1808 let inner_attrs = content.call(Attribute::parse_inner)?;
1809 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1810
1811 Ok(ExprArray {
David Tolnay5d314dc2018-07-21 16:40:01 -07001812 attrs: {
1813 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001814 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001815 attrs
1816 },
David Tolnay60291082018-08-28 09:54:49 -07001817 bracket_token: bracket_token,
1818 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001819 })
David Tolnay60291082018-08-28 09:54:49 -07001820 }
Alex Crichton954046c2017-05-30 21:49:42 -07001821 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001822
Michael Layzell734adb42017-06-07 16:58:31 -04001823 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07001824 impl Parse for GenericMethodArgument {
David Tolnayd60cfec2017-12-29 00:21:38 -05001825 // TODO parse const generics as well
David Tolnay1501f7e2018-08-27 14:21:03 -07001826 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07001827 input
1828 .parse_synom(ty_no_eq_after)
1829 .map(GenericMethodArgument::Type)
David Tolnay1501f7e2018-08-27 14:21:03 -07001830 }
David Tolnayd60cfec2017-12-29 00:21:38 -05001831 }
1832
1833 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001834 impl Parse for ExprTuple {
1835 fn parse(input: ParseStream) -> Result<Self> {
1836 let outer_attrs = input.call(Attribute::parse_outer)?;
1837
1838 let content;
1839 let paren_token = parenthesized!(content in input);
1840 let inner_attrs = content.call(Attribute::parse_inner)?;
1841 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1842
1843 Ok(ExprTuple {
David Tolnay5d314dc2018-07-21 16:40:01 -07001844 attrs: {
1845 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001846 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001847 attrs
1848 },
David Tolnay60291082018-08-28 09:54:49 -07001849 paren_token: paren_token,
1850 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001851 })
David Tolnay60291082018-08-28 09:54:49 -07001852 }
Alex Crichton954046c2017-05-30 21:49:42 -07001853 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001854
Michael Layzell734adb42017-06-07 16:58:31 -04001855 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001856 impl Parse for ExprIfLet {
1857 fn parse(input: ParseStream) -> Result<Self> {
1858 Ok(ExprIfLet {
David Tolnay8c91b882017-12-28 23:04:32 -05001859 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001860 if_token: input.parse()?,
1861 let_token: input.parse()?,
1862 pats: {
1863 let mut pats = Punctuated::new();
1864 let value: Pat = input.parse()?;
1865 pats.push_value(value);
1866 while input.peek(Token![|])
1867 && !input.peek(Token![||])
1868 && !input.peek(Token![|=])
1869 {
1870 let punct = input.parse()?;
1871 pats.push_punct(punct);
1872 let value: Pat = input.parse()?;
1873 pats.push_value(value);
1874 }
1875 pats
Michael Layzell92639a52017-06-01 00:07:44 -04001876 },
David Tolnay60291082018-08-28 09:54:49 -07001877 eq_token: input.parse()?,
1878 expr: Box::new(input.call(expr_no_struct)?),
1879 then_branch: input.parse()?,
1880 else_branch: {
1881 if input.peek(Token![else]) {
1882 Some(input.call(else_block)?)
1883 } else {
1884 None
1885 }
1886 },
Michael Layzell92639a52017-06-01 00:07:44 -04001887 })
David Tolnay60291082018-08-28 09:54:49 -07001888 }
David Tolnay29f9ce12016-10-02 20:58:40 -07001889 }
1890
Michael Layzell734adb42017-06-07 16:58:31 -04001891 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001892 impl Parse for ExprIf {
1893 fn parse(input: ParseStream) -> Result<Self> {
1894 Ok(ExprIf {
David Tolnay8c91b882017-12-28 23:04:32 -05001895 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001896 if_token: input.parse()?,
1897 cond: Box::new(input.call(expr_no_struct)?),
1898 then_branch: input.parse()?,
1899 else_branch: {
1900 if input.peek(Token![else]) {
1901 Some(input.call(else_block)?)
1902 } else {
1903 None
1904 }
Michael Layzell92639a52017-06-01 00:07:44 -04001905 },
Michael Layzell92639a52017-06-01 00:07:44 -04001906 })
David Tolnay60291082018-08-28 09:54:49 -07001907 }
Alex Crichton954046c2017-05-30 21:49:42 -07001908 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001909
Michael Layzell734adb42017-06-07 16:58:31 -04001910 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001911 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1912 let else_token: Token![else] = input.parse()?;
1913
1914 let lookahead = input.lookahead1();
1915 let else_branch = if input.peek(Token![if]) {
1916 if input.peek2(Token![let]) {
1917 input.parse().map(Expr::IfLet)?
1918 } else {
1919 input.parse().map(Expr::If)?
1920 }
1921 } else if input.peek(token::Brace) {
1922 Expr::Block(ExprBlock {
1923 attrs: Vec::new(),
1924 label: None,
1925 block: input.parse()?,
1926 })
1927 } else {
1928 return Err(lookahead.error());
1929 };
1930
1931 Ok((else_token, Box::new(else_branch)))
1932 }
David Tolnay939766a2016-09-23 23:48:12 -07001933
Michael Layzell734adb42017-06-07 16:58:31 -04001934 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001935 impl Parse for ExprForLoop {
1936 fn parse(input: ParseStream) -> Result<Self> {
1937 let outer_attrs = input.call(Attribute::parse_outer)?;
1938 let label: Option<Label> = input.parse()?;
1939 let for_token: Token![for] = input.parse()?;
1940 let pat: Pat = input.parse()?;
1941 let in_token: Token![in] = input.parse()?;
1942 let expr: Expr = input.call(expr_no_struct)?;
1943
1944 let content;
1945 let brace_token = braced!(content in input);
1946 let inner_attrs = content.call(Attribute::parse_inner)?;
1947 let stmts = content.call(Block::parse_within)?;
1948
1949 Ok(ExprForLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07001950 attrs: {
1951 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001952 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001953 attrs
1954 },
David Tolnaybcd498f2017-12-29 12:02:33 -05001955 label: label,
David Tolnay60291082018-08-28 09:54:49 -07001956 for_token: for_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001957 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07001958 in_token: in_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001959 expr: Box::new(expr),
1960 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001961 brace_token: brace_token,
1962 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07001963 },
Michael Layzell92639a52017-06-01 00:07:44 -04001964 })
David Tolnay60291082018-08-28 09:54:49 -07001965 }
Alex Crichton954046c2017-05-30 21:49:42 -07001966 }
Gregory Katze5f35682016-09-27 14:20:55 -04001967
Michael Layzell734adb42017-06-07 16:58:31 -04001968 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001969 impl Parse for ExprLoop {
1970 fn parse(input: ParseStream) -> Result<Self> {
1971 let outer_attrs = input.call(Attribute::parse_outer)?;
1972 let label: Option<Label> = input.parse()?;
1973 let loop_token: Token![loop] = input.parse()?;
1974
1975 let content;
1976 let brace_token = braced!(content in input);
1977 let inner_attrs = content.call(Attribute::parse_inner)?;
1978 let stmts = content.call(Block::parse_within)?;
1979
1980 Ok(ExprLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07001981 attrs: {
1982 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001983 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001984 attrs
1985 },
David Tolnaybcd498f2017-12-29 12:02:33 -05001986 label: label,
David Tolnay60291082018-08-28 09:54:49 -07001987 loop_token: loop_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001988 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001989 brace_token: brace_token,
1990 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07001991 },
Michael Layzell92639a52017-06-01 00:07:44 -04001992 })
David Tolnay60291082018-08-28 09:54:49 -07001993 }
Alex Crichton954046c2017-05-30 21:49:42 -07001994 }
1995
Michael Layzell734adb42017-06-07 16:58:31 -04001996 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001997 impl Parse for ExprMatch {
1998 fn parse(input: ParseStream) -> Result<Self> {
1999 let outer_attrs = input.call(Attribute::parse_outer)?;
2000 let match_token: Token![match] = input.parse()?;
2001 let expr = expr_no_struct(input)?;
2002
2003 let content;
2004 let brace_token = braced!(content in input);
2005 let inner_attrs = content.call(Attribute::parse_inner)?;
2006
2007 let mut arms = Vec::new();
2008 while !content.is_empty() {
2009 arms.push(content.parse()?);
2010 }
2011
2012 Ok(ExprMatch {
David Tolnay5d314dc2018-07-21 16:40:01 -07002013 attrs: {
2014 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002015 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002016 attrs
2017 },
David Tolnay60291082018-08-28 09:54:49 -07002018 match_token: match_token,
2019 expr: Box::new(expr),
2020 brace_token: brace_token,
2021 arms: arms,
Michael Layzell92639a52017-06-01 00:07:44 -04002022 })
David Tolnay60291082018-08-28 09:54:49 -07002023 }
Alex Crichton954046c2017-05-30 21:49:42 -07002024 }
David Tolnay1978c672016-10-27 22:05:52 -07002025
Michael Layzell734adb42017-06-07 16:58:31 -04002026 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002027 impl Parse for ExprTryBlock {
2028 fn parse(input: ParseStream) -> Result<Self> {
2029 Ok(ExprTryBlock {
David Tolnay8c91b882017-12-28 23:04:32 -05002030 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002031 try_token: input.parse()?,
2032 block: input.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05002033 })
David Tolnay60291082018-08-28 09:54:49 -07002034 }
Alex Crichton954046c2017-05-30 21:49:42 -07002035 }
Arnavion02ef13f2017-04-25 00:54:31 -07002036
Michael Layzell734adb42017-06-07 16:58:31 -04002037 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002038 impl Parse for ExprYield {
2039 fn parse(input: ParseStream) -> Result<Self> {
2040 Ok(ExprYield {
David Tolnay8c91b882017-12-28 23:04:32 -05002041 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002042 yield_token: input.parse()?,
2043 expr: {
2044 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2045 Some(input.parse()?)
2046 } else {
2047 None
2048 }
2049 },
Alex Crichtonfe110462017-06-01 12:49:27 -07002050 })
David Tolnay60291082018-08-28 09:54:49 -07002051 }
Alex Crichtonfe110462017-06-01 12:49:27 -07002052 }
2053
2054 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002055 impl Parse for Arm {
2056 fn parse(input: ParseStream) -> Result<Self> {
2057 let requires_comma;
2058 Ok(Arm {
2059 attrs: input.call(Attribute::parse_outer)?,
2060 leading_vert: input.parse()?,
2061 pats: {
2062 let mut pats = Punctuated::new();
2063 let value: Pat = input.parse()?;
2064 pats.push_value(value);
2065 loop {
2066 if !input.peek(Token![|]) {
2067 break;
2068 }
2069 let punct = input.parse()?;
2070 pats.push_punct(punct);
2071 let value: Pat = input.parse()?;
2072 pats.push_value(value);
2073 }
2074 pats
2075 },
2076 guard: {
2077 if input.peek(Token![if]) {
2078 let if_token: Token![if] = input.parse()?;
2079 let guard: Expr = input.parse()?;
2080 Some((if_token, Box::new(guard)))
2081 } else {
2082 None
2083 }
2084 },
2085 fat_arrow_token: input.parse()?,
2086 body: {
2087 let body = if input.fork().call(expr_nosemi).is_ok() {
2088 input.call(expr_nosemi)?
2089 } else {
2090 input.parse()?
2091 };
2092 requires_comma = arm_expr_requires_comma(&body);
2093 Box::new(body)
2094 },
2095 comma: {
2096 if requires_comma && !input.is_empty() {
2097 Some(input.parse()?)
2098 } else {
2099 input.parse()?
2100 }
2101 },
Michael Layzell92639a52017-06-01 00:07:44 -04002102 })
David Tolnay60291082018-08-28 09:54:49 -07002103 }
Alex Crichton954046c2017-05-30 21:49:42 -07002104 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002105
Michael Layzell734adb42017-06-07 16:58:31 -04002106 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002107 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2108 let attrs = input.call(Attribute::parse_outer)?;
2109 let asyncness: Option<Token![async]> = input.parse()?;
2110 let movability: Option<Token![static]> = if asyncness.is_none() {
2111 input.parse()?
2112 } else {
2113 None
2114 };
2115 let capture: Option<Token![move]> = input.parse()?;
2116 let or1_token: Token![|] = input.parse()?;
2117
2118 let mut inputs = Punctuated::new();
2119 loop {
2120 if input.peek(Token![|]) {
2121 break;
2122 }
2123 let value = fn_arg(input)?;
2124 inputs.push_value(value);
2125 if input.peek(Token![|]) {
2126 break;
2127 }
2128 let punct: Token![,] = input.parse()?;
2129 inputs.push_punct(punct);
2130 }
2131
2132 let or2_token: Token![|] = input.parse()?;
2133
2134 let (output, body) = if input.peek(Token![->]) {
2135 let arrow_token: Token![->] = input.parse()?;
2136 let ty: Type = input.parse()?;
2137 let body: Block = input.parse()?;
2138 let output = ReturnType::Type(arrow_token, Box::new(ty));
2139 let block = Expr::Block(ExprBlock {
2140 attrs: Vec::new(),
2141 label: None,
2142 block: body,
2143 });
2144 (output, block)
2145 } else {
2146 let body = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2147 (ReturnType::Default, body)
2148 };
2149
2150 Ok(ExprClosure {
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002151 attrs: attrs,
2152 asyncness: asyncness,
2153 movability: movability,
2154 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002155 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002156 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002157 or2_token: or2_token,
2158 output: output,
2159 body: Box::new(body),
2160 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002161 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002162
2163 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002164 impl Parse for ExprAsync {
2165 fn parse(input: ParseStream) -> Result<Self> {
2166 Ok(ExprAsync {
2167 attrs: input.call(Attribute::parse_outer)?,
2168 async_token: input.parse()?,
2169 capture: input.parse()?,
2170 block: input.parse()?,
2171 })
2172 }
2173 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002174
Michael Layzell734adb42017-06-07 16:58:31 -04002175 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002176 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2177 let pat: Pat = input.parse()?;
2178
2179 if input.peek(Token![:]) {
2180 Ok(FnArg::Captured(ArgCaptured {
2181 pat: pat,
2182 colon_token: input.parse()?,
2183 ty: input.parse()?,
2184 }))
2185 } else {
2186 Ok(FnArg::Inferred(pat))
2187 }
2188 }
2189
2190 #[cfg(feature = "full")]
2191 impl Parse for ExprWhile {
2192 fn parse(input: ParseStream) -> Result<Self> {
2193 let outer_attrs = input.call(Attribute::parse_outer)?;
2194 let label: Option<Label> = input.parse()?;
2195 let while_token: Token![while] = input.parse()?;
2196 let cond = expr_no_struct(input)?;
2197
2198 let content;
2199 let brace_token = braced!(content in input);
2200 let inner_attrs = content.call(Attribute::parse_inner)?;
2201 let stmts = content.call(Block::parse_within)?;
2202
2203 Ok(ExprWhile {
David Tolnay5d314dc2018-07-21 16:40:01 -07002204 attrs: {
2205 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002206 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002207 attrs
2208 },
2209 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002210 while_token: while_token,
Michael Layzell92639a52017-06-01 00:07:44 -04002211 cond: Box::new(cond),
David Tolnay5d314dc2018-07-21 16:40:01 -07002212 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002213 brace_token: brace_token,
2214 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002215 },
Michael Layzell92639a52017-06-01 00:07:44 -04002216 })
David Tolnay60291082018-08-28 09:54:49 -07002217 }
Alex Crichton954046c2017-05-30 21:49:42 -07002218 }
2219
Michael Layzell734adb42017-06-07 16:58:31 -04002220 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002221 impl Parse for ExprWhileLet {
2222 fn parse(input: ParseStream) -> Result<Self> {
2223 let outer_attrs = input.call(Attribute::parse_outer)?;
2224 let label: Option<Label> = input.parse()?;
2225 let while_token: Token![while] = input.parse()?;
2226 let let_token: Token![let] = input.parse()?;
2227
2228 let mut pats = Punctuated::new();
2229 let value: Pat = input.parse()?;
2230 pats.push_value(value);
2231 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2232 let punct = input.parse()?;
2233 pats.push_punct(punct);
2234 let value: Pat = input.parse()?;
2235 pats.push_value(value);
2236 }
2237
2238 let eq_token: Token![=] = input.parse()?;
2239 let expr = expr_no_struct(input)?;
2240
2241 let content;
2242 let brace_token = braced!(content in input);
2243 let inner_attrs = content.call(Attribute::parse_inner)?;
2244 let stmts = content.call(Block::parse_within)?;
2245
2246 Ok(ExprWhileLet {
David Tolnay5d314dc2018-07-21 16:40:01 -07002247 attrs: {
2248 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002249 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002250 attrs
2251 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002252 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002253 while_token: while_token,
2254 let_token: let_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002255 pats: pats,
David Tolnay60291082018-08-28 09:54:49 -07002256 eq_token: eq_token,
2257 expr: Box::new(expr),
David Tolnay5d314dc2018-07-21 16:40:01 -07002258 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002259 brace_token: brace_token,
2260 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002261 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002262 })
David Tolnay60291082018-08-28 09:54:49 -07002263 }
David Tolnaybcd498f2017-12-29 12:02:33 -05002264 }
2265
2266 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002267 impl Parse for Label {
2268 fn parse(input: ParseStream) -> Result<Self> {
2269 Ok(Label {
2270 name: input.parse()?,
2271 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002272 })
David Tolnay60291082018-08-28 09:54:49 -07002273 }
Alex Crichton954046c2017-05-30 21:49:42 -07002274 }
2275
Michael Layzell734adb42017-06-07 16:58:31 -04002276 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002277 impl Parse for Option<Label> {
2278 fn parse(input: ParseStream) -> Result<Self> {
2279 if input.peek(Lifetime) {
2280 input.parse().map(Some)
2281 } else {
2282 Ok(None)
2283 }
2284 }
2285 }
2286
2287 #[cfg(feature = "full")]
2288 impl Parse for ExprContinue {
2289 fn parse(input: ParseStream) -> Result<Self> {
2290 Ok(ExprContinue {
2291 attrs: input.call(Attribute::parse_outer)?,
2292 continue_token: input.parse()?,
2293 label: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002294 })
David Tolnay60291082018-08-28 09:54:49 -07002295 }
Alex Crichton954046c2017-05-30 21:49:42 -07002296 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002297
Michael Layzell734adb42017-06-07 16:58:31 -04002298 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002299 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2300 Ok(ExprBreak {
2301 attrs: input.call(Attribute::parse_outer)?,
2302 break_token: input.parse()?,
2303 label: input.parse()?,
2304 expr: {
2305 if input.is_empty()
2306 || input.peek(Token![,])
2307 || input.peek(Token![;])
2308 || !allow_struct.0 && input.peek(token::Brace)
2309 {
2310 None
2311 } else {
2312 // We can't allow blocks after a `break` expression when we
2313 // wouldn't allow structs, as this expression is ambiguous.
2314 let allow_block = AllowBlock(allow_struct.0);
2315 let expr = ambiguous_expr(input, allow_struct, allow_block)?;
2316 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002317 }
David Tolnay60291082018-08-28 09:54:49 -07002318 },
2319 })
Alex Crichton954046c2017-05-30 21:49:42 -07002320 }
2321
Michael Layzell734adb42017-06-07 16:58:31 -04002322 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002323 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2324 Ok(ExprReturn {
2325 attrs: input.call(Attribute::parse_outer)?,
2326 return_token: input.parse()?,
2327 expr: {
2328 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2329 None
2330 } else {
2331 // NOTE: return is greedy and eats blocks after it even when in a
2332 // position where structs are not allowed, such as in if statement
2333 // conditions. For example:
2334 //
2335 // if return { println!("A") } {} // Prints "A"
2336 let expr = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2337 Some(Box::new(expr))
2338 }
2339 },
2340 })
2341 }
2342
2343 #[cfg(feature = "full")]
2344 impl Parse for ExprStruct {
2345 fn parse(input: ParseStream) -> Result<Self> {
2346 let outer_attrs = input.call(Attribute::parse_outer)?;
2347 let path: Path = input.parse()?;
2348
2349 let content;
2350 let brace_token = braced!(content in input);
2351 let inner_attrs = content.call(Attribute::parse_inner)?;
2352
2353 let mut fields = Punctuated::new();
2354 loop {
2355 let attrs = content.call(Attribute::parse_outer)?;
2356 if content.fork().parse::<Member>().is_err() {
2357 if attrs.is_empty() {
2358 break;
2359 } else {
2360 return Err(content.error("expected struct field"));
2361 }
2362 }
2363
2364 let member: Member = content.parse()?;
2365 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2366 let colon_token: Token![:] = content.parse()?;
2367 let value: Expr = content.parse()?;
2368 (Some(colon_token), value)
2369 } else if let Member::Named(ref ident) = member {
2370 let value = Expr::Path(ExprPath {
David Tolnayc42b90a2018-01-18 23:11:37 -08002371 attrs: Vec::new(),
2372 qself: None,
David Tolnay60291082018-08-28 09:54:49 -07002373 path: Path::from(ident.clone()),
2374 });
2375 (None, value)
2376 } else {
2377 unreachable!()
2378 };
2379
2380 fields.push(FieldValue {
2381 attrs: attrs,
2382 member: member,
2383 colon_token: colon_token,
2384 expr: value,
2385 });
2386
2387 if !content.peek(Token![,]) {
2388 break;
2389 }
2390 let punct: Token![,] = content.parse()?;
2391 fields.push_punct(punct);
2392 }
2393
2394 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2395 let dot2_token: Token![..] = content.parse()?;
2396 let rest: Expr = content.parse()?;
2397 (Some(dot2_token), Some(Box::new(rest)))
2398 } else {
2399 (None, None)
2400 };
2401
2402 Ok(ExprStruct {
2403 attrs: {
2404 let mut attrs = outer_attrs;
2405 attrs.extend(inner_attrs);
2406 attrs
2407 },
2408 brace_token: brace_token,
2409 path: path,
2410 fields: fields,
2411 dot2_token: dot2_token,
2412 rest: rest,
Michael Layzell92639a52017-06-01 00:07:44 -04002413 })
David Tolnay60291082018-08-28 09:54:49 -07002414 }
Alex Crichton954046c2017-05-30 21:49:42 -07002415 }
David Tolnay055a7042016-10-02 19:23:54 -07002416
Michael Layzell734adb42017-06-07 16:58:31 -04002417 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002418 impl Parse for ExprRepeat {
2419 fn parse(input: ParseStream) -> Result<Self> {
2420 let outer_attrs = input.call(Attribute::parse_outer)?;
2421
2422 let content;
2423 let bracket_token = bracketed!(content in input);
2424 let inner_attrs = content.call(Attribute::parse_inner)?;
2425 let expr: Expr = content.parse()?;
2426 let semi_token: Token![;] = content.parse()?;
2427 let len: Expr = content.parse()?;
2428
2429 Ok(ExprRepeat {
David Tolnay5d314dc2018-07-21 16:40:01 -07002430 attrs: {
2431 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002432 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002433 attrs
2434 },
David Tolnay60291082018-08-28 09:54:49 -07002435 bracket_token: bracket_token,
2436 expr: Box::new(expr),
2437 semi_token: semi_token,
2438 len: Box::new(len),
Michael Layzell92639a52017-06-01 00:07:44 -04002439 })
David Tolnay60291082018-08-28 09:54:49 -07002440 }
Alex Crichton954046c2017-05-30 21:49:42 -07002441 }
David Tolnay055a7042016-10-02 19:23:54 -07002442
Michael Layzell734adb42017-06-07 16:58:31 -04002443 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002444 impl Parse for ExprUnsafe {
2445 fn parse(input: ParseStream) -> Result<Self> {
2446 let outer_attrs = input.call(Attribute::parse_outer)?;
2447 let unsafe_token: Token![unsafe] = input.parse()?;
2448
2449 let content;
2450 let brace_token = braced!(content in input);
2451 let inner_attrs = content.call(Attribute::parse_inner)?;
2452 let stmts = content.call(Block::parse_within)?;
2453
2454 Ok(ExprUnsafe {
David Tolnayc4be3512018-08-27 06:25:44 -07002455 attrs: {
2456 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002457 attrs.extend(inner_attrs);
David Tolnayc4be3512018-08-27 06:25:44 -07002458 attrs
2459 },
David Tolnay60291082018-08-28 09:54:49 -07002460 unsafe_token: unsafe_token,
David Tolnayc4be3512018-08-27 06:25:44 -07002461 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002462 brace_token: brace_token,
2463 stmts: stmts,
David Tolnayc4be3512018-08-27 06:25:44 -07002464 },
Nika Layzell640832a2017-12-04 13:37:09 -05002465 })
David Tolnay60291082018-08-28 09:54:49 -07002466 }
Nika Layzell640832a2017-12-04 13:37:09 -05002467 }
2468
2469 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002470 impl Parse for ExprBlock {
2471 fn parse(input: ParseStream) -> Result<Self> {
2472 let outer_attrs = input.call(Attribute::parse_outer)?;
2473 let label: Option<Label> = input.parse()?;
2474
2475 let content;
2476 let brace_token = braced!(content in input);
2477 let inner_attrs = content.call(Attribute::parse_inner)?;
2478 let stmts = content.call(Block::parse_within)?;
2479
2480 Ok(ExprBlock {
David Tolnay5d314dc2018-07-21 16:40:01 -07002481 attrs: {
2482 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002483 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002484 attrs
2485 },
David Tolnay1d8e9962018-08-24 19:04:20 -04002486 label: label,
David Tolnay5d314dc2018-07-21 16:40:01 -07002487 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002488 brace_token: brace_token,
2489 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002490 },
Michael Layzell92639a52017-06-01 00:07:44 -04002491 })
David Tolnay60291082018-08-28 09:54:49 -07002492 }
Alex Crichton954046c2017-05-30 21:49:42 -07002493 }
David Tolnay89e05672016-10-02 14:39:42 -07002494
Michael Layzell734adb42017-06-07 16:58:31 -04002495 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002496 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2497 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002498 attrs: Vec::new(),
2499 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002500 limits: input.parse()?,
2501 to: {
2502 if input.is_empty()
2503 || input.peek(Token![,])
2504 || input.peek(Token![;])
2505 || !allow_struct.0 && input.peek(token::Brace)
2506 {
2507 None
2508 } else {
2509 let to = ambiguous_expr(input, allow_struct, AllowBlock(allow_struct.0))?;
2510 Some(Box::new(to))
2511 }
2512 },
2513 })
2514 }
David Tolnay438c9052016-10-07 23:24:48 -07002515
Michael Layzell734adb42017-06-07 16:58:31 -04002516 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002517 impl Parse for RangeLimits {
2518 fn parse(input: ParseStream) -> Result<Self> {
2519 let lookahead = input.lookahead1();
2520 if lookahead.peek(Token![..=]) {
2521 input.parse().map(RangeLimits::Closed)
2522 } else if lookahead.peek(Token![...]) {
2523 let dot3: Token![...] = input.parse()?;
2524 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2525 } else if lookahead.peek(Token![..]) {
2526 input.parse().map(RangeLimits::HalfOpen)
2527 } else {
2528 Err(lookahead.error())
2529 }
2530 }
Alex Crichton954046c2017-05-30 21:49:42 -07002531 }
David Tolnay438c9052016-10-07 23:24:48 -07002532
David Tolnay60291082018-08-28 09:54:49 -07002533 impl Parse for ExprPath {
2534 fn parse(input: ParseStream) -> Result<Self> {
2535 #[cfg(not(feature = "full"))]
2536 let attrs = Vec::new();
2537 #[cfg(feature = "full")]
2538 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002539
David Tolnay60291082018-08-28 09:54:49 -07002540 let (qself, path) = path::parsing::qpath(input, true)?;
2541
2542 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002543 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002544 qself: qself,
2545 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002546 })
David Tolnay60291082018-08-28 09:54:49 -07002547 }
Alex Crichton954046c2017-05-30 21:49:42 -07002548 }
David Tolnay42602292016-10-01 22:25:45 -07002549
Michael Layzell734adb42017-06-07 16:58:31 -04002550 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002551 impl Parse for Block {
2552 fn parse(input: ParseStream) -> Result<Self> {
2553 let content;
2554 Ok(Block {
2555 brace_token: braced!(content in input),
2556 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002557 })
David Tolnay60291082018-08-28 09:54:49 -07002558 }
Alex Crichton954046c2017-05-30 21:49:42 -07002559 }
David Tolnay939766a2016-09-23 23:48:12 -07002560
Michael Layzell734adb42017-06-07 16:58:31 -04002561 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002562 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002563 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
2564 input.step_cursor(|cursor| Self::old_parse_within(*cursor))
2565 }
2566
2567 named!(old_parse_within -> Vec<Stmt>, do_parse!(
David Tolnay4699a312017-12-27 14:39:22 -05002568 many0!(punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05002569 mut standalone: many0!(do_parse!(
2570 stmt: syn!(Stmt) >>
2571 many0!(punct!(;)) >>
2572 (stmt)
2573 )) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002574 last: option!(do_parse!(
David Tolnayf8106f82018-08-25 21:17:45 -04002575 attrs: many0!(Attribute::old_parse_outer) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002576 mut e: syn!(Expr) >>
2577 ({
David Tolnay2ae520a2017-12-29 11:19:50 -05002578 e.replace_attrs(attrs);
David Tolnay1f0b7b82018-01-06 16:07:14 -08002579 Stmt::Expr(e)
Alex Crichton70bbd592017-08-27 10:40:03 -07002580 })
2581 )) >>
Michael Layzell92639a52017-06-01 00:07:44 -04002582 (match last {
2583 None => standalone,
2584 Some(last) => {
Alex Crichton70bbd592017-08-27 10:40:03 -07002585 standalone.push(last);
Michael Layzell92639a52017-06-01 00:07:44 -04002586 standalone
2587 }
2588 })
2589 ));
Alex Crichton954046c2017-05-30 21:49:42 -07002590 }
2591
Michael Layzell734adb42017-06-07 16:58:31 -04002592 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002593 impl Parse for Stmt {
2594 fn parse(input: ParseStream) -> Result<Self> {
2595 let ahead = input.fork();
2596 ahead.call(Attribute::parse_outer)?;
David Tolnay939766a2016-09-23 23:48:12 -07002597
David Tolnay60291082018-08-28 09:54:49 -07002598 // TODO: better error messages
2599 if {
2600 let ahead = ahead.fork();
2601 // Only parse braces here; paren and bracket will get parsed as
2602 // expression statements
2603 ahead.call(Path::parse_mod_style).is_ok()
2604 && ahead.parse::<Token![!]>().is_ok()
2605 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2606 } {
2607 stmt_mac(input)
2608 } else if ahead.peek(Token![let]) {
2609 stmt_local(input).map(Stmt::Local)
2610 } else if ahead.peek(Token![pub])
2611 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2612 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2613 || ahead.peek(Token![use])
2614 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2615 || ahead.peek(Token![const])
2616 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2617 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2618 || ahead.peek(Token![fn])
2619 || ahead.peek(Token![mod])
2620 || ahead.peek(Token![type])
2621 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2622 || ahead.peek(Token![struct])
2623 || ahead.peek(Token![enum])
2624 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2625 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2626 || ahead.peek(Token![trait])
2627 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2628 || ahead.peek(Token![impl])
2629 || ahead.peek(Token![macro])
2630 {
2631 input.parse().map(Stmt::Item)
2632 } else if ahead.fork().call(stmt_blockexpr).is_ok() {
2633 stmt_blockexpr(input)
2634 } else if ahead.call(stmt_expr).is_ok() {
2635 stmt_expr(input)
Michael Layzell35418782017-06-07 09:20:25 -04002636 } else {
David Tolnay60291082018-08-28 09:54:49 -07002637 Err(input.error("expected statement"))
Michael Layzell35418782017-06-07 09:20:25 -04002638 }
David Tolnay60291082018-08-28 09:54:49 -07002639 }
Alex Crichton954046c2017-05-30 21:49:42 -07002640 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002641
Michael Layzell734adb42017-06-07 16:58:31 -04002642 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002643 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2644 let attrs = input.call(Attribute::parse_outer)?;
2645 let path = input.call(Path::parse_mod_style)?;
2646 let bang_token: Token![!] = input.parse()?;
2647 let ident: Option<Ident> = input.parse()?;
2648 let (delimiter, tts) = mac::parse_delimiter(input)?;
2649 let semi_token: Option<Token![;]> = input.parse()?;
2650
2651 Ok(Stmt::Item(Item::Macro(ItemMacro {
2652 attrs: attrs,
2653 ident: ident,
2654 mac: Macro {
2655 path: path,
2656 bang_token: bang_token,
2657 delimiter: delimiter,
2658 tts: tts,
2659 },
2660 semi_token: semi_token,
2661 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002662 }
David Tolnay84aa0752016-10-02 23:01:13 -07002663
Michael Layzell734adb42017-06-07 16:58:31 -04002664 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002665 fn stmt_local(input: ParseStream) -> Result<Local> {
2666 Ok(Local {
2667 attrs: input.call(Attribute::parse_outer)?,
2668 let_token: input.parse()?,
2669 pats: {
2670 let mut pats = Punctuated::new();
2671 let value: Pat = input.parse()?;
2672 pats.push_value(value);
2673 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2674 let punct = input.parse()?;
2675 pats.push_punct(punct);
2676 let value: Pat = input.parse()?;
2677 pats.push_value(value);
2678 }
2679 pats
2680 },
2681 ty: {
2682 if input.peek(Token![:]) {
2683 let colon_token: Token![:] = input.parse()?;
2684 let ty: Type = input.parse()?;
2685 Some((colon_token, Box::new(ty)))
2686 } else {
2687 None
2688 }
2689 },
2690 init: {
2691 if input.peek(Token![=]) {
2692 let eq_token: Token![=] = input.parse()?;
2693 let init: Expr = input.parse()?;
2694 Some((eq_token, Box::new(init)))
2695 } else {
2696 None
2697 }
2698 },
2699 semi_token: input.parse()?,
2700 })
2701 }
2702
2703 #[cfg(feature = "full")]
2704 fn stmt_blockexpr(input: ParseStream) -> Result<Stmt> {
2705 let mut attrs = input.call(Attribute::parse_outer)?;
2706 let mut e = expr_nosemi(input)?;
2707
2708 attrs.extend(e.replace_attrs(Vec::new()));
2709 e.replace_attrs(attrs);
2710
2711 if input.peek(Token![;]) {
2712 Ok(Stmt::Semi(e, input.parse()?))
2713 } else {
2714 Ok(Stmt::Expr(e))
2715 }
2716 }
2717
2718 #[cfg(feature = "full")]
2719 fn stmt_expr(input: ParseStream) -> Result<Stmt> {
2720 let mut attrs = input.call(Attribute::parse_outer)?;
2721 let mut e: Expr = input.parse()?;
2722 let semi_token: Token![;] = input.parse()?;
2723
2724 attrs.extend(e.replace_attrs(Vec::new()));
2725 e.replace_attrs(attrs);
2726
2727 Ok(Stmt::Semi(e, semi_token))
2728 }
2729
2730 #[cfg(feature = "full")]
2731 impl Parse for Pat {
2732 fn parse(input: ParseStream) -> Result<Self> {
2733 // TODO: better error messages
2734 let lookahead = input.lookahead1();
2735 if lookahead.peek(Token![_]) {
2736 input.parse().map(Pat::Wild)
2737 } else if lookahead.peek(Token![box]) {
2738 input.parse().map(Pat::Box)
2739 } else if input.fork().parse::<PatRange>().is_ok() {
2740 // must be before Pat::Lit
2741 input.parse().map(Pat::Range)
2742 } else if input.fork().parse::<PatTupleStruct>().is_ok() {
2743 // must be before Pat::Ident
2744 input.parse().map(Pat::TupleStruct)
2745 } else if input.fork().parse::<PatStruct>().is_ok() {
2746 // must be before Pat::Ident
2747 input.parse().map(Pat::Struct)
2748 } else if input.fork().parse::<PatMacro>().is_ok() {
2749 // must be before Pat::Ident
2750 input.parse().map(Pat::Macro)
2751 } else if input.fork().parse::<PatLit>().is_ok() {
2752 // must be before Pat::Ident
2753 input.parse().map(Pat::Lit)
2754 } else if input.fork().parse::<PatIdent>().is_ok() {
2755 input.parse().map(Pat::Ident)
2756 } else if input.fork().parse::<PatPath>().is_ok() {
2757 input.parse().map(Pat::Path)
2758 } else if lookahead.peek(token::Paren) {
2759 input.parse().map(Pat::Tuple)
2760 } else if lookahead.peek(Token![&]) {
2761 input.parse().map(Pat::Ref)
2762 } else if lookahead.peek(token::Bracket) {
2763 input.parse().map(Pat::Slice)
2764 } else {
2765 Err(lookahead.error())
2766 }
2767 }
2768 }
2769
2770 #[cfg(feature = "full")]
2771 impl Parse for PatWild {
2772 fn parse(input: ParseStream) -> Result<Self> {
2773 Ok(PatWild {
2774 underscore_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002775 })
David Tolnay60291082018-08-28 09:54:49 -07002776 }
Alex Crichton954046c2017-05-30 21:49:42 -07002777 }
2778
Michael Layzell734adb42017-06-07 16:58:31 -04002779 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002780 impl Parse for PatBox {
2781 fn parse(input: ParseStream) -> Result<Self> {
2782 Ok(PatBox {
2783 box_token: input.parse()?,
2784 pat: input.parse()?,
2785 })
2786 }
2787 }
2788
2789 #[cfg(feature = "full")]
2790 impl Parse for PatIdent {
2791 fn parse(input: ParseStream) -> Result<Self> {
2792 Ok(PatIdent {
2793 by_ref: input.parse()?,
2794 mutability: input.parse()?,
2795 ident: {
2796 let ident = if input.peek(Ident) || input.peek(Token![self]) {
2797 input.call(Ident::parse_any2)?
2798 } else {
2799 return Err(input.error("expected identifier or `self`"));
2800 };
2801 if input.peek(Token![<]) || input.peek(Token![::]) {
2802 return Err(input.error("unexpected token"));
2803 }
2804 ident
2805 },
2806 subpat: {
2807 if input.peek(Token![@]) {
2808 let at_token: Token![@] = input.parse()?;
2809 let subpat: Pat = input.parse()?;
2810 Some((at_token, Box::new(subpat)))
2811 } else {
2812 None
2813 }
2814 },
2815 })
2816 }
2817 }
2818
2819 #[cfg(feature = "full")]
2820 impl Parse for PatTupleStruct {
2821 fn parse(input: ParseStream) -> Result<Self> {
2822 Ok(PatTupleStruct {
2823 path: input.parse()?,
2824 pat: input.parse()?,
2825 })
2826 }
2827 }
2828
2829 #[cfg(feature = "full")]
2830 impl Parse for PatStruct {
2831 fn parse(input: ParseStream) -> Result<Self> {
2832 let path: Path = input.parse()?;
2833
2834 let content;
2835 let brace_token = braced!(content in input);
2836
2837 let mut fields = Punctuated::new();
2838 while !content.is_empty() && !content.peek(Token![..]) {
2839 let value: FieldPat = content.parse()?;
2840 fields.push_value(value);
2841 if !content.peek(Token![,]) {
2842 break;
2843 }
2844 let punct: Token![,] = content.parse()?;
2845 fields.push_punct(punct);
2846 }
2847
2848 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2849 Some(content.parse()?)
2850 } else {
2851 None
2852 };
2853
2854 Ok(PatStruct {
2855 path: path,
2856 brace_token: brace_token,
2857 fields: fields,
2858 dot2_token: dot2_token,
2859 })
2860 }
2861 }
2862
2863 #[cfg(feature = "full")]
2864 impl Parse for FieldPat {
2865 fn parse(input: ParseStream) -> Result<Self> {
2866 let boxed: Option<Token![box]> = input.parse()?;
2867 let by_ref: Option<Token![ref]> = input.parse()?;
2868 let mutability: Option<Token![mut]> = input.parse()?;
2869 let member: Member = input.parse()?;
2870
2871 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2872 || member.is_unnamed()
2873 {
2874 return Ok(FieldPat {
2875 attrs: Vec::new(),
2876 member: member,
2877 colon_token: input.parse()?,
2878 pat: input.parse()?,
2879 });
2880 }
2881
2882 let ident = match member {
2883 Member::Named(ident) => ident,
2884 Member::Unnamed(_) => unreachable!(),
2885 };
2886
2887 let mut pat = Pat::Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -05002888 by_ref: by_ref,
David Tolnayefc96fb2017-12-29 02:03:15 -05002889 mutability: mutability,
David Tolnay60291082018-08-28 09:54:49 -07002890 ident: ident.clone(),
2891 subpat: None,
2892 });
Alex Crichton954046c2017-05-30 21:49:42 -07002893
David Tolnay60291082018-08-28 09:54:49 -07002894 if let Some(boxed) = boxed {
2895 pat = Pat::Box(PatBox {
Michael Layzell92639a52017-06-01 00:07:44 -04002896 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07002897 box_token: boxed,
2898 });
2899 }
2900
2901 Ok(FieldPat {
2902 member: Member::Named(ident),
2903 pat: Box::new(pat),
2904 attrs: Vec::new(),
2905 colon_token: None,
2906 })
2907 }
Alex Crichton954046c2017-05-30 21:49:42 -07002908 }
2909
David Tolnay1501f7e2018-08-27 14:21:03 -07002910 impl Parse for Member {
2911 fn parse(input: ParseStream) -> Result<Self> {
2912 if input.peek(Ident) {
2913 input.parse().map(Member::Named)
2914 } else if input.peek(LitInt) {
2915 input.parse().map(Member::Unnamed)
2916 } else {
2917 Err(input.error("expected identifier or integer"))
2918 }
2919 }
David Tolnay85b69a42017-12-27 20:43:10 -05002920 }
2921
David Tolnay1501f7e2018-08-27 14:21:03 -07002922 impl Parse for Index {
2923 fn parse(input: ParseStream) -> Result<Self> {
2924 let lit: LitInt = input.parse()?;
2925 if let IntSuffix::None = lit.suffix() {
2926 Ok(Index {
2927 index: lit.value() as u32,
2928 span: lit.span(),
2929 })
2930 } else {
2931 Err(input.error("expected unsuffixed integer"))
2932 }
2933 }
David Tolnay85b69a42017-12-27 20:43:10 -05002934 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002935
Michael Layzell734adb42017-06-07 16:58:31 -04002936 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002937 impl Parse for PatPath {
2938 fn parse(input: ParseStream) -> Result<Self> {
2939 let p: ExprPath = input.parse()?;
2940 Ok(PatPath {
2941 qself: p.qself,
2942 path: p.path,
2943 })
2944 }
Alex Crichton954046c2017-05-30 21:49:42 -07002945 }
David Tolnay9636c052016-10-02 17:11:17 -07002946
Michael Layzell734adb42017-06-07 16:58:31 -04002947 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002948 impl Parse for PatTuple {
2949 fn parse(input: ParseStream) -> Result<Self> {
2950 let content;
2951 let paren_token = parenthesized!(content in input);
2952
2953 let mut front = Punctuated::new();
2954 let mut dot2_token = None::<Token![..]>;
2955 let mut comma_token = None::<Token![,]>;
2956 loop {
2957 if content.is_empty() {
2958 break;
Michael Layzell92639a52017-06-01 00:07:44 -04002959 }
David Tolnay60291082018-08-28 09:54:49 -07002960 if content.peek(Token![..]) {
2961 dot2_token = Some(content.parse()?);
2962 comma_token = content.parse()?;
2963 break;
2964 }
2965 let value: Pat = content.parse()?;
2966 front.push_value(value);
2967 if content.is_empty() {
2968 break;
2969 }
2970 let punct = content.parse()?;
2971 front.push_punct(punct);
2972 }
David Tolnayfbb73232016-10-03 01:00:06 -07002973
David Tolnay60291082018-08-28 09:54:49 -07002974 let back = if comma_token.is_some() {
2975 content.parse_synom(Punctuated::parse_terminated)?
Michael Layzell92639a52017-06-01 00:07:44 -04002976 } else {
David Tolnay60291082018-08-28 09:54:49 -07002977 Punctuated::new()
2978 };
2979
2980 Ok(PatTuple {
2981 paren_token: paren_token,
2982 front: front,
2983 dot2_token: dot2_token,
2984 comma_token: comma_token,
2985 back: back,
Michael Layzell92639a52017-06-01 00:07:44 -04002986 })
David Tolnay60291082018-08-28 09:54:49 -07002987 }
Alex Crichton954046c2017-05-30 21:49:42 -07002988 }
David Tolnaye1310902016-10-29 23:40:00 -07002989
Michael Layzell734adb42017-06-07 16:58:31 -04002990 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002991 impl Parse for PatRef {
2992 fn parse(input: ParseStream) -> Result<Self> {
2993 Ok(PatRef {
2994 and_token: input.parse()?,
2995 mutability: input.parse()?,
2996 pat: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002997 })
David Tolnay60291082018-08-28 09:54:49 -07002998 }
Alex Crichton954046c2017-05-30 21:49:42 -07002999 }
David Tolnaye1310902016-10-29 23:40:00 -07003000
Michael Layzell734adb42017-06-07 16:58:31 -04003001 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003002 impl Parse for PatLit {
3003 fn parse(input: ParseStream) -> Result<Self> {
3004 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
3005 Ok(PatLit {
3006 expr: input.call(pat_lit_expr)?,
3007 })
3008 } else {
3009 Err(input.error("expected literal pattern"))
3010 }
3011 }
3012 }
3013
3014 #[cfg(feature = "full")]
3015 impl Parse for PatRange {
3016 fn parse(input: ParseStream) -> Result<Self> {
3017 Ok(PatRange {
3018 lo: input.call(pat_lit_expr)?,
3019 limits: input.parse()?,
3020 hi: input.call(pat_lit_expr)?,
3021 })
3022 }
3023 }
3024
3025 #[cfg(feature = "full")]
3026 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
3027 let neg: Option<Token![-]> = input.parse()?;
3028
3029 let lookahead = input.lookahead1();
3030 let expr = if lookahead.peek(Lit) {
3031 Expr::Lit(input.parse()?)
3032 } else if lookahead.peek(Ident)
3033 || lookahead.peek(Token![::])
3034 || lookahead.peek(Token![<])
3035 || lookahead.peek(Token![self])
3036 || lookahead.peek(Token![Self])
3037 || lookahead.peek(Token![super])
3038 || lookahead.peek(Token![extern])
3039 || lookahead.peek(Token![crate])
3040 {
3041 Expr::Path(input.parse()?)
3042 } else {
3043 return Err(lookahead.error());
3044 };
3045
3046 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05003047 Expr::Unary(ExprUnary {
3048 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05003049 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07003050 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05003051 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07003052 } else {
David Tolnay60291082018-08-28 09:54:49 -07003053 expr
3054 }))
Alex Crichton954046c2017-05-30 21:49:42 -07003055 }
David Tolnay323279a2017-12-29 11:26:32 -05003056
3057 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003058 impl Parse for PatSlice {
3059 fn parse(input: ParseStream) -> Result<Self> {
3060 let content;
3061 let bracket_token = bracketed!(content in input);
3062
3063 let mut front = Punctuated::new();
3064 let mut middle = None;
3065 loop {
3066 if content.is_empty() || content.peek(Token![..]) {
3067 break;
3068 }
3069 let value: Pat = content.parse()?;
3070 if content.peek(Token![..]) {
3071 middle = Some(Box::new(value));
3072 break;
3073 }
3074 front.push_value(value);
3075 if content.is_empty() {
3076 break;
3077 }
3078 let punct = content.parse()?;
3079 front.push_punct(punct);
3080 }
3081
3082 let dot2_token: Option<Token![..]> = content.parse()?;
3083 let mut comma_token = None::<Token![,]>;
3084 let mut back = Punctuated::new();
3085 if dot2_token.is_some() {
3086 comma_token = content.parse()?;
3087 if comma_token.is_some() {
3088 loop {
3089 if content.is_empty() {
3090 break;
3091 }
3092 let value: Pat = content.parse()?;
3093 back.push_value(value);
3094 if content.is_empty() {
3095 break;
3096 }
3097 let punct = content.parse()?;
3098 back.push_punct(punct);
3099 }
3100 }
3101 }
3102
3103 Ok(PatSlice {
3104 bracket_token: bracket_token,
3105 front: front,
3106 middle: middle,
3107 dot2_token: dot2_token,
3108 comma_token: comma_token,
3109 back: back,
3110 })
3111 }
3112 }
3113
3114 #[cfg(feature = "full")]
3115 impl Parse for PatMacro {
3116 fn parse(input: ParseStream) -> Result<Self> {
3117 Ok(PatMacro {
3118 mac: input.parse()?,
3119 })
3120 }
David Tolnay323279a2017-12-29 11:26:32 -05003121 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003122
3123 #[cfg(feature = "full")]
3124 impl Member {
3125 fn is_named(&self) -> bool {
3126 match *self {
3127 Member::Named(_) => true,
3128 Member::Unnamed(_) => false,
3129 }
3130 }
David Tolnay60291082018-08-28 09:54:49 -07003131
3132 fn is_unnamed(&self) -> bool {
3133 match *self {
3134 Member::Named(_) => false,
3135 Member::Unnamed(_) => true,
3136 }
3137 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003138 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003139}
3140
David Tolnayf4bbbd92016-09-23 14:41:55 -07003141#[cfg(feature = "printing")]
3142mod printing {
3143 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04003144 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07003145 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07003146 use proc_macro2::{Literal, TokenStream};
3147 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003148
David Tolnaybcf26022017-12-25 22:10:52 -05003149 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003150 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003151 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003152 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003153 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003154 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003155 e.to_tokens(tokens);
3156 });
3157 } else {
3158 e.to_tokens(tokens);
3159 }
3160 }
3161
David Tolnay8c91b882017-12-28 23:04:32 -05003162 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003163 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003164 tokens.append_all(attrs.outer());
3165 }
Michael Layzell734adb42017-06-07 16:58:31 -04003166
David Tolnayd997aef2018-07-21 18:42:31 -07003167 #[cfg(feature = "full")]
3168 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3169 tokens.append_all(attrs.inner());
3170 }
3171
David Tolnay8c91b882017-12-28 23:04:32 -05003172 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003173 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3174
3175 #[cfg(not(feature = "full"))]
3176 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003177
Michael Layzell734adb42017-06-07 16:58:31 -04003178 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003179 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003180 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003181 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003182 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003183 self.expr.to_tokens(tokens);
3184 }
3185 }
3186
Michael Layzell734adb42017-06-07 16:58:31 -04003187 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003189 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003190 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003191 self.place.to_tokens(tokens);
3192 self.arrow_token.to_tokens(tokens);
3193 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003194 }
3195 }
3196
Michael Layzell734adb42017-06-07 16:58:31 -04003197 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003199 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003200 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003201 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003202 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003203 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003204 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003205 }
3206 }
3207
3208 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003209 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003210 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003211 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003212 self.paren_token.surround(tokens, |tokens| {
3213 self.args.to_tokens(tokens);
3214 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003215 }
3216 }
3217
Michael Layzell734adb42017-06-07 16:58:31 -04003218 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003219 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003220 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003221 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003222 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003223 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003224 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003225 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003226 self.paren_token.surround(tokens, |tokens| {
3227 self.args.to_tokens(tokens);
3228 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003229 }
3230 }
3231
Michael Layzell734adb42017-06-07 16:58:31 -04003232 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003233 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003234 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003235 self.colon2_token.to_tokens(tokens);
3236 self.lt_token.to_tokens(tokens);
3237 self.args.to_tokens(tokens);
3238 self.gt_token.to_tokens(tokens);
3239 }
3240 }
3241
3242 #[cfg(feature = "full")]
3243 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003244 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003245 match *self {
3246 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3247 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3248 }
3249 }
3250 }
3251
3252 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003253 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003254 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003255 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003256 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003257 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003258 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003259 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003260 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003261 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003262 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003263 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003264 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003265 }
3266 }
3267
3268 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003269 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003270 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003271 self.left.to_tokens(tokens);
3272 self.op.to_tokens(tokens);
3273 self.right.to_tokens(tokens);
3274 }
3275 }
3276
3277 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003278 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003279 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003280 self.op.to_tokens(tokens);
3281 self.expr.to_tokens(tokens);
3282 }
3283 }
3284
David Tolnay8c91b882017-12-28 23:04:32 -05003285 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003286 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003287 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003288 self.lit.to_tokens(tokens);
3289 }
3290 }
3291
Alex Crichton62a0a592017-05-22 13:58:53 -07003292 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003293 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003294 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003295 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003296 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003297 self.ty.to_tokens(tokens);
3298 }
3299 }
3300
David Tolnay0cf94f22017-12-28 23:46:26 -05003301 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003302 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003303 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003304 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003305 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003306 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003307 self.ty.to_tokens(tokens);
3308 }
3309 }
3310
Michael Layzell734adb42017-06-07 16:58:31 -04003311 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003312 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003313 if let Some((ref else_token, ref else_)) = *else_ {
3314 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003315
3316 // If we are not one of the valid expressions to exist in an else
3317 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003318 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003319 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003320 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003321 }
3322 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003323 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003324 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003325 });
3326 }
3327 }
3328 }
3329 }
3330
3331 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003332 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003333 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003334 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003335 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003336 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003337 self.then_branch.to_tokens(tokens);
3338 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003339 }
3340 }
3341
Michael Layzell734adb42017-06-07 16:58:31 -04003342 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003343 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003344 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003345 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003346 self.if_token.to_tokens(tokens);
3347 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003348 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003349 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003350 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003351 self.then_branch.to_tokens(tokens);
3352 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003353 }
3354 }
3355
Michael Layzell734adb42017-06-07 16:58:31 -04003356 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003357 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003358 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003359 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003360 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003361 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003362 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003363 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003364 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003365 tokens.append_all(&self.body.stmts);
3366 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003367 }
3368 }
3369
Michael Layzell734adb42017-06-07 16:58:31 -04003370 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003371 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003372 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003373 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003374 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003375 self.while_token.to_tokens(tokens);
3376 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003377 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003378 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003379 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003380 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003381 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003382 tokens.append_all(&self.body.stmts);
3383 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003384 }
3385 }
3386
Michael Layzell734adb42017-06-07 16:58:31 -04003387 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003388 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003389 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003390 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003391 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003392 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003393 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003394 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003395 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003396 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003397 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003398 tokens.append_all(&self.body.stmts);
3399 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 }
3401 }
3402
Michael Layzell734adb42017-06-07 16:58:31 -04003403 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003404 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003405 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003406 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003407 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003408 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003409 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003410 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003411 tokens.append_all(&self.body.stmts);
3412 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003413 }
3414 }
3415
Michael Layzell734adb42017-06-07 16:58:31 -04003416 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003417 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003418 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003419 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003420 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003421 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003422 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003423 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003424 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003425 arm.to_tokens(tokens);
3426 // Ensure that we have a comma after a non-block arm, except
3427 // for the last one.
3428 let is_last = i == self.arms.len() - 1;
Alex Crichton03b30272017-08-28 09:35:24 -07003429 if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003430 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003431 }
3432 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003433 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003434 }
3435 }
3436
Michael Layzell734adb42017-06-07 16:58:31 -04003437 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003438 impl ToTokens for ExprAsync {
3439 fn to_tokens(&self, tokens: &mut TokenStream) {
3440 outer_attrs_to_tokens(&self.attrs, tokens);
3441 self.async_token.to_tokens(tokens);
3442 self.capture.to_tokens(tokens);
3443 self.block.to_tokens(tokens);
3444 }
3445 }
3446
3447 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003448 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003449 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003450 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003451 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 self.block.to_tokens(tokens);
3453 }
3454 }
3455
Michael Layzell734adb42017-06-07 16:58:31 -04003456 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003457 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003458 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003459 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003460 self.yield_token.to_tokens(tokens);
3461 self.expr.to_tokens(tokens);
3462 }
3463 }
3464
3465 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003466 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003467 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003468 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003469 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003470 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003471 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003472 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003473 for input in self.inputs.pairs() {
3474 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003475 FnArg::Captured(ArgCaptured {
3476 ref pat,
3477 ty: Type::Infer(_),
3478 ..
3479 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003480 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003481 }
David Tolnay56080682018-01-06 14:01:52 -08003482 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003483 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003484 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003485 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003486 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003487 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003488 self.body.to_tokens(tokens);
3489 }
3490 }
3491
Michael Layzell734adb42017-06-07 16:58:31 -04003492 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003493 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003494 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003495 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003496 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003497 self.block.brace_token.surround(tokens, |tokens| {
3498 inner_attrs_to_tokens(&self.attrs, tokens);
3499 tokens.append_all(&self.block.stmts);
3500 });
Nika Layzell640832a2017-12-04 13:37:09 -05003501 }
3502 }
3503
3504 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003505 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003506 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003507 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003508 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003509 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003510 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003511 tokens.append_all(&self.block.stmts);
3512 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003513 }
3514 }
3515
Michael Layzell734adb42017-06-07 16:58:31 -04003516 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003517 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003518 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003519 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003520 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003521 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003522 self.right.to_tokens(tokens);
3523 }
3524 }
3525
Michael Layzell734adb42017-06-07 16:58:31 -04003526 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003527 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003528 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003529 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003530 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003531 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003532 self.right.to_tokens(tokens);
3533 }
3534 }
3535
3536 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003537 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003538 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003539 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003540 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003541 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003542 }
3543 }
3544
David Tolnay85b69a42017-12-27 20:43:10 -05003545 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003546 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003547 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003548 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003549 Member::Unnamed(ref index) => index.to_tokens(tokens),
3550 }
3551 }
3552 }
3553
David Tolnay85b69a42017-12-27 20:43:10 -05003554 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003555 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003556 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3557 lit.set_span(self.span);
3558 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003559 }
3560 }
3561
3562 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003563 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003564 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003565 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003566 self.bracket_token.surround(tokens, |tokens| {
3567 self.index.to_tokens(tokens);
3568 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003569 }
3570 }
3571
Michael Layzell734adb42017-06-07 16:58:31 -04003572 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003573 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003574 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003575 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003576 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003577 match self.limits {
3578 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3579 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3580 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003581 self.to.to_tokens(tokens);
3582 }
3583 }
3584
3585 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003586 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003587 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003588 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003589 }
3590 }
3591
Michael Layzell734adb42017-06-07 16:58:31 -04003592 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003593 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003594 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003595 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003596 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003597 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003598 self.expr.to_tokens(tokens);
3599 }
3600 }
3601
Michael Layzell734adb42017-06-07 16:58:31 -04003602 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003603 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003604 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003605 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003606 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003607 self.label.to_tokens(tokens);
3608 self.expr.to_tokens(tokens);
3609 }
3610 }
3611
Michael Layzell734adb42017-06-07 16:58:31 -04003612 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003613 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003614 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003615 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003616 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003617 self.label.to_tokens(tokens);
3618 }
3619 }
3620
Michael Layzell734adb42017-06-07 16:58:31 -04003621 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003622 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003623 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003624 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003625 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003626 self.expr.to_tokens(tokens);
3627 }
3628 }
3629
Michael Layzell734adb42017-06-07 16:58:31 -04003630 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003631 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003632 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003633 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003634 self.mac.to_tokens(tokens);
3635 }
3636 }
3637
3638 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003639 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003640 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003641 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003642 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003643 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003644 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003645 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003646 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003647 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003648 self.rest.to_tokens(tokens);
3649 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003650 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003651 }
3652 }
3653
Michael Layzell734adb42017-06-07 16:58:31 -04003654 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003655 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003656 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003657 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003658 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003659 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003660 self.expr.to_tokens(tokens);
3661 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003662 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003663 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003664 }
3665 }
3666
David Tolnaye98775f2017-12-28 23:17:00 -05003667 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003668 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003669 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003670 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003671 self.group_token.surround(tokens, |tokens| {
3672 self.expr.to_tokens(tokens);
3673 });
3674 }
3675 }
3676
Alex Crichton62a0a592017-05-22 13:58:53 -07003677 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003678 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003679 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003680 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003681 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 self.expr.to_tokens(tokens);
3683 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003684 }
3685 }
3686
Michael Layzell734adb42017-06-07 16:58:31 -04003687 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003688 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003689 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003690 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003691 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003692 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003693 }
3694 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003695
David Tolnay2ae520a2017-12-29 11:19:50 -05003696 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003697 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003698 self.tts.to_tokens(tokens);
3699 }
3700 }
3701
Michael Layzell734adb42017-06-07 16:58:31 -04003702 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003703 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003704 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003705 self.name.to_tokens(tokens);
3706 self.colon_token.to_tokens(tokens);
3707 }
3708 }
3709
3710 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003711 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003712 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003713 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003714 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003715 if let Some(ref colon_token) = self.colon_token {
3716 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003717 self.expr.to_tokens(tokens);
3718 }
David Tolnay055a7042016-10-02 19:23:54 -07003719 }
3720 }
3721
Michael Layzell734adb42017-06-07 16:58:31 -04003722 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003723 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003724 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003725 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003726 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003727 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003728 if let Some((ref if_token, ref guard)) = self.guard {
3729 if_token.to_tokens(tokens);
3730 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003731 }
David Tolnaydfb91432018-03-31 19:19:44 +02003732 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003733 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003734 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003735 }
3736 }
3737
Michael Layzell734adb42017-06-07 16:58:31 -04003738 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003739 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003740 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003741 self.underscore_token.to_tokens(tokens);
3742 }
3743 }
3744
Michael Layzell734adb42017-06-07 16:58:31 -04003745 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003746 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003747 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003748 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003749 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003750 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003751 if let Some((ref at_token, ref subpat)) = self.subpat {
3752 at_token.to_tokens(tokens);
3753 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003754 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003755 }
3756 }
3757
Michael Layzell734adb42017-06-07 16:58:31 -04003758 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003759 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003760 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003761 self.path.to_tokens(tokens);
3762 self.brace_token.surround(tokens, |tokens| {
3763 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003764 // NOTE: We need a comma before the dot2 token if it is present.
3765 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003766 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003767 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003768 self.dot2_token.to_tokens(tokens);
3769 });
3770 }
3771 }
3772
Michael Layzell734adb42017-06-07 16:58:31 -04003773 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003774 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003775 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003776 self.path.to_tokens(tokens);
3777 self.pat.to_tokens(tokens);
3778 }
3779 }
3780
Michael Layzell734adb42017-06-07 16:58:31 -04003781 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003782 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003783 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003784 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3785 }
3786 }
3787
Michael Layzell734adb42017-06-07 16:58:31 -04003788 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003789 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003790 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003791 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003792 self.front.to_tokens(tokens);
3793 if let Some(ref dot2_token) = self.dot2_token {
3794 if !self.front.empty_or_trailing() {
3795 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003796 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003797 }
David Tolnay41871922017-12-29 01:53:45 -05003798 dot2_token.to_tokens(tokens);
3799 self.comma_token.to_tokens(tokens);
3800 if self.comma_token.is_none() && !self.back.is_empty() {
3801 // Ensure there is a comma after the .. token.
3802 <Token![,]>::default().to_tokens(tokens);
3803 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003804 }
David Tolnay41871922017-12-29 01:53:45 -05003805 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003806 });
3807 }
3808 }
3809
Michael Layzell734adb42017-06-07 16:58:31 -04003810 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003811 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003812 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003813 self.box_token.to_tokens(tokens);
3814 self.pat.to_tokens(tokens);
3815 }
3816 }
3817
Michael Layzell734adb42017-06-07 16:58:31 -04003818 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003819 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003820 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003821 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003822 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003823 self.pat.to_tokens(tokens);
3824 }
3825 }
3826
Michael Layzell734adb42017-06-07 16:58:31 -04003827 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003828 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003829 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003830 self.expr.to_tokens(tokens);
3831 }
3832 }
3833
Michael Layzell734adb42017-06-07 16:58:31 -04003834 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003835 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003836 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003837 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003838 match self.limits {
3839 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003840 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003841 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003842 self.hi.to_tokens(tokens);
3843 }
3844 }
3845
Michael Layzell734adb42017-06-07 16:58:31 -04003846 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003847 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003848 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003849 // XXX: This is a mess, and it will be so easy to screw it up. How
3850 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003851 self.bracket_token.surround(tokens, |tokens| {
3852 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003853
3854 // If we need a comma before the middle or standalone .. token,
3855 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003856 if !self.front.empty_or_trailing()
3857 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003858 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003859 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003860 }
3861
3862 // If we have an identifier, we always need a .. token.
3863 if self.middle.is_some() {
3864 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003865 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003866 } else if self.dot2_token.is_some() {
3867 self.dot2_token.to_tokens(tokens);
3868 }
3869
3870 // Make sure we have a comma before the back half.
3871 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003872 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003873 self.back.to_tokens(tokens);
3874 } else {
3875 self.comma_token.to_tokens(tokens);
3876 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003877 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003878 }
3879 }
3880
Michael Layzell734adb42017-06-07 16:58:31 -04003881 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003882 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003883 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003884 self.mac.to_tokens(tokens);
3885 }
3886 }
3887
3888 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003889 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003890 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003891 self.tts.to_tokens(tokens);
3892 }
3893 }
3894
3895 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003896 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003897 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003898 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003899 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003900 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003901 }
3902 self.pat.to_tokens(tokens);
3903 }
3904 }
3905
Michael Layzell734adb42017-06-07 16:58:31 -04003906 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003907 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003908 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003909 self.brace_token.surround(tokens, |tokens| {
3910 tokens.append_all(&self.stmts);
3911 });
David Tolnay42602292016-10-01 22:25:45 -07003912 }
3913 }
3914
Michael Layzell734adb42017-06-07 16:58:31 -04003915 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003916 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003917 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003918 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003919 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003920 Stmt::Item(ref item) => item.to_tokens(tokens),
3921 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003922 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003923 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003924 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003925 }
David Tolnay42602292016-10-01 22:25:45 -07003926 }
3927 }
3928 }
David Tolnay191e0582016-10-02 18:31:09 -07003929
Michael Layzell734adb42017-06-07 16:58:31 -04003930 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003931 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003932 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003933 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003934 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003935 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003936 if let Some((ref colon_token, ref ty)) = self.ty {
3937 colon_token.to_tokens(tokens);
3938 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003939 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003940 if let Some((ref eq_token, ref init)) = self.init {
3941 eq_token.to_tokens(tokens);
3942 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003943 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003944 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003945 }
3946 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003947}