blob: 69f449dedb88e0e8f3e74ebf87cc58e755669474 [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -07002use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -07003use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -05004#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -05005use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -07006#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -05007use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -07008#[cfg(feature = "extra-traits")]
9use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070010
Alex Crichton62a0a592017-05-22 13:58:53 -070011ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080012 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080013 ///
David Tolnay461d98e2018-01-07 11:07:19 -080014 /// *This type is available if Syn is built with the `"derive"` or `"full"`
15 /// feature.*
16 ///
David Tolnay614a0142018-01-07 10:25:43 -080017 /// # Syntax tree enums
18 ///
19 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
20 /// are designed to be traversed using the following rebinding idiom.
21 ///
David Tolnay95989db2019-01-01 15:05:57 -050022 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080023 /// # use syn::Expr;
24 /// #
25 /// # fn example(expr: Expr) {
26 /// # const IGNORE: &str = stringify! {
27 /// let expr: Expr = /* ... */;
28 /// # };
29 /// match expr {
30 /// Expr::MethodCall(expr) => {
31 /// /* ... */
32 /// }
33 /// Expr::Cast(expr) => {
34 /// /* ... */
35 /// }
David Tolnay9c119122018-09-01 18:47:02 -070036 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080037 /// /* ... */
38 /// }
David Tolnay65336072019-04-22 23:10:52 -070039 ///
David Tolnay614a0142018-01-07 10:25:43 -080040 /// /* ... */
41 /// # _ => {}
David Tolnay65336072019-04-22 23:10:52 -070042 /// # }
David Tolnay614a0142018-01-07 10:25:43 -080043 /// # }
44 /// ```
45 ///
46 /// We begin with a variable `expr` of type `Expr` that has no fields
47 /// (because it is an enum), and by matching on it and rebinding a variable
48 /// with the same name `expr` we effectively imbue our variable with all of
49 /// the data fields provided by the variant that it turned out to be. So for
50 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070051 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
52 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080053 ///
David Tolnay614a0142018-01-07 10:25:43 -080054 /// This approach avoids repeating the variant names twice on every line.
55 ///
David Tolnay95989db2019-01-01 15:05:57 -050056 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080057 /// # use syn::{Expr, ExprMethodCall};
58 /// #
59 /// # fn example(expr: Expr) {
David Tolnay65336072019-04-22 23:10:52 -070060 /// // Repetitive; recommend not doing this.
61 /// match expr {
62 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
David Tolnay614a0142018-01-07 10:25:43 -080063 /// # }
64 /// # _ => {}
65 /// # }
66 /// # }
67 /// ```
68 ///
69 /// In general, the name to which a syntax tree enum variant is bound should
70 /// be a suitable name for the complete syntax tree enum type.
71 ///
David Tolnay95989db2019-01-01 15:05:57 -050072 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080073 /// # use syn::{Expr, ExprField};
74 /// #
David Tolnay65336072019-04-22 23:10:52 -070075 /// # fn example(discriminant: ExprField) {
David Tolnay614a0142018-01-07 10:25:43 -080076 /// // Binding is called `base` which is the name I would use if I were
77 /// // assigning `*discriminant.base` without an `if let`.
David Tolnay65336072019-04-22 23:10:52 -070078 /// if let Expr::Tuple(base) = *discriminant.base {
David Tolnay614a0142018-01-07 10:25:43 -080079 /// # }
80 /// # }
81 /// ```
82 ///
83 /// A sign that you may not be choosing the right variable names is if you
84 /// see names getting repeated in your code, like accessing
85 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -050086 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -080087 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -080088 ///
89 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040090 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -050091 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080092 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -050093 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -070094 }),
Clar Charrd22b5702017-03-10 15:24:56 -050095
David Tolnaya454c8f2018-01-07 01:01:10 -080096 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -080097 ///
98 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040099 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500100 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700101 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500102 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700103 pub value: Box<Expr>,
104 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500105
David Tolnaya454c8f2018-01-07 01:01:10 -0800106 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800107 ///
108 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400109 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500110 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500111 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500112 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500114
David Tolnaya454c8f2018-01-07 01:01:10 -0800115 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800116 ///
117 /// *This type is available if Syn is built with the `"derive"` or
118 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700119 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500122 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500123 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A method call expression: `x.foo::<T>(a, b)`.
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 MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500131 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800132 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500133 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500134 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500135 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500136 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700137 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500138
David Tolnaya454c8f2018-01-07 01:01:10 -0800139 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800140 ///
141 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500142 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500143 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500144 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500145 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700146 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500147
David Tolnaya454c8f2018-01-07 01:01:10 -0800148 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700152 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500153 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700154 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700156 pub right: Box<Expr>,
157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"derive"` or
162 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700163 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500164 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700165 pub op: UnOp,
166 pub expr: Box<Expr>,
167 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500168
David Tolnaya454c8f2018-01-07 01:01:10 -0800169 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800170 ///
171 /// *This type is available if Syn is built with the `"derive"` or
172 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub Lit(ExprLit {
174 pub attrs: Vec<Attribute>,
175 pub lit: Lit,
176 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500177
David Tolnaya454c8f2018-01-07 01:01:10 -0800178 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800179 ///
180 /// *This type is available if Syn is built with the `"derive"` or
181 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700182 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500183 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700184 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800185 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800186 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500192 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800195 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800196 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500198
David Tolnay9c119122018-09-01 18:47:02 -0700199 /// A `let` guard: `let Some(x) = opt`.
200 ///
201 /// *This type is available if Syn is built with the `"full"` feature.*
202 pub Let(ExprLet #full {
203 pub attrs: Vec<Attribute>,
204 pub let_token: Token![let],
205 pub pats: Punctuated<Pat, Token![|]>,
206 pub eq_token: Token![=],
207 pub expr: Box<Expr>,
208 }),
209
David Tolnaya454c8f2018-01-07 01:01:10 -0800210 /// An `if` expression with an optional `else` block: `if expr { ... }
211 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700212 ///
David Tolnay9c119122018-09-01 18:47:02 -0700213 /// The `else` branch expression may only be an `If` or `Block`
214 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800215 ///
216 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400217 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500218 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500219 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700220 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500221 pub then_branch: Block,
222 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700223 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500224
David Tolnaya454c8f2018-01-07 01:01:10 -0800225 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800226 ///
227 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400228 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500229 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500230 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800231 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500232 pub cond: Box<Expr>,
233 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700234 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500235
David Tolnaya454c8f2018-01-07 01:01:10 -0800236 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800237 ///
238 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400239 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500240 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500241 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500242 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500244 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700245 pub expr: Box<Expr>,
246 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700247 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500248
David Tolnaya454c8f2018-01-07 01:01:10 -0800249 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800250 ///
251 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400252 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500253 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500254 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500255 pub loop_token: Token![loop],
256 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700257 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500258
David Tolnaya454c8f2018-01-07 01:01:10 -0800259 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800260 ///
261 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400262 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500263 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800264 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500266 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 pub arms: Vec<Arm>,
268 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500269
David Tolnaya454c8f2018-01-07 01:01:10 -0800270 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800271 ///
272 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400273 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500274 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900275 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200276 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500277 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800278 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500279 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800280 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500281 pub output: ReturnType,
282 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700283 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500284
David Tolnaya454c8f2018-01-07 01:01:10 -0800285 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800286 ///
287 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500288 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500289 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500290 pub unsafe_token: Token![unsafe],
291 pub block: Block,
292 }),
293
David Tolnaya454c8f2018-01-07 01:01:10 -0800294 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800295 ///
296 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400297 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500298 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400299 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700300 pub block: Block,
301 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700302
David Tolnaya454c8f2018-01-07 01:01:10 -0800303 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800304 ///
305 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400306 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500307 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500310 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700311 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500312
David Tolnaya454c8f2018-01-07 01:01:10 -0800313 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800314 ///
315 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400316 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500317 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700318 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500319 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub right: Box<Expr>,
321 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500324 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800325 ///
326 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700327 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500328 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500329 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800330 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500331 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500333
David Tolnay05658502018-01-07 09:56:37 -0800334 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800335 ///
336 /// *This type is available if Syn is built with the `"derive"` or
337 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500341 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500342 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700343 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500344
David Tolnaya454c8f2018-01-07 01:01:10 -0800345 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800346 ///
347 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400348 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500349 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700350 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700351 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500352 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700353 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700354
David Tolnaya454c8f2018-01-07 01:01:10 -0800355 /// A path like `std::mem::replace` possibly containing generic
356 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700357 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800358 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800359 ///
360 /// *This type is available if Syn is built with the `"derive"` or
361 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700362 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500363 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700364 pub qself: Option<QSelf>,
365 pub path: Path,
366 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700367
David Tolnaya454c8f2018-01-07 01:01:10 -0800368 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800369 ///
370 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200371 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500372 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800373 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500374 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700375 pub expr: Box<Expr>,
376 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500377
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A `break`, with an optional label to break and an optional
379 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800380 ///
381 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400382 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500384 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700385 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700386 pub expr: Option<Box<Expr>>,
387 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500388
David Tolnaya454c8f2018-01-07 01:01:10 -0800389 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800390 ///
391 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400392 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500393 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800394 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500395 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500401 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500402 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800403 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700406
David Tolnaya454c8f2018-01-07 01:01:10 -0800407 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800408 ///
409 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500410 pub Macro(ExprMacro #full {
411 pub attrs: Vec<Attribute>,
412 pub mac: Macro,
413 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700414
David Tolnaya454c8f2018-01-07 01:01:10 -0800415 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800417 /// The `rest` provides the value of the remaining fields as in `S { a:
418 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400421 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700423 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500424 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500425 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500426 pub dot2_token: Option<Token![..]>,
427 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700428 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// An array literal constructed from one repeated element: `[0u8; N]`.
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 Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500435 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500437 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800438 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700439 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700440
David Tolnaya454c8f2018-01-07 01:01:10 -0800441 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800442 ///
443 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800444 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500445 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500446 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500447 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700449
David Tolnaya454c8f2018-01-07 01:01:10 -0800450 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400451 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800452 /// This variant is important for faithfully representing the precedence
453 /// of expressions and is related to `None`-delimited spans in a
454 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800455 ///
456 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500457 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500458 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500459 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500460 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400461 }),
462
David Tolnaya454c8f2018-01-07 01:01:10 -0800463 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800464 ///
465 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400466 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500467 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800469 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700471
David Tolnay02a9c6f2018-08-24 18:58:45 -0400472 /// An async block: `async { ... }`.
473 ///
474 /// *This type is available if Syn is built with the `"full"` feature.*
475 pub Async(ExprAsync #full {
476 pub attrs: Vec<Attribute>,
477 pub async_token: Token![async],
478 pub capture: Option<Token![move]>,
479 pub block: Block,
480 }),
481
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400482 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400485 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400487 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub block: Block,
489 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800492 ///
493 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700494 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500495 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800496 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700497 pub expr: Option<Box<Expr>>,
498 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500499
David Tolnaya454c8f2018-01-07 01:01:10 -0800500 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800501 ///
502 /// *This type is available if Syn is built with the `"derive"` or
503 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500504 pub Verbatim(ExprVerbatim #manual_extra_traits {
505 pub tts: TokenStream,
506 }),
507 }
508}
509
510#[cfg(feature = "extra-traits")]
511impl Eq for ExprVerbatim {}
512
513#[cfg(feature = "extra-traits")]
514impl PartialEq for ExprVerbatim {
515 fn eq(&self, other: &Self) -> bool {
516 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
517 }
518}
519
520#[cfg(feature = "extra-traits")]
521impl Hash for ExprVerbatim {
522 fn hash<H>(&self, state: &mut H)
523 where
524 H: Hasher,
525 {
526 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700527 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700528}
529
David Tolnay8c91b882017-12-28 23:04:32 -0500530impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700531 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700532 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500533 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800534 Expr::Box(ExprBox { ref mut attrs, .. })
535 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
536 | Expr::Array(ExprArray { ref mut attrs, .. })
537 | Expr::Call(ExprCall { ref mut attrs, .. })
538 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
539 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
540 | Expr::Binary(ExprBinary { ref mut attrs, .. })
541 | Expr::Unary(ExprUnary { ref mut attrs, .. })
542 | Expr::Lit(ExprLit { ref mut attrs, .. })
543 | Expr::Cast(ExprCast { ref mut attrs, .. })
544 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700545 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800546 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800547 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800548 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
549 | Expr::Loop(ExprLoop { ref mut attrs, .. })
550 | Expr::Match(ExprMatch { ref mut attrs, .. })
551 | Expr::Closure(ExprClosure { ref mut attrs, .. })
552 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
553 | Expr::Block(ExprBlock { ref mut attrs, .. })
554 | Expr::Assign(ExprAssign { ref mut attrs, .. })
555 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
556 | Expr::Field(ExprField { ref mut attrs, .. })
557 | Expr::Index(ExprIndex { ref mut attrs, .. })
558 | Expr::Range(ExprRange { ref mut attrs, .. })
559 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200560 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800561 | Expr::Break(ExprBreak { ref mut attrs, .. })
562 | Expr::Continue(ExprContinue { ref mut attrs, .. })
563 | Expr::Return(ExprReturn { ref mut attrs, .. })
564 | Expr::Macro(ExprMacro { ref mut attrs, .. })
565 | Expr::Struct(ExprStruct { ref mut attrs, .. })
566 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
567 | Expr::Paren(ExprParen { ref mut attrs, .. })
568 | Expr::Group(ExprGroup { ref mut attrs, .. })
569 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400570 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400571 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800572 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700573 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500574 }
575 }
576}
577
David Tolnay85b69a42017-12-27 20:43:10 -0500578ast_enum! {
579 /// A struct or tuple struct field accessed in a struct literal or field
580 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800581 ///
582 /// *This type is available if Syn is built with the `"derive"` or `"full"`
583 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500584 pub enum Member {
585 /// A named field like `self.x`.
586 Named(Ident),
587 /// An unnamed field like `self.0`.
588 Unnamed(Index),
589 }
590}
591
David Tolnay85b69a42017-12-27 20:43:10 -0500592ast_struct! {
593 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800594 ///
595 /// *This type is available if Syn is built with the `"derive"` or `"full"`
596 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500597 pub struct Index #manual_extra_traits {
598 pub index: u32,
599 pub span: Span,
600 }
601}
602
David Tolnay14982012017-12-29 00:49:51 -0500603impl From<usize> for Index {
604 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700605 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500606 Index {
607 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700608 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500609 }
610 }
611}
612
613#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500614impl Eq for Index {}
615
David Tolnay14982012017-12-29 00:49:51 -0500616#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500617impl PartialEq for Index {
618 fn eq(&self, other: &Self) -> bool {
619 self.index == other.index
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500624impl Hash for Index {
625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.index.hash(state);
627 }
628}
629
630#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700631ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800632 /// The `::<>` explicit type parameters passed to a method call:
633 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800634 ///
635 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500636 pub struct MethodTurbofish {
637 pub colon2_token: Token![::],
638 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500639 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500640 pub gt_token: Token![>],
641 }
642}
643
644#[cfg(feature = "full")]
645ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800646 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800647 ///
648 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500649 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800650 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500651 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500653 ///
654 /// NOTE: Identity expressions are represented as Type arguments, as
655 /// they are indistinguishable syntactically.
656 Const(Expr),
657 }
658}
659
660#[cfg(feature = "full")]
661ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700662 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800663 ///
664 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700665 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500666 /// Attributes tagged on the field.
667 pub attrs: Vec<Attribute>,
668
669 /// Name or index of the field.
670 pub member: Member,
671
David Tolnay5d7098a2017-12-29 01:35:24 -0500672 /// The colon in `Struct { x: x }`. If written in shorthand like
673 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500674 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500675
Alex Crichton62a0a592017-05-22 13:58:53 -0700676 /// Value of the field.
677 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700678 }
David Tolnay055a7042016-10-02 19:23:54 -0700679}
680
Michael Layzell734adb42017-06-07 16:58:31 -0400681#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700682ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800683 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800684 ///
685 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500686 pub struct Label {
687 pub name: Lifetime,
688 pub colon_token: Token![:],
689 }
690}
691
692#[cfg(feature = "full")]
693ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800695 ///
696 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700697 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500698 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700699 /// Statements in a block
700 pub stmts: Vec<Stmt>,
701 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700702}
703
Michael Layzell734adb42017-06-07 16:58:31 -0400704#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700705ast_enum! {
706 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub enum Stmt {
710 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800711 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700712
Alex Crichton62a0a592017-05-22 13:58:53 -0700713 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800714 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700715
Alex Crichton62a0a592017-05-22 13:58:53 -0700716 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800717 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700718
David Tolnaya454c8f2018-01-07 01:01:10 -0800719 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800720 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700721 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700722}
723
Michael Layzell734adb42017-06-07 16:58:31 -0400724#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700725ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800726 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700729 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500730 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800731 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200732 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500733 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500734 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500735 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700737}
738
Michael Layzell734adb42017-06-07 16:58:31 -0400739#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700740ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A pattern in a local binding, function signature, match expression, or
742 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800743 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800744 /// *This type is available if Syn is built with the `"full"` feature.*
745 ///
David Tolnay614a0142018-01-07 10:25:43 -0800746 /// # Syntax tree enum
747 ///
748 /// This type is a [syntax tree enum].
749 ///
750 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700751 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800752 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800753 ///
754 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700755 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800756 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700757 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700758
David Tolnaya454c8f2018-01-07 01:01:10 -0800759 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800760 ///
761 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700762 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500763 pub by_ref: Option<Token![ref]>,
764 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500766 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700767 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700768
David Tolnaya454c8f2018-01-07 01:01:10 -0800769 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800770 ///
771 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700772 pub Struct(PatStruct {
773 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500774 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500775 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800776 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700777 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700778
David Tolnaya454c8f2018-01-07 01:01:10 -0800779 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800780 ///
781 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700782 pub TupleStruct(PatTupleStruct {
783 pub path: Path,
784 pub pat: PatTuple,
785 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700786
David Tolnaya454c8f2018-01-07 01:01:10 -0800787 /// A path pattern like `Color::Red`, optionally qualified with a
788 /// self-type.
789 ///
Daniel Muellerd3d71a12019-01-28 06:10:46 -0800790 /// Unqualified path patterns can legally refer to variants, structs,
791 /// constants or associated constants. Qualified path patterns like
David Tolnaya454c8f2018-01-07 01:01:10 -0800792 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
793 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800794 ///
795 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700796 pub Path(PatPath {
797 pub qself: Option<QSelf>,
798 pub path: Path,
799 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700800
David Tolnaya454c8f2018-01-07 01:01:10 -0800801 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800802 ///
803 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500805 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500806 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500807 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500808 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500809 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700810 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800811
812 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800813 ///
814 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800816 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500817 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700818 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800819
820 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800821 ///
822 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700823 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800824 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500825 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500826 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800828
829 /// A literal pattern: `0`.
830 ///
831 /// This holds an `Expr` rather than a `Lit` because negative numbers
832 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800833 ///
834 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700835 pub Lit(PatLit {
836 pub expr: Box<Expr>,
837 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800838
839 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800840 ///
841 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700842 pub Range(PatRange {
843 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700844 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500845 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800847
848 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800849 ///
850 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700851 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500852 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500855 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500856 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500857 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700858 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800859
860 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800861 ///
862 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500863 pub Macro(PatMacro {
864 pub mac: Macro,
865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500870 pub Verbatim(PatVerbatim #manual_extra_traits {
871 pub tts: TokenStream,
872 }),
873 }
874}
875
David Tolnayc43b44e2017-12-30 23:55:54 -0500876#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500877impl Eq for PatVerbatim {}
878
David Tolnayc43b44e2017-12-30 23:55:54 -0500879#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500880impl PartialEq for PatVerbatim {
881 fn eq(&self, other: &Self) -> bool {
882 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
883 }
884}
885
David Tolnayc43b44e2017-12-30 23:55:54 -0500886#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500887impl Hash for PatVerbatim {
888 fn hash<H>(&self, state: &mut H)
889 where
890 H: Hasher,
891 {
892 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700893 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700894}
895
Michael Layzell734adb42017-06-07 16:58:31 -0400896#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700897ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800898 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700899 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800900 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700901 ///
David Tolnay95989db2019-01-01 15:05:57 -0500902 /// ```edition2018
David Tolnaya454c8f2018-01-07 01:01:10 -0800903 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500904 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700905 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800906 /// 0...10 => {
907 /// return true;
908 /// }
909 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500910 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700911 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800912 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500913 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700914 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700917 pub struct Arm {
918 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200919 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500920 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500921 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200922 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700923 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800924 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700925 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700926}
927
Michael Layzell734adb42017-06-07 16:58:31 -0400928#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700929ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800930 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800931 ///
932 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700933 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700934 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800935 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800936 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800937 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800938 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700939 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700940}
941
Michael Layzell734adb42017-06-07 16:58:31 -0400942#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700943ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800944 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700945 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800946 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
947 /// 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 -0800948 ///
949 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700950 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500951 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500952 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500953 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700954 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700956}
957
Michael Layzell3936ceb2017-07-08 00:28:36 -0400958#[cfg(any(feature = "parsing", feature = "printing"))]
959#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700960fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700961 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500962 match *expr {
963 Expr::Unsafe(..)
964 | Expr::Block(..)
965 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500966 | Expr::Match(..)
967 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500968 | Expr::Loop(..)
969 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400970 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400971 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700972 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400973 }
974}
975
David Tolnayb9c8e322016-09-23 20:48:37 -0700976#[cfg(feature = "parsing")]
977pub mod parsing {
978 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700979
Michael Layzell734adb42017-06-07 16:58:31 -0400980 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -0700981 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -0700982 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -0700983 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700984
David Tolnaybcf26022017-12-25 22:10:52 -0500985 // When we're parsing expressions which occur before blocks, like in an if
986 // statement's condition, we cannot parse a struct literal.
987 //
988 // Struct literals are ambiguous in certain positions
989 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -0700990 #[derive(Copy, Clone)]
991 pub struct AllowStruct(bool);
992
David Tolnay01218d12018-08-29 18:13:07 -0700993 #[derive(Copy, Clone, PartialEq, PartialOrd)]
994 enum Precedence {
995 Any,
996 Assign,
David Tolnay01218d12018-08-29 18:13:07 -0700997 Range,
998 Or,
999 And,
1000 Compare,
1001 BitOr,
1002 BitXor,
1003 BitAnd,
1004 Shift,
1005 Arithmetic,
1006 Term,
1007 Cast,
1008 }
1009
1010 impl Precedence {
1011 fn of(op: &BinOp) -> Self {
1012 match *op {
1013 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1014 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1015 BinOp::And(_) => Precedence::And,
1016 BinOp::Or(_) => Precedence::Or,
1017 BinOp::BitXor(_) => Precedence::BitXor,
1018 BinOp::BitAnd(_) => Precedence::BitAnd,
1019 BinOp::BitOr(_) => Precedence::BitOr,
1020 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001021 BinOp::Eq(_)
1022 | BinOp::Lt(_)
1023 | BinOp::Le(_)
1024 | BinOp::Ne(_)
1025 | BinOp::Ge(_)
1026 | BinOp::Gt(_) => Precedence::Compare,
1027 BinOp::AddEq(_)
1028 | BinOp::SubEq(_)
1029 | BinOp::MulEq(_)
1030 | BinOp::DivEq(_)
1031 | BinOp::RemEq(_)
1032 | BinOp::BitXorEq(_)
1033 | BinOp::BitAndEq(_)
1034 | BinOp::BitOrEq(_)
1035 | BinOp::ShlEq(_)
1036 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001037 }
1038 }
1039 }
1040
David Tolnay9389c382018-08-27 09:13:37 -07001041 impl Parse for Expr {
1042 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001043 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001044 }
1045 }
1046
Michael Layzell734adb42017-06-07 16:58:31 -04001047 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001048 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001049 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001050 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001051
David Tolnay01218d12018-08-29 18:13:07 -07001052 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001053 fn parse_expr(
1054 input: ParseStream,
1055 mut lhs: Expr,
1056 allow_struct: AllowStruct,
1057 base: Precedence,
1058 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001059 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001060 if input
1061 .fork()
1062 .parse::<BinOp>()
1063 .ok()
1064 .map_or(false, |op| Precedence::of(&op) >= base)
1065 {
David Tolnay01218d12018-08-29 18:13:07 -07001066 let op: BinOp = input.parse()?;
1067 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001068 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001069 loop {
1070 let next = peek_precedence(input);
1071 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001072 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001073 } else {
1074 break;
1075 }
1076 }
David Tolnay90276252018-08-31 10:50:08 -07001077 lhs = if precedence == Precedence::Assign {
1078 Expr::AssignOp(ExprAssignOp {
1079 attrs: Vec::new(),
1080 left: Box::new(lhs),
1081 op: op,
1082 right: Box::new(rhs),
1083 })
1084 } else {
1085 Expr::Binary(ExprBinary {
1086 attrs: Vec::new(),
1087 left: Box::new(lhs),
1088 op: op,
1089 right: Box::new(rhs),
1090 })
1091 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001092 } else if Precedence::Assign >= base
1093 && input.peek(Token![=])
1094 && !input.peek(Token![==])
1095 && !input.peek(Token![=>])
1096 {
David Tolnay01218d12018-08-29 18:13:07 -07001097 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001098 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001099 loop {
1100 let next = peek_precedence(input);
1101 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001102 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001103 } else {
1104 break;
1105 }
1106 }
1107 lhs = Expr::Assign(ExprAssign {
1108 attrs: Vec::new(),
1109 left: Box::new(lhs),
1110 eq_token: eq_token,
1111 right: Box::new(rhs),
1112 });
David Tolnay01218d12018-08-29 18:13:07 -07001113 } else if Precedence::Range >= base && input.peek(Token![..]) {
1114 let limits: RangeLimits = input.parse()?;
1115 let rhs = if input.is_empty()
1116 || input.peek(Token![,])
1117 || input.peek(Token![;])
1118 || !allow_struct.0 && input.peek(token::Brace)
1119 {
1120 None
1121 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001122 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001123 loop {
1124 let next = peek_precedence(input);
1125 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001126 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001127 } else {
1128 break;
1129 }
1130 }
1131 Some(rhs)
1132 };
1133 lhs = Expr::Range(ExprRange {
1134 attrs: Vec::new(),
1135 from: Some(Box::new(lhs)),
1136 limits: limits,
1137 to: rhs.map(Box::new),
1138 });
1139 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1140 let as_token: Token![as] = input.parse()?;
1141 let ty = input.call(Type::without_plus)?;
1142 lhs = Expr::Cast(ExprCast {
1143 attrs: Vec::new(),
1144 expr: Box::new(lhs),
1145 as_token: as_token,
1146 ty: Box::new(ty),
1147 });
1148 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1149 let colon_token: Token![:] = input.parse()?;
1150 let ty = input.call(Type::without_plus)?;
1151 lhs = Expr::Type(ExprType {
1152 attrs: Vec::new(),
1153 expr: Box::new(lhs),
1154 colon_token: colon_token,
1155 ty: Box::new(ty),
1156 });
1157 } else {
1158 break;
1159 }
1160 }
1161 Ok(lhs)
1162 }
1163
David Tolnay3e541292018-08-30 11:42:15 -07001164 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001165 fn parse_expr(
1166 input: ParseStream,
1167 mut lhs: Expr,
1168 allow_struct: AllowStruct,
1169 base: Precedence,
1170 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001171 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001172 if input
1173 .fork()
1174 .parse::<BinOp>()
1175 .ok()
1176 .map_or(false, |op| Precedence::of(&op) >= base)
1177 {
David Tolnay3e541292018-08-30 11:42:15 -07001178 let op: BinOp = input.parse()?;
1179 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001180 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001181 loop {
1182 let next = peek_precedence(input);
1183 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001184 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001185 } else {
1186 break;
1187 }
1188 }
1189 lhs = Expr::Binary(ExprBinary {
1190 attrs: Vec::new(),
1191 left: Box::new(lhs),
1192 op: op,
1193 right: Box::new(rhs),
1194 });
1195 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1196 let as_token: Token![as] = input.parse()?;
1197 let ty = input.call(Type::without_plus)?;
1198 lhs = Expr::Cast(ExprCast {
1199 attrs: Vec::new(),
1200 expr: Box::new(lhs),
1201 as_token: as_token,
1202 ty: Box::new(ty),
1203 });
1204 } else {
1205 break;
1206 }
1207 }
1208 Ok(lhs)
1209 }
1210
David Tolnay01218d12018-08-29 18:13:07 -07001211 fn peek_precedence(input: ParseStream) -> Precedence {
1212 if let Ok(op) = input.fork().parse() {
1213 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001214 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001215 Precedence::Assign
David Tolnay01218d12018-08-29 18:13:07 -07001216 } else if input.peek(Token![..]) {
1217 Precedence::Range
1218 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1219 Precedence::Cast
1220 } else {
1221 Precedence::Any
1222 }
1223 }
1224
David Tolnaybcf26022017-12-25 22:10:52 -05001225 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001226 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001227 let lhs = unary_expr(input, allow_struct)?;
1228 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001229 }
1230
David Tolnaybcf26022017-12-25 22:10:52 -05001231 // <UnOp> <trailer>
1232 // & <trailer>
1233 // &mut <trailer>
1234 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001235 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001236 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001237 let ahead = input.fork();
1238 ahead.call(Attribute::parse_outer)?;
1239 if ahead.peek(Token![&])
1240 || ahead.peek(Token![box])
1241 || ahead.peek(Token![*])
1242 || ahead.peek(Token![!])
1243 || ahead.peek(Token![-])
1244 {
1245 let attrs = input.call(Attribute::parse_outer)?;
1246 if input.peek(Token![&]) {
1247 Ok(Expr::Reference(ExprReference {
1248 attrs: attrs,
1249 and_token: input.parse()?,
1250 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001251 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001252 }))
1253 } else if input.peek(Token![box]) {
1254 Ok(Expr::Box(ExprBox {
1255 attrs: attrs,
1256 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001257 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001258 }))
1259 } else {
1260 Ok(Expr::Unary(ExprUnary {
1261 attrs: attrs,
1262 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001263 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001264 }))
1265 }
1266 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001267 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001268 }
1269 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001270
Michael Layzell734adb42017-06-07 16:58:31 -04001271 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001272 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001273 let ahead = input.fork();
1274 ahead.call(Attribute::parse_outer)?;
1275 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1276 Ok(Expr::Unary(ExprUnary {
1277 attrs: input.call(Attribute::parse_outer)?,
1278 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001279 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001280 }))
1281 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001282 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001283 }
1284 }
Michael Layzell734adb42017-06-07 16:58:31 -04001285
David Tolnaybcf26022017-12-25 22:10:52 -05001286 // <atom> (..<args>) ...
1287 // <atom> . <ident> (..<args>) ...
1288 // <atom> . <ident> ...
1289 // <atom> . <lit> ...
1290 // <atom> [ <expr> ] ...
1291 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001292 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001293 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001294 if input.peek(token::Group) {
1295 return input.call(expr_group).map(Expr::Group);
1296 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001297
David Tolnay577fd312018-09-01 02:26:40 -07001298 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001299
David Tolnay577fd312018-09-01 02:26:40 -07001300 let atom = atom_expr(input, allow_struct)?;
1301 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001302
David Tolnay577fd312018-09-01 02:26:40 -07001303 let inner_attrs = e.replace_attrs(Vec::new());
1304 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001305 e.replace_attrs(attrs);
1306 Ok(e)
1307 }
1308
1309 #[cfg(feature = "full")]
1310 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001311 loop {
1312 if input.peek(token::Paren) {
1313 let content;
1314 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001315 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001316 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001317 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001318 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001319 });
1320 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1321 let dot_token: Token![.] = input.parse()?;
1322 let member: Member = input.parse()?;
1323 let turbofish = if member.is_named() && input.peek(Token![::]) {
1324 Some(MethodTurbofish {
1325 colon2_token: input.parse()?,
1326 lt_token: input.parse()?,
1327 args: {
1328 let mut args = Punctuated::new();
1329 loop {
1330 if input.peek(Token![>]) {
1331 break;
1332 }
David Tolnay310b3262018-08-30 15:33:00 -07001333 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001334 args.push_value(value);
1335 if input.peek(Token![>]) {
1336 break;
1337 }
1338 let punct = input.parse()?;
1339 args.push_punct(punct);
1340 }
1341 args
1342 },
1343 gt_token: input.parse()?,
1344 })
1345 } else {
1346 None
1347 };
1348
1349 if turbofish.is_some() || input.peek(token::Paren) {
1350 if let Member::Named(method) = member {
1351 let content;
1352 e = Expr::MethodCall(ExprMethodCall {
1353 attrs: Vec::new(),
1354 receiver: Box::new(e),
1355 dot_token: dot_token,
1356 method: method,
1357 turbofish: turbofish,
1358 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001359 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001360 });
1361 continue;
1362 }
1363 }
1364
1365 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001366 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001367 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001368 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001369 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001370 });
1371 } else if input.peek(token::Bracket) {
1372 let content;
1373 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001374 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001375 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001376 bracket_token: bracketed!(content in input),
1377 index: content.parse()?,
1378 });
1379 } else if input.peek(Token![?]) {
1380 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001381 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001382 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001383 question_token: input.parse()?,
1384 });
1385 } else {
1386 break;
1387 }
1388 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001389 Ok(e)
1390 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001391
Michael Layzell734adb42017-06-07 16:58:31 -04001392 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001393 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001394 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001395
1396 loop {
1397 if input.peek(token::Paren) {
1398 let content;
1399 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001400 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001401 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001402 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001403 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001404 });
1405 } else if input.peek(Token![.]) {
1406 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001407 attrs: Vec::new(),
1408 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001409 dot_token: input.parse()?,
1410 member: input.parse()?,
1411 });
1412 } else if input.peek(token::Bracket) {
1413 let content;
1414 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001415 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001416 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001417 bracket_token: bracketed!(content in input),
1418 index: content.parse()?,
1419 });
1420 } else {
1421 break;
1422 }
1423 }
1424
1425 Ok(e)
1426 }
Michael Layzell734adb42017-06-07 16:58:31 -04001427
David Tolnaya454c8f2018-01-07 01:01:10 -08001428 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001429 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001430 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001431 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001432 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001433 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001434 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001435 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001436 } else if input.peek(Token![async])
1437 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1438 {
David Tolnay577fd312018-09-01 02:26:40 -07001439 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001440 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001441 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001442 } else if input.peek(Token![|])
1443 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1444 || input.peek(Token![static])
1445 || input.peek(Token![move])
1446 {
David Tolnay577fd312018-09-01 02:26:40 -07001447 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001448 } else if input.peek(Ident)
1449 || input.peek(Token![::])
1450 || input.peek(Token![<])
1451 || input.peek(Token![self])
1452 || input.peek(Token![Self])
1453 || input.peek(Token![super])
1454 || input.peek(Token![extern])
1455 || input.peek(Token![crate])
1456 {
David Tolnay577fd312018-09-01 02:26:40 -07001457 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001458 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001459 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001460 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001461 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001462 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001463 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001464 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001465 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001466 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001467 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001468 } else if input.peek(Token![let]) {
1469 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001470 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001471 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001472 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001473 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001474 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001475 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001476 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001477 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001478 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001479 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001481 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001482 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001483 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001484 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001485 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001486 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001487 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001488 } else if input.peek(Lifetime) {
1489 let the_label: Label = input.parse()?;
1490 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001491 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001493 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001495 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001496 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001497 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else {
1499 return Err(input.error("expected loop or block expression"));
1500 };
1501 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001502 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001503 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1504 | Expr::Loop(ExprLoop { ref mut label, .. })
1505 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001506 _ => unreachable!(),
1507 }
David Tolnay577fd312018-09-01 02:26:40 -07001508 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001509 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001510 Err(input.error("expected expression"))
1511 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001512 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001513
Michael Layzell734adb42017-06-07 16:58:31 -04001514 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001515 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001516 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001517 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001519 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001520 } else if input.peek(Ident)
1521 || input.peek(Token![::])
1522 || input.peek(Token![<])
1523 || input.peek(Token![self])
1524 || input.peek(Token![Self])
1525 || input.peek(Token![super])
1526 || input.peek(Token![extern])
1527 || input.peek(Token![crate])
1528 {
1529 input.parse().map(Expr::Path)
1530 } else {
1531 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1532 }
1533 }
1534
1535 #[cfg(feature = "full")]
1536 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1537 let expr: ExprPath = input.parse()?;
1538 if expr.qself.is_some() {
1539 return Ok(Expr::Path(expr));
1540 }
1541
1542 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1543 let mut contains_arguments = false;
1544 for segment in &expr.path.segments {
1545 match segment.arguments {
1546 PathArguments::None => {}
1547 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1548 contains_arguments = true;
1549 }
1550 }
1551 }
1552
1553 if !contains_arguments {
1554 let bang_token: Token![!] = input.parse()?;
1555 let (delimiter, tts) = mac::parse_delimiter(input)?;
1556 return Ok(Expr::Macro(ExprMacro {
1557 attrs: Vec::new(),
1558 mac: Macro {
1559 path: expr.path,
1560 bang_token: bang_token,
1561 delimiter: delimiter,
1562 tts: tts,
1563 },
1564 }));
1565 }
1566 }
1567
1568 if allow_struct.0 && input.peek(token::Brace) {
1569 let outer_attrs = Vec::new();
1570 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1571 } else {
1572 Ok(Expr::Path(expr))
1573 }
1574 }
1575
1576 #[cfg(feature = "full")]
1577 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1578 let content;
1579 let paren_token = parenthesized!(content in input);
1580 let inner_attrs = content.call(Attribute::parse_inner)?;
1581 if content.is_empty() {
1582 return Ok(Expr::Tuple(ExprTuple {
1583 attrs: inner_attrs,
1584 paren_token: paren_token,
1585 elems: Punctuated::new(),
1586 }));
1587 }
1588
1589 let first: Expr = content.parse()?;
1590 if content.is_empty() {
1591 return Ok(Expr::Paren(ExprParen {
1592 attrs: inner_attrs,
1593 paren_token: paren_token,
1594 expr: Box::new(first),
1595 }));
1596 }
1597
1598 let mut elems = Punctuated::new();
1599 elems.push_value(first);
1600 while !content.is_empty() {
1601 let punct = content.parse()?;
1602 elems.push_punct(punct);
1603 if content.is_empty() {
1604 break;
1605 }
1606 let value = content.parse()?;
1607 elems.push_value(value);
1608 }
1609 Ok(Expr::Tuple(ExprTuple {
1610 attrs: inner_attrs,
1611 paren_token: paren_token,
1612 elems: elems,
1613 }))
1614 }
1615
1616 #[cfg(feature = "full")]
1617 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1618 let content;
1619 let bracket_token = bracketed!(content in input);
1620 let inner_attrs = content.call(Attribute::parse_inner)?;
1621 if content.is_empty() {
1622 return Ok(Expr::Array(ExprArray {
1623 attrs: inner_attrs,
1624 bracket_token: bracket_token,
1625 elems: Punctuated::new(),
1626 }));
1627 }
1628
1629 let first: Expr = content.parse()?;
1630 if content.is_empty() || content.peek(Token![,]) {
1631 let mut elems = Punctuated::new();
1632 elems.push_value(first);
1633 while !content.is_empty() {
1634 let punct = content.parse()?;
1635 elems.push_punct(punct);
1636 if content.is_empty() {
1637 break;
1638 }
1639 let value = content.parse()?;
1640 elems.push_value(value);
1641 }
1642 Ok(Expr::Array(ExprArray {
1643 attrs: inner_attrs,
1644 bracket_token: bracket_token,
1645 elems: elems,
1646 }))
1647 } else if content.peek(Token![;]) {
1648 let semi_token: Token![;] = content.parse()?;
1649 let len: Expr = content.parse()?;
1650 Ok(Expr::Repeat(ExprRepeat {
1651 attrs: inner_attrs,
1652 bracket_token: bracket_token,
1653 expr: Box::new(first),
1654 semi_token: semi_token,
1655 len: Box::new(len),
1656 }))
1657 } else {
1658 Err(content.error("expected `,` or `;`"))
1659 }
1660 }
Michael Layzell734adb42017-06-07 16:58:31 -04001661
Michael Layzell734adb42017-06-07 16:58:31 -04001662 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001663 fn expr_early(input: ParseStream) -> Result<Expr> {
1664 let mut attrs = input.call(Attribute::parse_outer)?;
1665 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001666 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001667 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001668 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001669 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001670 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001671 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001672 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001673 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001674 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001675 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001676 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001677 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001678 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001679 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001680 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001681 } else {
1682 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001683 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001684
1685 attrs.extend(expr.replace_attrs(Vec::new()));
1686 expr.replace_attrs(attrs);
1687
David Tolnay7d2e1db2018-08-30 11:49:04 -07001688 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001689 };
1690
1691 if input.peek(Token![.]) || input.peek(Token![?]) {
1692 expr = trailer_helper(input, expr)?;
1693
1694 attrs.extend(expr.replace_attrs(Vec::new()));
1695 expr.replace_attrs(attrs);
1696
1697 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001698 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001699 }
1700
1701 attrs.extend(expr.replace_attrs(Vec::new()));
1702 expr.replace_attrs(attrs);
1703 Ok(expr)
1704 }
Michael Layzell35418782017-06-07 09:20:25 -04001705
Peter Hall04f42792019-04-02 16:58:45 +02001706 impl Parse for ExprLit {
1707 fn parse(input: ParseStream) -> Result<Self> {
1708 Ok(ExprLit {
1709 attrs: Vec::new(),
1710 lit: input.parse()?,
1711 })
1712 }
David Tolnay8c91b882017-12-28 23:04:32 -05001713 }
1714
1715 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001716 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001717 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001718 Ok(ExprGroup {
1719 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001720 group_token: group.token,
1721 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001722 })
1723 }
1724
1725 #[cfg(not(feature = "full"))]
1726 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1727 let content;
1728 Ok(ExprParen {
1729 attrs: Vec::new(),
1730 paren_token: parenthesized!(content in input),
1731 expr: content.parse()?,
1732 })
David Tolnay8c91b882017-12-28 23:04:32 -05001733 }
1734
David Tolnaye98775f2017-12-28 23:17:00 -05001735 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001736 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001737 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001738 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001739 }
1740
1741 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001742 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1743 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001744 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001745 let_token: input.parse()?,
1746 pats: {
1747 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001748 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001749 let value: Pat = input.parse()?;
1750 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001751 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001752 let punct = input.parse()?;
1753 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001754 let value: Pat = input.parse()?;
1755 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001756 }
1757 pats
1758 },
1759 eq_token: input.parse()?,
1760 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001761 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001762 }
1763
Michael Layzell734adb42017-06-07 16:58:31 -04001764 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001765 impl Parse for ExprIf {
1766 fn parse(input: ParseStream) -> Result<Self> {
1767 Ok(ExprIf {
1768 attrs: Vec::new(),
1769 if_token: input.parse()?,
1770 cond: Box::new(input.call(expr_no_struct)?),
1771 then_branch: input.parse()?,
1772 else_branch: {
1773 if input.peek(Token![else]) {
1774 Some(input.call(else_block)?)
1775 } else {
1776 None
1777 }
1778 },
1779 })
1780 }
Alex Crichton954046c2017-05-30 21:49:42 -07001781 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001782
Michael Layzell734adb42017-06-07 16:58:31 -04001783 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001784 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1785 let else_token: Token![else] = input.parse()?;
1786
1787 let lookahead = input.lookahead1();
1788 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001789 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001790 } else if input.peek(token::Brace) {
1791 Expr::Block(ExprBlock {
1792 attrs: Vec::new(),
1793 label: None,
1794 block: input.parse()?,
1795 })
1796 } else {
1797 return Err(lookahead.error());
1798 };
1799
1800 Ok((else_token, Box::new(else_branch)))
1801 }
David Tolnay939766a2016-09-23 23:48:12 -07001802
Michael Layzell734adb42017-06-07 16:58:31 -04001803 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001804 impl Parse for ExprForLoop {
1805 fn parse(input: ParseStream) -> Result<Self> {
1806 let label: Option<Label> = input.parse()?;
1807 let for_token: Token![for] = input.parse()?;
1808 let pat: Pat = input.parse()?;
1809 let in_token: Token![in] = input.parse()?;
1810 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001811
Peter Hall04f42792019-04-02 16:58:45 +02001812 let content;
1813 let brace_token = braced!(content in input);
1814 let inner_attrs = content.call(Attribute::parse_inner)?;
1815 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001816
Peter Hall04f42792019-04-02 16:58:45 +02001817 Ok(ExprForLoop {
1818 attrs: inner_attrs,
1819 label: label,
1820 for_token: for_token,
1821 pat: Box::new(pat),
1822 in_token: in_token,
1823 expr: Box::new(expr),
1824 body: Block {
1825 brace_token: brace_token,
1826 stmts: stmts,
1827 },
1828 })
1829 }
Alex Crichton954046c2017-05-30 21:49:42 -07001830 }
David Tolnay1978c672016-10-27 22:05:52 -07001831
Michael Layzell734adb42017-06-07 16:58:31 -04001832 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001833 impl Parse for ExprLoop {
1834 fn parse(input: ParseStream) -> Result<Self> {
1835 let label: Option<Label> = input.parse()?;
1836 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001837
Peter Hall04f42792019-04-02 16:58:45 +02001838 let content;
1839 let brace_token = braced!(content in input);
1840 let inner_attrs = content.call(Attribute::parse_inner)?;
1841 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001842
Peter Hall04f42792019-04-02 16:58:45 +02001843 Ok(ExprLoop {
1844 attrs: inner_attrs,
1845 label: label,
1846 loop_token: loop_token,
1847 body: Block {
1848 brace_token: brace_token,
1849 stmts: stmts,
1850 },
1851 })
1852 }
Alex Crichton954046c2017-05-30 21:49:42 -07001853 }
Arnavion02ef13f2017-04-25 00:54:31 -07001854
Michael Layzell734adb42017-06-07 16:58:31 -04001855 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001856 impl Parse for ExprMatch {
1857 fn parse(input: ParseStream) -> Result<Self> {
1858 let match_token: Token![match] = input.parse()?;
1859 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001860
Peter Hall55f00f72019-04-02 16:50:57 +02001861 let content;
1862 let brace_token = braced!(content in input);
1863 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001864
Peter Hall55f00f72019-04-02 16:50:57 +02001865 let mut arms = Vec::new();
1866 while !content.is_empty() {
1867 arms.push(content.call(Arm::parse)?);
1868 }
1869
1870 Ok(ExprMatch {
1871 attrs: inner_attrs,
1872 match_token: match_token,
1873 expr: Box::new(expr),
1874 brace_token: brace_token,
1875 arms: arms,
1876 })
David Tolnay310b3262018-08-30 15:33:00 -07001877 }
David Tolnay310b3262018-08-30 15:33:00 -07001878 }
1879
David Tolnaye52022b2019-05-25 00:26:54 -07001880 #[cfg(all(feature = "full", feature = "printing"))]
1881 impl Parse for ExprInPlace {
1882 fn parse(input: ParseStream) -> Result<Self> {
1883 let msg = "placement expression has been removed from Rust and is no longer parsed";
1884 Err(input.error(msg))
1885 }
1886 }
1887
bstriecde20e62019-05-05 13:29:15 -04001888 macro_rules! impl_by_parsing_expr {
David Tolnaye957eb62019-05-07 22:02:51 -07001889 (
1890 $(
1891 $expr_type:ty, $variant:ident, $msg:expr,
1892 )*
1893 ) => {
1894 $(
1895 #[cfg(all(feature = "full", feature = "printing"))]
1896 impl Parse for $expr_type {
1897 fn parse(input: ParseStream) -> Result<Self> {
1898 let mut expr: Expr = input.parse()?;
1899 loop {
1900 match expr {
1901 Expr::$variant(inner) => return Ok(inner),
1902 Expr::Group(next) => expr = *next.expr,
1903 _ => return Err(Error::new_spanned(expr, $msg)),
1904 }
bstrie1626c372019-05-05 13:44:57 -04001905 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001906 }
1907 }
David Tolnaye957eb62019-05-07 22:02:51 -07001908 )*
David Tolnaya58223d2019-05-07 21:58:15 -07001909 };
bstrie7b4f52d2019-04-30 18:44:21 -04001910 }
1911
David Tolnaye957eb62019-05-07 22:02:51 -07001912 impl_by_parsing_expr! {
1913 ExprBox, Box, "expected box expression",
David Tolnaye957eb62019-05-07 22:02:51 -07001914 ExprArray, Array, "expected slice literal expression",
1915 ExprCall, Call, "expected function call expression",
1916 ExprMethodCall, MethodCall, "expected method call expression",
1917 ExprTuple, Tuple, "expected tuple expression",
1918 ExprBinary, Binary, "expected binary operation",
1919 ExprUnary, Unary, "expected unary operation",
1920 ExprCast, Cast, "expected cast expression",
1921 ExprType, Type, "expected type ascription expression",
1922 ExprLet, Let, "expected let guard",
1923 ExprClosure, Closure, "expected closure expression",
1924 ExprUnsafe, Unsafe, "expected unsafe block",
1925 ExprBlock, Block, "expected blocked scope",
1926 ExprAssign, Assign, "expected assignment expression",
1927 ExprAssignOp, AssignOp, "expected compound assignment expression",
1928 ExprField, Field, "expected struct field access",
1929 ExprIndex, Index, "expected indexing expression",
1930 ExprRange, Range, "expected range expression",
1931 ExprReference, Reference, "expected referencing operation",
1932 ExprBreak, Break, "expected break expression",
1933 ExprContinue, Continue, "expected continue expression",
1934 ExprReturn, Return, "expected return expression",
1935 ExprMacro, Macro, "expected macro invocation expression",
1936 ExprStruct, Struct, "expected struct literal expression",
1937 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
1938 ExprParen, Paren, "expected parenthesized expression",
1939 ExprTry, Try, "expected try expression",
1940 ExprAsync, Async, "expected async block",
1941 ExprTryBlock, TryBlock, "expected try block",
1942 ExprYield, Yield, "expected yield expression",
1943 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001944
David Tolnay310b3262018-08-30 15:33:00 -07001945 #[cfg(feature = "full")]
1946 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1947 Ok(ExprTryBlock {
1948 attrs: Vec::new(),
1949 try_token: input.parse()?,
1950 block: input.parse()?,
1951 })
1952 }
1953
1954 #[cfg(feature = "full")]
1955 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1956 Ok(ExprYield {
1957 attrs: Vec::new(),
1958 yield_token: input.parse()?,
1959 expr: {
1960 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1961 Some(input.parse()?)
1962 } else {
1963 None
1964 }
1965 },
1966 })
1967 }
1968
1969 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001970 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001971 let asyncness: Option<Token![async]> = input.parse()?;
1972 let movability: Option<Token![static]> = if asyncness.is_none() {
1973 input.parse()?
1974 } else {
1975 None
1976 };
1977 let capture: Option<Token![move]> = input.parse()?;
1978 let or1_token: Token![|] = input.parse()?;
1979
1980 let mut inputs = Punctuated::new();
1981 loop {
1982 if input.peek(Token![|]) {
1983 break;
1984 }
1985 let value = fn_arg(input)?;
1986 inputs.push_value(value);
1987 if input.peek(Token![|]) {
1988 break;
1989 }
1990 let punct: Token![,] = input.parse()?;
1991 inputs.push_punct(punct);
1992 }
1993
1994 let or2_token: Token![|] = input.parse()?;
1995
1996 let (output, body) = if input.peek(Token![->]) {
1997 let arrow_token: Token![->] = input.parse()?;
1998 let ty: Type = input.parse()?;
1999 let body: Block = input.parse()?;
2000 let output = ReturnType::Type(arrow_token, Box::new(ty));
2001 let block = Expr::Block(ExprBlock {
2002 attrs: Vec::new(),
2003 label: None,
2004 block: body,
2005 });
2006 (output, block)
2007 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002008 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002009 (ReturnType::Default, body)
2010 };
2011
2012 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002013 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002014 asyncness: asyncness,
2015 movability: movability,
2016 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002017 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002018 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002019 or2_token: or2_token,
2020 output: output,
2021 body: Box::new(body),
2022 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002023 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002024
2025 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002026 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2027 Ok(ExprAsync {
2028 attrs: Vec::new(),
2029 async_token: input.parse()?,
2030 capture: input.parse()?,
2031 block: input.parse()?,
2032 })
David Tolnay60291082018-08-28 09:54:49 -07002033 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002034
Michael Layzell734adb42017-06-07 16:58:31 -04002035 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002036 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2037 let pat: Pat = input.parse()?;
2038
2039 if input.peek(Token![:]) {
2040 Ok(FnArg::Captured(ArgCaptured {
2041 pat: pat,
2042 colon_token: input.parse()?,
2043 ty: input.parse()?,
2044 }))
2045 } else {
2046 Ok(FnArg::Inferred(pat))
2047 }
2048 }
2049
2050 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002051 impl Parse for ExprWhile {
2052 fn parse(input: ParseStream) -> Result<Self> {
2053 let label: Option<Label> = input.parse()?;
2054 let while_token: Token![while] = input.parse()?;
2055 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002056
Peter Hall04f42792019-04-02 16:58:45 +02002057 let content;
2058 let brace_token = braced!(content in input);
2059 let inner_attrs = content.call(Attribute::parse_inner)?;
2060 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002061
Peter Hall04f42792019-04-02 16:58:45 +02002062 Ok(ExprWhile {
2063 attrs: inner_attrs,
2064 label: label,
2065 while_token: while_token,
2066 cond: Box::new(cond),
2067 body: Block {
2068 brace_token: brace_token,
2069 stmts: stmts,
2070 },
2071 })
2072 }
Alex Crichton954046c2017-05-30 21:49:42 -07002073 }
2074
Michael Layzell734adb42017-06-07 16:58:31 -04002075 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002076 impl Parse for Label {
2077 fn parse(input: ParseStream) -> Result<Self> {
2078 Ok(Label {
2079 name: input.parse()?,
2080 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002081 })
David Tolnay60291082018-08-28 09:54:49 -07002082 }
Alex Crichton954046c2017-05-30 21:49:42 -07002083 }
2084
Michael Layzell734adb42017-06-07 16:58:31 -04002085 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002086 impl Parse for Option<Label> {
2087 fn parse(input: ParseStream) -> Result<Self> {
2088 if input.peek(Lifetime) {
2089 input.parse().map(Some)
2090 } else {
2091 Ok(None)
2092 }
2093 }
2094 }
2095
2096 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002097 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2098 Ok(ExprContinue {
2099 attrs: Vec::new(),
2100 continue_token: input.parse()?,
2101 label: input.parse()?,
2102 })
Alex Crichton954046c2017-05-30 21:49:42 -07002103 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002104
Michael Layzell734adb42017-06-07 16:58:31 -04002105 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002106 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2107 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002108 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002109 break_token: input.parse()?,
2110 label: input.parse()?,
2111 expr: {
2112 if input.is_empty()
2113 || input.peek(Token![,])
2114 || input.peek(Token![;])
2115 || !allow_struct.0 && input.peek(token::Brace)
2116 {
2117 None
2118 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002119 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002120 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002121 }
David Tolnay60291082018-08-28 09:54:49 -07002122 },
2123 })
Alex Crichton954046c2017-05-30 21:49:42 -07002124 }
2125
Michael Layzell734adb42017-06-07 16:58:31 -04002126 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002127 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2128 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002129 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002130 return_token: input.parse()?,
2131 expr: {
2132 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2133 None
2134 } else {
2135 // NOTE: return is greedy and eats blocks after it even when in a
2136 // position where structs are not allowed, such as in if statement
2137 // conditions. For example:
2138 //
2139 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002140 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002141 Some(Box::new(expr))
2142 }
2143 },
2144 })
2145 }
2146
2147 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002148 impl Parse for FieldValue {
2149 fn parse(input: ParseStream) -> Result<Self> {
2150 let member: Member = input.parse()?;
2151 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2152 let colon_token: Token![:] = input.parse()?;
2153 let value: Expr = input.parse()?;
2154 (Some(colon_token), value)
2155 } else if let Member::Named(ref ident) = member {
2156 let value = Expr::Path(ExprPath {
2157 attrs: Vec::new(),
2158 qself: None,
2159 path: Path::from(ident.clone()),
2160 });
2161 (None, value)
2162 } else {
2163 unreachable!()
2164 };
2165
2166 Ok(FieldValue {
2167 attrs: Vec::new(),
2168 member: member,
2169 colon_token: colon_token,
2170 expr: value,
2171 })
2172 }
2173 }
2174
2175 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002176 fn expr_struct_helper(
2177 input: ParseStream,
2178 outer_attrs: Vec<Attribute>,
2179 path: Path,
2180 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002181 let content;
2182 let brace_token = braced!(content in input);
2183 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002184
David Tolnay6e1e5052018-08-30 10:21:48 -07002185 let mut fields = Punctuated::new();
2186 loop {
2187 let attrs = content.call(Attribute::parse_outer)?;
2188 if content.fork().parse::<Member>().is_err() {
2189 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002190 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002191 } else {
2192 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002193 }
David Tolnay60291082018-08-28 09:54:49 -07002194 }
2195
David Tolnay6e1e5052018-08-30 10:21:48 -07002196 fields.push(FieldValue {
2197 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002198 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002199 });
2200
2201 if !content.peek(Token![,]) {
2202 break;
2203 }
2204 let punct: Token![,] = content.parse()?;
2205 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002206 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002207
2208 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2209 let dot2_token: Token![..] = content.parse()?;
2210 let rest: Expr = content.parse()?;
2211 (Some(dot2_token), Some(Box::new(rest)))
2212 } else {
2213 (None, None)
2214 };
2215
2216 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002217 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002218 brace_token: brace_token,
2219 path: path,
2220 fields: fields,
2221 dot2_token: dot2_token,
2222 rest: rest,
2223 })
Alex Crichton954046c2017-05-30 21:49:42 -07002224 }
David Tolnay055a7042016-10-02 19:23:54 -07002225
Michael Layzell734adb42017-06-07 16:58:31 -04002226 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002227 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2228 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002229
David Tolnay310b3262018-08-30 15:33:00 -07002230 let content;
2231 let brace_token = braced!(content in input);
2232 let inner_attrs = content.call(Attribute::parse_inner)?;
2233 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002234
David Tolnay310b3262018-08-30 15:33:00 -07002235 Ok(ExprUnsafe {
2236 attrs: inner_attrs,
2237 unsafe_token: unsafe_token,
2238 block: Block {
2239 brace_token: brace_token,
2240 stmts: stmts,
2241 },
2242 })
Alex Crichton954046c2017-05-30 21:49:42 -07002243 }
David Tolnay055a7042016-10-02 19:23:54 -07002244
Michael Layzell734adb42017-06-07 16:58:31 -04002245 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002246 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2247 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002248
David Tolnay310b3262018-08-30 15:33:00 -07002249 let content;
2250 let brace_token = braced!(content in input);
2251 let inner_attrs = content.call(Attribute::parse_inner)?;
2252 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002253
David Tolnay310b3262018-08-30 15:33:00 -07002254 Ok(ExprBlock {
2255 attrs: inner_attrs,
2256 label: label,
2257 block: Block {
2258 brace_token: brace_token,
2259 stmts: stmts,
2260 },
2261 })
Alex Crichton954046c2017-05-30 21:49:42 -07002262 }
David Tolnay89e05672016-10-02 14:39:42 -07002263
Michael Layzell734adb42017-06-07 16:58:31 -04002264 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002265 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2266 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002267 attrs: Vec::new(),
2268 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002269 limits: input.parse()?,
2270 to: {
2271 if input.is_empty()
2272 || input.peek(Token![,])
2273 || input.peek(Token![;])
2274 || !allow_struct.0 && input.peek(token::Brace)
2275 {
2276 None
2277 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002278 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002279 Some(Box::new(to))
2280 }
2281 },
2282 })
2283 }
David Tolnay438c9052016-10-07 23:24:48 -07002284
Michael Layzell734adb42017-06-07 16:58:31 -04002285 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002286 impl Parse for RangeLimits {
2287 fn parse(input: ParseStream) -> Result<Self> {
2288 let lookahead = input.lookahead1();
2289 if lookahead.peek(Token![..=]) {
2290 input.parse().map(RangeLimits::Closed)
2291 } else if lookahead.peek(Token![...]) {
2292 let dot3: Token![...] = input.parse()?;
2293 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2294 } else if lookahead.peek(Token![..]) {
2295 input.parse().map(RangeLimits::HalfOpen)
2296 } else {
2297 Err(lookahead.error())
2298 }
2299 }
Alex Crichton954046c2017-05-30 21:49:42 -07002300 }
David Tolnay438c9052016-10-07 23:24:48 -07002301
David Tolnay60291082018-08-28 09:54:49 -07002302 impl Parse for ExprPath {
2303 fn parse(input: ParseStream) -> Result<Self> {
2304 #[cfg(not(feature = "full"))]
2305 let attrs = Vec::new();
2306 #[cfg(feature = "full")]
2307 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002308
David Tolnay60291082018-08-28 09:54:49 -07002309 let (qself, path) = path::parsing::qpath(input, true)?;
2310
2311 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002312 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002313 qself: qself,
2314 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002315 })
David Tolnay60291082018-08-28 09:54:49 -07002316 }
Alex Crichton954046c2017-05-30 21:49:42 -07002317 }
David Tolnay42602292016-10-01 22:25:45 -07002318
Michael Layzell734adb42017-06-07 16:58:31 -04002319 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002320 impl Parse for Block {
2321 fn parse(input: ParseStream) -> Result<Self> {
2322 let content;
2323 Ok(Block {
2324 brace_token: braced!(content in input),
2325 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002326 })
David Tolnay60291082018-08-28 09:54:49 -07002327 }
Alex Crichton954046c2017-05-30 21:49:42 -07002328 }
David Tolnay939766a2016-09-23 23:48:12 -07002329
Michael Layzell734adb42017-06-07 16:58:31 -04002330 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002331 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002332 /// Parse the body of a block as zero or more statements, possibly
2333 /// including one trailing expression.
2334 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002335 /// *This function is available if Syn is built with the `"parsing"`
2336 /// feature.*
2337 ///
David Tolnay6b457252018-09-01 15:55:47 -07002338 /// # Example
2339 ///
David Tolnay95989db2019-01-01 15:05:57 -05002340 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002341 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002342 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002343 ///
2344 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002345 /// //
2346 /// // fn playground {
2347 /// // let mut x = 1;
2348 /// // x += 1;
2349 /// // println!("{}", x);
2350 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002351 /// struct MiniFunction {
2352 /// attrs: Vec<Attribute>,
2353 /// fn_token: Token![fn],
2354 /// name: Ident,
2355 /// brace_token: token::Brace,
2356 /// stmts: Vec<Stmt>,
2357 /// }
2358 ///
2359 /// impl Parse for MiniFunction {
2360 /// fn parse(input: ParseStream) -> Result<Self> {
2361 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2362 /// let fn_token: Token![fn] = input.parse()?;
2363 /// let name: Ident = input.parse()?;
2364 ///
2365 /// let content;
2366 /// let brace_token = braced!(content in input);
2367 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2368 /// let stmts = content.call(Block::parse_within)?;
2369 ///
2370 /// Ok(MiniFunction {
2371 /// attrs: {
2372 /// let mut attrs = outer_attrs;
2373 /// attrs.extend(inner_attrs);
2374 /// attrs
2375 /// },
2376 /// fn_token: fn_token,
2377 /// name: name,
2378 /// brace_token: brace_token,
2379 /// stmts: stmts,
2380 /// })
2381 /// }
2382 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002383 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002384 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002385 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002386 loop {
2387 while input.peek(Token![;]) {
2388 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002389 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002390 if input.is_empty() {
2391 break;
2392 }
2393 let s = parse_stmt(input, true)?;
2394 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2395 requires_terminator(s)
2396 } else {
2397 false
2398 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002399 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002400 if input.is_empty() {
2401 break;
2402 } else if requires_semicolon {
2403 return Err(input.error("unexpected token"));
2404 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002405 }
2406 Ok(stmts)
2407 }
Alex Crichton954046c2017-05-30 21:49:42 -07002408 }
2409
Michael Layzell734adb42017-06-07 16:58:31 -04002410 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002411 impl Parse for Stmt {
2412 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002413 parse_stmt(input, false)
2414 }
2415 }
David Tolnay939766a2016-09-23 23:48:12 -07002416
David Tolnaye532d6b2018-08-30 16:55:01 -07002417 #[cfg(feature = "full")]
2418 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2419 let ahead = input.fork();
2420 ahead.call(Attribute::parse_outer)?;
2421
David Tolnaye532d6b2018-08-30 16:55:01 -07002422 if {
2423 let ahead = ahead.fork();
2424 // Only parse braces here; paren and bracket will get parsed as
2425 // expression statements
2426 ahead.call(Path::parse_mod_style).is_ok()
2427 && ahead.parse::<Token![!]>().is_ok()
2428 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2429 } {
2430 stmt_mac(input)
2431 } else if ahead.peek(Token![let]) {
2432 stmt_local(input).map(Stmt::Local)
2433 } else if ahead.peek(Token![pub])
2434 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2435 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2436 || ahead.peek(Token![use])
2437 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2438 || ahead.peek(Token![const])
2439 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2440 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2441 || ahead.peek(Token![fn])
2442 || ahead.peek(Token![mod])
2443 || ahead.peek(Token![type])
2444 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2445 || ahead.peek(Token![struct])
2446 || ahead.peek(Token![enum])
2447 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2448 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2449 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002450 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002451 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2452 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002453 || ahead.peek(Token![macro])
2454 {
2455 input.parse().map(Stmt::Item)
2456 } else {
2457 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002458 }
Alex Crichton954046c2017-05-30 21:49:42 -07002459 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002460
Michael Layzell734adb42017-06-07 16:58:31 -04002461 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002462 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2463 let attrs = input.call(Attribute::parse_outer)?;
2464 let path = input.call(Path::parse_mod_style)?;
2465 let bang_token: Token![!] = input.parse()?;
2466 let ident: Option<Ident> = input.parse()?;
2467 let (delimiter, tts) = mac::parse_delimiter(input)?;
2468 let semi_token: Option<Token![;]> = input.parse()?;
2469
2470 Ok(Stmt::Item(Item::Macro(ItemMacro {
2471 attrs: attrs,
2472 ident: ident,
2473 mac: Macro {
2474 path: path,
2475 bang_token: bang_token,
2476 delimiter: delimiter,
2477 tts: tts,
2478 },
2479 semi_token: semi_token,
2480 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002481 }
David Tolnay84aa0752016-10-02 23:01:13 -07002482
Michael Layzell734adb42017-06-07 16:58:31 -04002483 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002484 fn stmt_local(input: ParseStream) -> Result<Local> {
2485 Ok(Local {
2486 attrs: input.call(Attribute::parse_outer)?,
2487 let_token: input.parse()?,
2488 pats: {
2489 let mut pats = Punctuated::new();
2490 let value: Pat = input.parse()?;
2491 pats.push_value(value);
2492 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2493 let punct = input.parse()?;
2494 pats.push_punct(punct);
2495 let value: Pat = input.parse()?;
2496 pats.push_value(value);
2497 }
2498 pats
2499 },
2500 ty: {
2501 if input.peek(Token![:]) {
2502 let colon_token: Token![:] = input.parse()?;
2503 let ty: Type = input.parse()?;
2504 Some((colon_token, Box::new(ty)))
2505 } else {
2506 None
2507 }
2508 },
2509 init: {
2510 if input.peek(Token![=]) {
2511 let eq_token: Token![=] = input.parse()?;
2512 let init: Expr = input.parse()?;
2513 Some((eq_token, Box::new(init)))
2514 } else {
2515 None
2516 }
2517 },
2518 semi_token: input.parse()?,
2519 })
2520 }
2521
2522 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002523 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002524 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002525 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002526
2527 attrs.extend(e.replace_attrs(Vec::new()));
2528 e.replace_attrs(attrs);
2529
2530 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002531 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002532 }
David Tolnay60291082018-08-28 09:54:49 -07002533
David Tolnayf00a2762018-08-30 17:22:22 -07002534 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002535 Ok(Stmt::Expr(e))
2536 } else {
2537 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002538 }
David Tolnay60291082018-08-28 09:54:49 -07002539 }
2540
2541 #[cfg(feature = "full")]
2542 impl Parse for Pat {
2543 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002544 let lookahead = input.lookahead1();
2545 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002546 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002547 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002548 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002549 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2550 pat_lit_or_range(input)
2551 } else if input.peek(Ident)
2552 && ({
2553 input.peek2(Token![::])
2554 || input.peek2(Token![!])
2555 || input.peek2(token::Brace)
2556 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002557 || input.peek2(Token![..])
2558 && !{
2559 let ahead = input.fork();
2560 ahead.parse::<Ident>()?;
2561 ahead.parse::<RangeLimits>()?;
2562 ahead.is_empty() || ahead.peek(Token![,])
2563 }
David Tolnay8d534b02018-09-02 09:46:05 -07002564 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002565 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002566 || input.peek(Token![::])
2567 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002568 || input.peek(Token![Self])
2569 || input.peek(Token![super])
2570 || input.peek(Token![extern])
2571 || input.peek(Token![crate])
2572 {
2573 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002574 } else if input.peek(Token![ref])
2575 || input.peek(Token![mut])
2576 || input.peek(Token![self])
2577 || input.peek(Ident)
2578 {
David Tolnay310b3262018-08-30 15:33:00 -07002579 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002580 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002581 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002582 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002583 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002584 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002585 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002586 } else {
2587 Err(lookahead.error())
2588 }
2589 }
2590 }
2591
2592 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002593 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2594 let (qself, path) = path::parsing::qpath(input, true)?;
2595
2596 if input.peek(Token![..]) {
2597 return pat_range(input, qself, path).map(Pat::Range);
2598 }
2599
2600 if qself.is_some() {
2601 return Ok(Pat::Path(PatPath {
2602 qself: qself,
2603 path: path,
2604 }));
2605 }
2606
2607 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2608 let mut contains_arguments = false;
2609 for segment in &path.segments {
2610 match segment.arguments {
2611 PathArguments::None => {}
2612 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2613 contains_arguments = true;
2614 }
2615 }
2616 }
2617
2618 if !contains_arguments {
2619 let bang_token: Token![!] = input.parse()?;
2620 let (delimiter, tts) = mac::parse_delimiter(input)?;
2621 return Ok(Pat::Macro(PatMacro {
2622 mac: Macro {
2623 path: path,
2624 bang_token: bang_token,
2625 delimiter: delimiter,
2626 tts: tts,
2627 },
2628 }));
2629 }
2630 }
2631
2632 if input.peek(token::Brace) {
2633 pat_struct(input, path).map(Pat::Struct)
2634 } else if input.peek(token::Paren) {
2635 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2636 } else if input.peek(Token![..]) {
2637 pat_range(input, qself, path).map(Pat::Range)
2638 } else {
2639 Ok(Pat::Path(PatPath {
2640 qself: qself,
2641 path: path,
2642 }))
2643 }
2644 }
2645
2646 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002647 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2648 Ok(PatWild {
2649 underscore_token: input.parse()?,
2650 })
Alex Crichton954046c2017-05-30 21:49:42 -07002651 }
2652
Michael Layzell734adb42017-06-07 16:58:31 -04002653 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002654 fn pat_box(input: ParseStream) -> Result<PatBox> {
2655 Ok(PatBox {
2656 box_token: input.parse()?,
2657 pat: input.parse()?,
2658 })
David Tolnay60291082018-08-28 09:54:49 -07002659 }
2660
2661 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002662 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2663 Ok(PatIdent {
2664 by_ref: input.parse()?,
2665 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002666 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002667 subpat: {
2668 if input.peek(Token![@]) {
2669 let at_token: Token![@] = input.parse()?;
2670 let subpat: Pat = input.parse()?;
2671 Some((at_token, Box::new(subpat)))
2672 } else {
2673 None
2674 }
2675 },
2676 })
David Tolnay60291082018-08-28 09:54:49 -07002677 }
2678
2679 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002680 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002681 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002682 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002683 pat: input.call(pat_tuple)?,
2684 })
2685 }
David Tolnay60291082018-08-28 09:54:49 -07002686
David Tolnay310b3262018-08-30 15:33:00 -07002687 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002688 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002689 let content;
2690 let brace_token = braced!(content in input);
2691
2692 let mut fields = Punctuated::new();
2693 while !content.is_empty() && !content.peek(Token![..]) {
2694 let value = content.call(field_pat)?;
2695 fields.push_value(value);
2696 if !content.peek(Token![,]) {
2697 break;
David Tolnay60291082018-08-28 09:54:49 -07002698 }
David Tolnay310b3262018-08-30 15:33:00 -07002699 let punct: Token![,] = content.parse()?;
2700 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002701 }
David Tolnay310b3262018-08-30 15:33:00 -07002702
2703 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2704 Some(content.parse()?)
2705 } else {
2706 None
2707 };
2708
2709 Ok(PatStruct {
2710 path: path,
2711 brace_token: brace_token,
2712 fields: fields,
2713 dot2_token: dot2_token,
2714 })
2715 }
2716
2717 #[cfg(feature = "full")]
2718 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2719 let boxed: Option<Token![box]> = input.parse()?;
2720 let by_ref: Option<Token![ref]> = input.parse()?;
2721 let mutability: Option<Token![mut]> = input.parse()?;
2722 let member: Member = input.parse()?;
2723
2724 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2725 || member.is_unnamed()
2726 {
2727 return Ok(FieldPat {
2728 attrs: Vec::new(),
2729 member: member,
2730 colon_token: input.parse()?,
2731 pat: input.parse()?,
2732 });
2733 }
2734
2735 let ident = match member {
2736 Member::Named(ident) => ident,
2737 Member::Unnamed(_) => unreachable!(),
2738 };
2739
2740 let mut pat = Pat::Ident(PatIdent {
2741 by_ref: by_ref,
2742 mutability: mutability,
2743 ident: ident.clone(),
2744 subpat: None,
2745 });
2746
2747 if let Some(boxed) = boxed {
2748 pat = Pat::Box(PatBox {
2749 pat: Box::new(pat),
2750 box_token: boxed,
2751 });
2752 }
2753
2754 Ok(FieldPat {
2755 member: Member::Named(ident),
2756 pat: Box::new(pat),
2757 attrs: Vec::new(),
2758 colon_token: None,
2759 })
Alex Crichton954046c2017-05-30 21:49:42 -07002760 }
2761
David Tolnay1501f7e2018-08-27 14:21:03 -07002762 impl Parse for Member {
2763 fn parse(input: ParseStream) -> Result<Self> {
2764 if input.peek(Ident) {
2765 input.parse().map(Member::Named)
2766 } else if input.peek(LitInt) {
2767 input.parse().map(Member::Unnamed)
2768 } else {
2769 Err(input.error("expected identifier or integer"))
2770 }
2771 }
David Tolnay85b69a42017-12-27 20:43:10 -05002772 }
2773
Bastien Oriveld29ea392018-10-16 23:50:16 +02002774 #[cfg(feature = "full")]
2775 impl Parse for Arm {
2776 fn parse(input: ParseStream) -> Result<Arm> {
2777 let requires_comma;
2778 Ok(Arm {
2779 attrs: input.call(Attribute::parse_outer)?,
2780 leading_vert: input.parse()?,
2781 pats: {
2782 let mut pats = Punctuated::new();
2783 let value: Pat = input.parse()?;
2784 pats.push_value(value);
2785 loop {
2786 if !input.peek(Token![|]) {
2787 break;
2788 }
2789 let punct = input.parse()?;
2790 pats.push_punct(punct);
2791 let value: Pat = input.parse()?;
2792 pats.push_value(value);
2793 }
2794 pats
2795 },
2796 guard: {
2797 if input.peek(Token![if]) {
2798 let if_token: Token![if] = input.parse()?;
2799 let guard: Expr = input.parse()?;
2800 Some((if_token, Box::new(guard)))
2801 } else {
2802 None
2803 }
2804 },
2805 fat_arrow_token: input.parse()?,
2806 body: {
2807 let body = input.call(expr_early)?;
2808 requires_comma = requires_terminator(&body);
2809 Box::new(body)
2810 },
2811 comma: {
2812 if requires_comma && !input.is_empty() {
2813 Some(input.parse()?)
2814 } else {
2815 input.parse()?
2816 }
2817 },
2818 })
2819 }
2820 }
2821
David Tolnay1501f7e2018-08-27 14:21:03 -07002822 impl Parse for Index {
2823 fn parse(input: ParseStream) -> Result<Self> {
2824 let lit: LitInt = input.parse()?;
2825 if let IntSuffix::None = lit.suffix() {
2826 Ok(Index {
2827 index: lit.value() as u32,
2828 span: lit.span(),
2829 })
2830 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002831 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002832 }
2833 }
David Tolnay85b69a42017-12-27 20:43:10 -05002834 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002835
Michael Layzell734adb42017-06-07 16:58:31 -04002836 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002837 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2838 Ok(PatRange {
2839 lo: Box::new(Expr::Path(ExprPath {
2840 attrs: Vec::new(),
2841 qself: qself,
2842 path: path,
2843 })),
2844 limits: input.parse()?,
2845 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002846 })
Alex Crichton954046c2017-05-30 21:49:42 -07002847 }
David Tolnay9636c052016-10-02 17:11:17 -07002848
Michael Layzell734adb42017-06-07 16:58:31 -04002849 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002850 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2851 let content;
2852 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002853
David Tolnay310b3262018-08-30 15:33:00 -07002854 let mut front = Punctuated::new();
2855 let mut dot2_token = None::<Token![..]>;
2856 let mut comma_token = None::<Token![,]>;
2857 loop {
2858 if content.is_empty() {
2859 break;
David Tolnay60291082018-08-28 09:54:49 -07002860 }
David Tolnay310b3262018-08-30 15:33:00 -07002861 if content.peek(Token![..]) {
2862 dot2_token = Some(content.parse()?);
2863 comma_token = content.parse()?;
2864 break;
David Tolnay60291082018-08-28 09:54:49 -07002865 }
David Tolnay310b3262018-08-30 15:33:00 -07002866 let value: Pat = content.parse()?;
2867 front.push_value(value);
2868 if content.is_empty() {
2869 break;
2870 }
2871 let punct = content.parse()?;
2872 front.push_punct(punct);
2873 }
2874
David Tolnayf5ebc192018-08-30 18:23:46 -07002875 let mut back = Punctuated::new();
2876 while !content.is_empty() {
2877 let value: Pat = content.parse()?;
2878 back.push_value(value);
2879 if content.is_empty() {
2880 break;
2881 }
2882 let punct = content.parse()?;
2883 back.push_punct(punct);
2884 }
David Tolnay310b3262018-08-30 15:33:00 -07002885
2886 Ok(PatTuple {
2887 paren_token: paren_token,
2888 front: front,
2889 dot2_token: dot2_token,
2890 comma_token: comma_token,
2891 back: back,
2892 })
2893 }
2894
2895 #[cfg(feature = "full")]
2896 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2897 Ok(PatRef {
2898 and_token: input.parse()?,
2899 mutability: input.parse()?,
2900 pat: input.parse()?,
2901 })
2902 }
2903
2904 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002905 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2906 let lo = input.call(pat_lit_expr)?;
2907 if input.peek(Token![..]) {
2908 Ok(Pat::Range(PatRange {
2909 lo: lo,
2910 limits: input.parse()?,
2911 hi: input.call(pat_lit_expr)?,
2912 }))
David Tolnay310b3262018-08-30 15:33:00 -07002913 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002914 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002915 }
2916 }
2917
2918 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002919 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2920 let neg: Option<Token![-]> = input.parse()?;
2921
2922 let lookahead = input.lookahead1();
2923 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002924 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002925 } else if lookahead.peek(Ident)
2926 || lookahead.peek(Token![::])
2927 || lookahead.peek(Token![<])
2928 || lookahead.peek(Token![self])
2929 || lookahead.peek(Token![Self])
2930 || lookahead.peek(Token![super])
2931 || lookahead.peek(Token![extern])
2932 || lookahead.peek(Token![crate])
2933 {
2934 Expr::Path(input.parse()?)
2935 } else {
2936 return Err(lookahead.error());
2937 };
2938
2939 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002940 Expr::Unary(ExprUnary {
2941 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002942 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002943 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002944 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002945 } else {
David Tolnay60291082018-08-28 09:54:49 -07002946 expr
2947 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002948 }
David Tolnay323279a2017-12-29 11:26:32 -05002949
2950 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002951 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2952 let content;
2953 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002954
David Tolnay310b3262018-08-30 15:33:00 -07002955 let mut front = Punctuated::new();
2956 let mut middle = None;
2957 loop {
2958 if content.is_empty() || content.peek(Token![..]) {
2959 break;
David Tolnay60291082018-08-28 09:54:49 -07002960 }
David Tolnay310b3262018-08-30 15:33:00 -07002961 let value: Pat = content.parse()?;
2962 if content.peek(Token![..]) {
2963 middle = Some(Box::new(value));
2964 break;
David Tolnay60291082018-08-28 09:54:49 -07002965 }
David Tolnay310b3262018-08-30 15:33:00 -07002966 front.push_value(value);
2967 if content.is_empty() {
2968 break;
2969 }
2970 let punct = content.parse()?;
2971 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002972 }
David Tolnay310b3262018-08-30 15:33:00 -07002973
2974 let dot2_token: Option<Token![..]> = content.parse()?;
2975 let mut comma_token = None::<Token![,]>;
2976 let mut back = Punctuated::new();
2977 if dot2_token.is_some() {
2978 comma_token = content.parse()?;
2979 if comma_token.is_some() {
2980 loop {
2981 if content.is_empty() {
2982 break;
2983 }
2984 let value: Pat = content.parse()?;
2985 back.push_value(value);
2986 if content.is_empty() {
2987 break;
2988 }
2989 let punct = content.parse()?;
2990 back.push_punct(punct);
2991 }
2992 }
2993 }
2994
2995 Ok(PatSlice {
2996 bracket_token: bracket_token,
2997 front: front,
2998 middle: middle,
2999 dot2_token: dot2_token,
3000 comma_token: comma_token,
3001 back: back,
3002 })
David Tolnay60291082018-08-28 09:54:49 -07003003 }
3004
3005 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003006 impl Member {
3007 fn is_named(&self) -> bool {
3008 match *self {
3009 Member::Named(_) => true,
3010 Member::Unnamed(_) => false,
3011 }
3012 }
David Tolnay60291082018-08-28 09:54:49 -07003013
3014 fn is_unnamed(&self) -> bool {
3015 match *self {
3016 Member::Named(_) => false,
3017 Member::Unnamed(_) => true,
3018 }
3019 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003020 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003021}
3022
David Tolnayf4bbbd92016-09-23 14:41:55 -07003023#[cfg(feature = "printing")]
3024mod printing {
3025 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003026
Alex Crichtona74a1c82018-05-16 10:20:44 -07003027 use proc_macro2::{Literal, TokenStream};
3028 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003029
David Tolnay64023912018-08-31 09:51:12 -07003030 #[cfg(feature = "full")]
3031 use attr::FilterAttrs;
3032 #[cfg(feature = "full")]
3033 use print::TokensOrDefault;
3034
David Tolnaybcf26022017-12-25 22:10:52 -05003035 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003036 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003037 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003038 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003039 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003040 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003041 e.to_tokens(tokens);
3042 });
3043 } else {
3044 e.to_tokens(tokens);
3045 }
3046 }
3047
David Tolnay8c91b882017-12-28 23:04:32 -05003048 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003049 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003050 tokens.append_all(attrs.outer());
3051 }
Michael Layzell734adb42017-06-07 16:58:31 -04003052
David Tolnayd997aef2018-07-21 18:42:31 -07003053 #[cfg(feature = "full")]
3054 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3055 tokens.append_all(attrs.inner());
3056 }
3057
David Tolnay8c91b882017-12-28 23:04:32 -05003058 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003059 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3060
3061 #[cfg(not(feature = "full"))]
3062 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003063
Michael Layzell734adb42017-06-07 16:58:31 -04003064 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003065 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003066 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003067 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003068 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003069 self.expr.to_tokens(tokens);
3070 }
3071 }
3072
Michael Layzell734adb42017-06-07 16:58:31 -04003073 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003074 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003075 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003076 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003077 self.place.to_tokens(tokens);
3078 self.arrow_token.to_tokens(tokens);
3079 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003080 }
3081 }
3082
Michael Layzell734adb42017-06-07 16:58:31 -04003083 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003084 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003085 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003086 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003087 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003088 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003089 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003090 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003091 }
3092 }
3093
3094 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003095 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003096 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003097 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003098 self.paren_token.surround(tokens, |tokens| {
3099 self.args.to_tokens(tokens);
3100 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003101 }
3102 }
3103
Michael Layzell734adb42017-06-07 16:58:31 -04003104 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003105 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003106 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003107 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003108 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003109 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003110 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003111 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003112 self.paren_token.surround(tokens, |tokens| {
3113 self.args.to_tokens(tokens);
3114 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003115 }
3116 }
3117
Michael Layzell734adb42017-06-07 16:58:31 -04003118 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003119 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003120 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003121 self.colon2_token.to_tokens(tokens);
3122 self.lt_token.to_tokens(tokens);
3123 self.args.to_tokens(tokens);
3124 self.gt_token.to_tokens(tokens);
3125 }
3126 }
3127
3128 #[cfg(feature = "full")]
3129 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003130 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003131 match *self {
3132 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3133 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3134 }
3135 }
3136 }
3137
3138 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003139 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003140 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003141 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003142 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003143 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003144 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003145 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003146 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003147 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003148 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003149 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003150 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003151 }
3152 }
3153
3154 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003155 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003156 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003157 self.left.to_tokens(tokens);
3158 self.op.to_tokens(tokens);
3159 self.right.to_tokens(tokens);
3160 }
3161 }
3162
3163 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003164 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003165 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003166 self.op.to_tokens(tokens);
3167 self.expr.to_tokens(tokens);
3168 }
3169 }
3170
David Tolnay8c91b882017-12-28 23:04:32 -05003171 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003172 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003173 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003174 self.lit.to_tokens(tokens);
3175 }
3176 }
3177
Alex Crichton62a0a592017-05-22 13:58:53 -07003178 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003179 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003180 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003181 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003182 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003183 self.ty.to_tokens(tokens);
3184 }
3185 }
3186
David Tolnay0cf94f22017-12-28 23:46:26 -05003187 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 impl ToTokens for ExprType {
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);
Alex Crichton62a0a592017-05-22 13:58:53 -07003191 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003192 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003193 self.ty.to_tokens(tokens);
3194 }
3195 }
3196
Michael Layzell734adb42017-06-07 16:58:31 -04003197 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003198 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003199 if let Some((ref else_token, ref else_)) = *else_ {
3200 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003201
3202 // If we are not one of the valid expressions to exist in an else
3203 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003204 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003205 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003206 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003207 }
3208 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003209 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003210 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003211 });
3212 }
3213 }
3214 }
3215 }
3216
3217 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003218 impl ToTokens for ExprLet {
3219 fn to_tokens(&self, tokens: &mut TokenStream) {
3220 outer_attrs_to_tokens(&self.attrs, tokens);
3221 self.let_token.to_tokens(tokens);
3222 self.pats.to_tokens(tokens);
3223 self.eq_token.to_tokens(tokens);
3224 wrap_bare_struct(tokens, &self.expr);
3225 }
3226 }
3227
3228 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003229 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003230 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003231 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003232 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003233 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003234 self.then_branch.to_tokens(tokens);
3235 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003236 }
3237 }
3238
Michael Layzell734adb42017-06-07 16:58:31 -04003239 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003240 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003241 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003242 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003243 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003244 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003245 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003246 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003247 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003248 tokens.append_all(&self.body.stmts);
3249 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003250 }
3251 }
3252
Michael Layzell734adb42017-06-07 16:58:31 -04003253 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003254 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003255 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003256 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003257 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003258 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003259 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003260 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003261 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003262 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003263 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003264 tokens.append_all(&self.body.stmts);
3265 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003266 }
3267 }
3268
Michael Layzell734adb42017-06-07 16:58:31 -04003269 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003270 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003271 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003272 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003273 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003274 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003275 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003276 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003277 tokens.append_all(&self.body.stmts);
3278 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003279 }
3280 }
3281
Michael Layzell734adb42017-06-07 16:58:31 -04003282 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003283 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003284 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003285 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003286 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003287 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003288 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003289 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003290 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003291 arm.to_tokens(tokens);
3292 // Ensure that we have a comma after a non-block arm, except
3293 // for the last one.
3294 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003295 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003296 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003297 }
3298 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003299 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003300 }
3301 }
3302
Michael Layzell734adb42017-06-07 16:58:31 -04003303 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003304 impl ToTokens for ExprAsync {
3305 fn to_tokens(&self, tokens: &mut TokenStream) {
3306 outer_attrs_to_tokens(&self.attrs, tokens);
3307 self.async_token.to_tokens(tokens);
3308 self.capture.to_tokens(tokens);
3309 self.block.to_tokens(tokens);
3310 }
3311 }
3312
3313 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003314 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003315 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003316 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003317 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003318 self.block.to_tokens(tokens);
3319 }
3320 }
3321
Michael Layzell734adb42017-06-07 16:58:31 -04003322 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003323 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003324 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003325 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003326 self.yield_token.to_tokens(tokens);
3327 self.expr.to_tokens(tokens);
3328 }
3329 }
3330
3331 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003332 impl ToTokens for ExprClosure {
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);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003335 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003336 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003337 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003338 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003339 for input in self.inputs.pairs() {
3340 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003341 FnArg::Captured(ArgCaptured {
3342 ref pat,
3343 ty: Type::Infer(_),
3344 ..
3345 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003346 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003347 }
David Tolnay56080682018-01-06 14:01:52 -08003348 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003349 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003350 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003351 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003352 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003353 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003354 self.body.to_tokens(tokens);
3355 }
3356 }
3357
Michael Layzell734adb42017-06-07 16:58:31 -04003358 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003359 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003360 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003361 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003362 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003363 self.block.brace_token.surround(tokens, |tokens| {
3364 inner_attrs_to_tokens(&self.attrs, tokens);
3365 tokens.append_all(&self.block.stmts);
3366 });
Nika Layzell640832a2017-12-04 13:37:09 -05003367 }
3368 }
3369
3370 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003371 impl ToTokens for ExprBlock {
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 Tolnay1d8e9962018-08-24 19:04:20 -04003374 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003375 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003376 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003377 tokens.append_all(&self.block.stmts);
3378 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003379 }
3380 }
3381
Michael Layzell734adb42017-06-07 16:58:31 -04003382 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003383 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003384 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003385 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003386 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003387 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003388 self.right.to_tokens(tokens);
3389 }
3390 }
3391
Michael Layzell734adb42017-06-07 16:58:31 -04003392 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003393 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003394 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003395 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003396 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003397 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003398 self.right.to_tokens(tokens);
3399 }
3400 }
3401
3402 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003403 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003404 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003405 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003406 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003407 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 }
3409 }
3410
David Tolnay85b69a42017-12-27 20:43:10 -05003411 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003412 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003413 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003414 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003415 Member::Unnamed(ref index) => index.to_tokens(tokens),
3416 }
3417 }
3418 }
3419
David Tolnay85b69a42017-12-27 20:43:10 -05003420 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003421 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003422 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3423 lit.set_span(self.span);
3424 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003425 }
3426 }
3427
3428 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003429 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003430 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003431 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003432 self.bracket_token.surround(tokens, |tokens| {
3433 self.index.to_tokens(tokens);
3434 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003435 }
3436 }
3437
Michael Layzell734adb42017-06-07 16:58:31 -04003438 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003439 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003440 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003441 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003442 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003443 match self.limits {
3444 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3445 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3446 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003447 self.to.to_tokens(tokens);
3448 }
3449 }
3450
3451 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003452 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003453 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003454 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003455 }
3456 }
3457
Michael Layzell734adb42017-06-07 16:58:31 -04003458 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003459 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003460 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003461 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003462 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003463 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003464 self.expr.to_tokens(tokens);
3465 }
3466 }
3467
Michael Layzell734adb42017-06-07 16:58:31 -04003468 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003469 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003470 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003471 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003472 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003473 self.label.to_tokens(tokens);
3474 self.expr.to_tokens(tokens);
3475 }
3476 }
3477
Michael Layzell734adb42017-06-07 16:58:31 -04003478 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003479 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003480 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003481 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003482 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003483 self.label.to_tokens(tokens);
3484 }
3485 }
3486
Michael Layzell734adb42017-06-07 16:58:31 -04003487 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003488 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003489 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003490 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003491 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003492 self.expr.to_tokens(tokens);
3493 }
3494 }
3495
Michael Layzell734adb42017-06-07 16:58:31 -04003496 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003497 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003498 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003499 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003500 self.mac.to_tokens(tokens);
3501 }
3502 }
3503
3504 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003505 impl ToTokens for ExprStruct {
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);
Alex Crichton62a0a592017-05-22 13:58:53 -07003508 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003509 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003510 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003511 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003512 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003513 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003514 self.rest.to_tokens(tokens);
3515 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003516 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003517 }
3518 }
3519
Michael Layzell734adb42017-06-07 16:58:31 -04003520 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003521 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003522 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003523 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003524 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003525 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003526 self.expr.to_tokens(tokens);
3527 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003528 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003529 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003530 }
3531 }
3532
David Tolnaye98775f2017-12-28 23:17:00 -05003533 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003534 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003535 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003536 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003537 self.group_token.surround(tokens, |tokens| {
3538 self.expr.to_tokens(tokens);
3539 });
3540 }
3541 }
3542
Alex Crichton62a0a592017-05-22 13:58:53 -07003543 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003544 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003545 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003546 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003547 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003548 self.expr.to_tokens(tokens);
3549 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003550 }
3551 }
3552
Michael Layzell734adb42017-06-07 16:58:31 -04003553 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003554 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003555 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003556 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003557 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003558 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003559 }
3560 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003561
David Tolnay2ae520a2017-12-29 11:19:50 -05003562 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003563 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003564 self.tts.to_tokens(tokens);
3565 }
3566 }
3567
Michael Layzell734adb42017-06-07 16:58:31 -04003568 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003569 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003570 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003571 self.name.to_tokens(tokens);
3572 self.colon_token.to_tokens(tokens);
3573 }
3574 }
3575
3576 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003577 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003578 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003579 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003580 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003581 if let Some(ref colon_token) = self.colon_token {
3582 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003583 self.expr.to_tokens(tokens);
3584 }
David Tolnay055a7042016-10-02 19:23:54 -07003585 }
3586 }
3587
Michael Layzell734adb42017-06-07 16:58:31 -04003588 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003589 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003590 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003591 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003592 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003593 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003594 if let Some((ref if_token, ref guard)) = self.guard {
3595 if_token.to_tokens(tokens);
3596 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003597 }
David Tolnaydfb91432018-03-31 19:19:44 +02003598 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003599 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003600 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003601 }
3602 }
3603
Michael Layzell734adb42017-06-07 16:58:31 -04003604 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003605 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003606 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003607 self.underscore_token.to_tokens(tokens);
3608 }
3609 }
3610
Michael Layzell734adb42017-06-07 16:58:31 -04003611 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003612 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003613 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003614 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003615 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003616 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003617 if let Some((ref at_token, ref subpat)) = self.subpat {
3618 at_token.to_tokens(tokens);
3619 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003620 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003621 }
3622 }
3623
Michael Layzell734adb42017-06-07 16:58:31 -04003624 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003625 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003626 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003627 self.path.to_tokens(tokens);
3628 self.brace_token.surround(tokens, |tokens| {
3629 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003630 // NOTE: We need a comma before the dot2 token if it is present.
3631 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003632 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003633 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003634 self.dot2_token.to_tokens(tokens);
3635 });
3636 }
3637 }
3638
Michael Layzell734adb42017-06-07 16:58:31 -04003639 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003640 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003641 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003642 self.path.to_tokens(tokens);
3643 self.pat.to_tokens(tokens);
3644 }
3645 }
3646
Michael Layzell734adb42017-06-07 16:58:31 -04003647 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003648 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003649 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003650 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003651 }
3652 }
3653
Michael Layzell734adb42017-06-07 16:58:31 -04003654 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003655 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003656 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003657 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003658 self.front.to_tokens(tokens);
3659 if let Some(ref dot2_token) = self.dot2_token {
3660 if !self.front.empty_or_trailing() {
3661 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003662 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003663 }
David Tolnay41871922017-12-29 01:53:45 -05003664 dot2_token.to_tokens(tokens);
3665 self.comma_token.to_tokens(tokens);
3666 if self.comma_token.is_none() && !self.back.is_empty() {
3667 // Ensure there is a comma after the .. token.
3668 <Token![,]>::default().to_tokens(tokens);
3669 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003670 }
David Tolnay41871922017-12-29 01:53:45 -05003671 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 });
3673 }
3674 }
3675
Michael Layzell734adb42017-06-07 16:58:31 -04003676 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003678 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003679 self.box_token.to_tokens(tokens);
3680 self.pat.to_tokens(tokens);
3681 }
3682 }
3683
Michael Layzell734adb42017-06-07 16:58:31 -04003684 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003685 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003686 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003687 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003688 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003689 self.pat.to_tokens(tokens);
3690 }
3691 }
3692
Michael Layzell734adb42017-06-07 16:58:31 -04003693 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003694 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003695 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003696 self.expr.to_tokens(tokens);
3697 }
3698 }
3699
Michael Layzell734adb42017-06-07 16:58:31 -04003700 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003702 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003703 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003704 match self.limits {
3705 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
Jeb Rosen918e8de2019-06-19 18:42:43 -07003706 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003707 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 self.hi.to_tokens(tokens);
3709 }
3710 }
3711
Michael Layzell734adb42017-06-07 16:58:31 -04003712 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003713 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003714 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003715 self.bracket_token.surround(tokens, |tokens| {
3716 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003717
3718 // If we need a comma before the middle or standalone .. token,
3719 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003720 if !self.front.empty_or_trailing()
3721 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003722 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003723 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003724 }
3725
3726 // If we have an identifier, we always need a .. token.
3727 if self.middle.is_some() {
3728 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003729 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003730 } else if self.dot2_token.is_some() {
3731 self.dot2_token.to_tokens(tokens);
3732 }
3733
3734 // Make sure we have a comma before the back half.
3735 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003736 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003737 self.back.to_tokens(tokens);
3738 } else {
3739 self.comma_token.to_tokens(tokens);
3740 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003741 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003742 }
3743 }
3744
Michael Layzell734adb42017-06-07 16:58:31 -04003745 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003746 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003747 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003748 self.mac.to_tokens(tokens);
3749 }
3750 }
3751
3752 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003753 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003754 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003755 self.tts.to_tokens(tokens);
3756 }
3757 }
3758
3759 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003760 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003761 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003762 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003763 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003764 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003765 }
3766 self.pat.to_tokens(tokens);
3767 }
3768 }
3769
Michael Layzell734adb42017-06-07 16:58:31 -04003770 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003771 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003772 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003773 self.brace_token.surround(tokens, |tokens| {
3774 tokens.append_all(&self.stmts);
3775 });
David Tolnay42602292016-10-01 22:25:45 -07003776 }
3777 }
3778
Michael Layzell734adb42017-06-07 16:58:31 -04003779 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003780 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003781 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003782 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003783 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003784 Stmt::Item(ref item) => item.to_tokens(tokens),
3785 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003786 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003787 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003788 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003789 }
David Tolnay42602292016-10-01 22:25:45 -07003790 }
3791 }
3792 }
David Tolnay191e0582016-10-02 18:31:09 -07003793
Michael Layzell734adb42017-06-07 16:58:31 -04003794 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003795 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003796 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003797 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003798 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003799 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003800 if let Some((ref colon_token, ref ty)) = self.ty {
3801 colon_token.to_tokens(tokens);
3802 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003803 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003804 if let Some((ref eq_token, ref init)) = self.init {
3805 eq_token.to_tokens(tokens);
3806 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003807 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003808 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003809 }
3810 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003811}