blob: 85f02e4b2d396306c9666cf57e5e290c2d3746c4 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -070014#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -050015use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
David Tolnay9c119122018-09-01 18:47:02 -070044 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080045 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070058 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
59 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080060 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnay9c119122018-09-01 18:47:02 -0700219 /// A `let` guard: `let Some(x) = opt`.
220 ///
221 /// *This type is available if Syn is built with the `"full"` feature.*
222 pub Let(ExprLet #full {
223 pub attrs: Vec<Attribute>,
224 pub let_token: Token![let],
225 pub pats: Punctuated<Pat, Token![|]>,
226 pub eq_token: Token![=],
227 pub expr: Box<Expr>,
228 }),
229
David Tolnaya454c8f2018-01-07 01:01:10 -0800230 /// An `if` expression with an optional `else` block: `if expr { ... }
231 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 ///
David Tolnay9c119122018-09-01 18:47:02 -0700233 /// The `else` branch expression may only be an `If` or `Block`
234 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800235 ///
236 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400237 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500238 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500239 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700240 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500241 pub then_branch: Block,
242 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500244
David Tolnaya454c8f2018-01-07 01:01:10 -0800245 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800246 ///
247 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400248 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500249 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500250 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800251 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500252 pub cond: Box<Expr>,
253 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700254 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500255
David Tolnaya454c8f2018-01-07 01:01:10 -0800256 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800257 ///
258 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400259 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500260 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500261 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500262 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700263 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500264 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
266 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500268
David Tolnaya454c8f2018-01-07 01:01:10 -0800269 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800270 ///
271 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400272 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500273 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500274 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500275 pub loop_token: Token![loop],
276 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700277 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500278
David Tolnaya454c8f2018-01-07 01:01:10 -0800279 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800280 ///
281 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400282 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500283 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800284 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700285 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500286 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700287 pub arms: Vec<Arm>,
288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900295 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200296 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500297 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800298 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500299 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800300 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500301 pub output: ReturnType,
302 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700303 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500304
David Tolnaya454c8f2018-01-07 01:01:10 -0800305 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800306 ///
307 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500308 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500309 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500310 pub unsafe_token: Token![unsafe],
311 pub block: Block,
312 }),
313
David Tolnaya454c8f2018-01-07 01:01:10 -0800314 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800315 ///
316 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400317 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500318 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400319 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub block: Block,
321 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800324 ///
325 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400326 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500327 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700328 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800329 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500330 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700331 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500332
David Tolnaya454c8f2018-01-07 01:01:10 -0800333 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800334 ///
335 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400336 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500337 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500339 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub right: Box<Expr>,
341 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500342
David Tolnaya454c8f2018-01-07 01:01:10 -0800343 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500344 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700347 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500349 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500351 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnay05658502018-01-07 09:56:37 -0800354 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"derive"` or
357 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700358 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500359 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700360 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500361 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500362 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700363 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500364
David Tolnaya454c8f2018-01-07 01:01:10 -0800365 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400368 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700370 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700371 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500372 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700374
David Tolnaya454c8f2018-01-07 01:01:10 -0800375 /// A path like `std::mem::replace` possibly containing generic
376 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700377 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800379 ///
380 /// *This type is available if Syn is built with the `"derive"` or
381 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700382 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 pub qself: Option<QSelf>,
385 pub path: Path,
386 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700387
David Tolnaya454c8f2018-01-07 01:01:10 -0800388 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800389 ///
390 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200391 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500392 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800393 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500394 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700395 pub expr: Box<Expr>,
396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `break`, with an optional label to break and an optional
399 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400402 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500403 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700405 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700406 pub expr: Option<Box<Expr>>,
407 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400412 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500415 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500417
David Tolnaya454c8f2018-01-07 01:01:10 -0800418 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500421 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800423 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500424 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700425 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700426
David Tolnaya454c8f2018-01-07 01:01:10 -0800427 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800428 ///
429 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500430 pub Macro(ExprMacro #full {
431 pub attrs: Vec<Attribute>,
432 pub mac: Macro,
433 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700434
David Tolnaya454c8f2018-01-07 01:01:10 -0800435 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800437 /// The `rest` provides the value of the remaining fields as in `S { a:
438 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800439 ///
440 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400441 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500442 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700443 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500444 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500445 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500446 pub dot2_token: Option<Token![..]>,
447 pub rest: Option<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 array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800451 ///
452 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400453 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500454 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500455 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700456 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500457 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800458 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700459 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700460
David Tolnaya454c8f2018-01-07 01:01:10 -0800461 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800462 ///
463 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800464 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500465 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500466 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700469
David Tolnaya454c8f2018-01-07 01:01:10 -0800470 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400471 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800472 /// This variant is important for faithfully representing the precedence
473 /// of expressions and is related to `None`-delimited spans in a
474 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800475 ///
476 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500477 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500478 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500479 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500480 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400481 }),
482
David Tolnaya454c8f2018-01-07 01:01:10 -0800483 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800484 ///
485 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400486 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500487 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800489 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700490 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700491
David Tolnay02a9c6f2018-08-24 18:58:45 -0400492 /// An async block: `async { ... }`.
493 ///
494 /// *This type is available if Syn is built with the `"full"` feature.*
495 pub Async(ExprAsync #full {
496 pub attrs: Vec<Attribute>,
497 pub async_token: Token![async],
498 pub capture: Option<Token![move]>,
499 pub block: Block,
500 }),
501
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400502 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800503 ///
504 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400505 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500506 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400507 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700508 pub block: Block,
509 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700510
David Tolnaya454c8f2018-01-07 01:01:10 -0800511 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800512 ///
513 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700514 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500515 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800516 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700517 pub expr: Option<Box<Expr>>,
518 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500519
David Tolnaya454c8f2018-01-07 01:01:10 -0800520 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800521 ///
522 /// *This type is available if Syn is built with the `"derive"` or
523 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500524 pub Verbatim(ExprVerbatim #manual_extra_traits {
525 pub tts: TokenStream,
526 }),
527 }
528}
529
530#[cfg(feature = "extra-traits")]
531impl Eq for ExprVerbatim {}
532
533#[cfg(feature = "extra-traits")]
534impl PartialEq for ExprVerbatim {
535 fn eq(&self, other: &Self) -> bool {
536 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
537 }
538}
539
540#[cfg(feature = "extra-traits")]
541impl Hash for ExprVerbatim {
542 fn hash<H>(&self, state: &mut H)
543 where
544 H: Hasher,
545 {
546 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700547 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700548}
549
David Tolnay8c91b882017-12-28 23:04:32 -0500550impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700551 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700552 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500553 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800554 Expr::Box(ExprBox { ref mut attrs, .. })
555 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
556 | Expr::Array(ExprArray { ref mut attrs, .. })
557 | Expr::Call(ExprCall { ref mut attrs, .. })
558 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
559 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
560 | Expr::Binary(ExprBinary { ref mut attrs, .. })
561 | Expr::Unary(ExprUnary { ref mut attrs, .. })
562 | Expr::Lit(ExprLit { ref mut attrs, .. })
563 | Expr::Cast(ExprCast { ref mut attrs, .. })
564 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700565 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800566 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800567 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800568 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
569 | Expr::Loop(ExprLoop { ref mut attrs, .. })
570 | Expr::Match(ExprMatch { ref mut attrs, .. })
571 | Expr::Closure(ExprClosure { ref mut attrs, .. })
572 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
573 | Expr::Block(ExprBlock { ref mut attrs, .. })
574 | Expr::Assign(ExprAssign { ref mut attrs, .. })
575 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
576 | Expr::Field(ExprField { ref mut attrs, .. })
577 | Expr::Index(ExprIndex { ref mut attrs, .. })
578 | Expr::Range(ExprRange { ref mut attrs, .. })
579 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200580 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800581 | Expr::Break(ExprBreak { ref mut attrs, .. })
582 | Expr::Continue(ExprContinue { ref mut attrs, .. })
583 | Expr::Return(ExprReturn { ref mut attrs, .. })
584 | Expr::Macro(ExprMacro { ref mut attrs, .. })
585 | Expr::Struct(ExprStruct { ref mut attrs, .. })
586 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
587 | Expr::Paren(ExprParen { ref mut attrs, .. })
588 | Expr::Group(ExprGroup { ref mut attrs, .. })
589 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400590 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400591 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800592 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700593 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500594 }
595 }
596}
597
David Tolnay85b69a42017-12-27 20:43:10 -0500598ast_enum! {
599 /// A struct or tuple struct field accessed in a struct literal or field
600 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800601 ///
602 /// *This type is available if Syn is built with the `"derive"` or `"full"`
603 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500604 pub enum Member {
605 /// A named field like `self.x`.
606 Named(Ident),
607 /// An unnamed field like `self.0`.
608 Unnamed(Index),
609 }
610}
611
David Tolnay85b69a42017-12-27 20:43:10 -0500612ast_struct! {
613 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800614 ///
615 /// *This type is available if Syn is built with the `"derive"` or `"full"`
616 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500617 pub struct Index #manual_extra_traits {
618 pub index: u32,
619 pub span: Span,
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623impl From<usize> for Index {
624 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700625 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500626 Index {
627 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700628 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500629 }
630 }
631}
632
633#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500634impl Eq for Index {}
635
David Tolnay14982012017-12-29 00:49:51 -0500636#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500637impl PartialEq for Index {
638 fn eq(&self, other: &Self) -> bool {
639 self.index == other.index
640 }
641}
642
David Tolnay14982012017-12-29 00:49:51 -0500643#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500644impl Hash for Index {
645 fn hash<H: Hasher>(&self, state: &mut H) {
646 self.index.hash(state);
647 }
648}
649
650#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700651ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// The `::<>` explicit type parameters passed to a method call:
653 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800654 ///
655 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500656 pub struct MethodTurbofish {
657 pub colon2_token: Token![::],
658 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500659 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500660 pub gt_token: Token![>],
661 }
662}
663
664#[cfg(feature = "full")]
665ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800666 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800667 ///
668 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500669 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800670 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500671 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800672 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500673 ///
674 /// NOTE: Identity expressions are represented as Type arguments, as
675 /// they are indistinguishable syntactically.
676 Const(Expr),
677 }
678}
679
680#[cfg(feature = "full")]
681ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700682 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800683 ///
684 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700685 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500686 /// Attributes tagged on the field.
687 pub attrs: Vec<Attribute>,
688
689 /// Name or index of the field.
690 pub member: Member,
691
David Tolnay5d7098a2017-12-29 01:35:24 -0500692 /// The colon in `Struct { x: x }`. If written in shorthand like
693 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500694 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500695
Alex Crichton62a0a592017-05-22 13:58:53 -0700696 /// Value of the field.
697 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700698 }
David Tolnay055a7042016-10-02 19:23:54 -0700699}
700
Michael Layzell734adb42017-06-07 16:58:31 -0400701#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700702ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800703 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800704 ///
705 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500706 pub struct Label {
707 pub name: Lifetime,
708 pub colon_token: Token![:],
709 }
710}
711
712#[cfg(feature = "full")]
713ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800714 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800715 ///
716 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700717 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500718 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700719 /// Statements in a block
720 pub stmts: Vec<Stmt>,
721 }
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_enum! {
726 /// A statement, usually ending in a semicolon.
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 enum Stmt {
730 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800731 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700732
Alex Crichton62a0a592017-05-22 13:58:53 -0700733 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800734 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700735
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800737 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700738
David Tolnaya454c8f2018-01-07 01:01:10 -0800739 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800740 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700742}
743
Michael Layzell734adb42017-06-07 16:58:31 -0400744#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700745ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800746 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800747 ///
748 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700749 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500750 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800751 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200752 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500753 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500754 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500755 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700756 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700757}
758
Michael Layzell734adb42017-06-07 16:58:31 -0400759#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700760ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800761 /// A pattern in a local binding, function signature, match expression, or
762 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800763 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800764 /// *This type is available if Syn is built with the `"full"` feature.*
765 ///
David Tolnay614a0142018-01-07 10:25:43 -0800766 /// # Syntax tree enum
767 ///
768 /// This type is a [syntax tree enum].
769 ///
770 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700771 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800772 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800773 ///
774 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700775 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800776 pub underscore_token: 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 pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
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 Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500783 pub by_ref: Option<Token![ref]>,
784 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700785 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500786 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700787 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700788
David Tolnaya454c8f2018-01-07 01:01:10 -0800789 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800790 ///
791 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700792 pub Struct(PatStruct {
793 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500794 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500795 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800796 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700797 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700798
David Tolnaya454c8f2018-01-07 01:01:10 -0800799 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800800 ///
801 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700802 pub TupleStruct(PatTupleStruct {
803 pub path: Path,
804 pub pat: PatTuple,
805 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700806
David Tolnaya454c8f2018-01-07 01:01:10 -0800807 /// A path pattern like `Color::Red`, optionally qualified with a
808 /// self-type.
809 ///
810 /// Unquailfied path patterns can legally refer to variants, structs,
811 /// constants or associated constants. Quailfied path patterns like
812 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
813 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800814 ///
815 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700816 pub Path(PatPath {
817 pub qself: Option<QSelf>,
818 pub path: Path,
819 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700820
David Tolnaya454c8f2018-01-07 01:01:10 -0800821 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800822 ///
823 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700824 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500825 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500826 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500827 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500828 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500829 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700830 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800831
832 /// A box pattern: `box v`.
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 Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800836 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500837 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700838 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800839
840 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800841 ///
842 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700843 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800844 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500845 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500846 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700847 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800848
849 /// A literal pattern: `0`.
850 ///
851 /// This holds an `Expr` rather than a `Lit` because negative numbers
852 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800853 ///
854 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700855 pub Lit(PatLit {
856 pub expr: Box<Expr>,
857 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800858
859 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800860 ///
861 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700862 pub Range(PatRange {
863 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700864 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500865 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700866 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800867
868 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800869 ///
870 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700871 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500872 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500873 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700874 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500875 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500876 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500877 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700878 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800879
880 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800881 ///
882 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500883 pub Macro(PatMacro {
884 pub mac: Macro,
885 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800886
887 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800888 ///
889 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500890 pub Verbatim(PatVerbatim #manual_extra_traits {
891 pub tts: TokenStream,
892 }),
893 }
894}
895
David Tolnayc43b44e2017-12-30 23:55:54 -0500896#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500897impl Eq for PatVerbatim {}
898
David Tolnayc43b44e2017-12-30 23:55:54 -0500899#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500900impl PartialEq for PatVerbatim {
901 fn eq(&self, other: &Self) -> bool {
902 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
903 }
904}
905
David Tolnayc43b44e2017-12-30 23:55:54 -0500906#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500907impl Hash for PatVerbatim {
908 fn hash<H>(&self, state: &mut H)
909 where
910 H: Hasher,
911 {
912 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700913 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700914}
915
Michael Layzell734adb42017-06-07 16:58:31 -0400916#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700917ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800918 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700919 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800920 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700921 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500922 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800923 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500924 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700925 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800926 /// 0...10 => {
927 /// return true;
928 /// }
929 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500930 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700931 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800932 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500933 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700934 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800935 ///
936 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700937 pub struct Arm {
938 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200939 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500940 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500941 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200942 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700943 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800944 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700945 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700946}
947
Michael Layzell734adb42017-06-07 16:58:31 -0400948#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700949ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800951 ///
952 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700953 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700954 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800955 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800956 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800957 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800958 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700959 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700960}
961
Michael Layzell734adb42017-06-07 16:58:31 -0400962#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700963ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800964 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700965 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800966 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
967 /// 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 -0800968 ///
969 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700970 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500971 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500972 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500973 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700974 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700975 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700976}
977
Michael Layzell3936ceb2017-07-08 00:28:36 -0400978#[cfg(any(feature = "parsing", feature = "printing"))]
979#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700980fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700981 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500982 match *expr {
983 Expr::Unsafe(..)
984 | Expr::Block(..)
985 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500986 | Expr::Match(..)
987 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500988 | Expr::Loop(..)
989 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400990 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400991 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700992 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400993 }
994}
995
David Tolnayb9c8e322016-09-23 20:48:37 -0700996#[cfg(feature = "parsing")]
997pub mod parsing {
998 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700999
Michael Layzell734adb42017-06-07 16:58:31 -04001000 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -07001001 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -07001002 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -07001003 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001004
David Tolnaybcf26022017-12-25 22:10:52 -05001005 // When we're parsing expressions which occur before blocks, like in an if
1006 // statement's condition, we cannot parse a struct literal.
1007 //
1008 // Struct literals are ambiguous in certain positions
1009 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001010 #[derive(Copy, Clone)]
1011 pub struct AllowStruct(bool);
1012
David Tolnay01218d12018-08-29 18:13:07 -07001013 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1014 enum Precedence {
1015 Any,
1016 Assign,
1017 Placement,
1018 Range,
1019 Or,
1020 And,
1021 Compare,
1022 BitOr,
1023 BitXor,
1024 BitAnd,
1025 Shift,
1026 Arithmetic,
1027 Term,
1028 Cast,
1029 }
1030
1031 impl Precedence {
1032 fn of(op: &BinOp) -> Self {
1033 match *op {
1034 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1035 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1036 BinOp::And(_) => Precedence::And,
1037 BinOp::Or(_) => Precedence::Or,
1038 BinOp::BitXor(_) => Precedence::BitXor,
1039 BinOp::BitAnd(_) => Precedence::BitAnd,
1040 BinOp::BitOr(_) => Precedence::BitOr,
1041 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001042 BinOp::Eq(_)
1043 | BinOp::Lt(_)
1044 | BinOp::Le(_)
1045 | BinOp::Ne(_)
1046 | BinOp::Ge(_)
1047 | BinOp::Gt(_) => Precedence::Compare,
1048 BinOp::AddEq(_)
1049 | BinOp::SubEq(_)
1050 | BinOp::MulEq(_)
1051 | BinOp::DivEq(_)
1052 | BinOp::RemEq(_)
1053 | BinOp::BitXorEq(_)
1054 | BinOp::BitAndEq(_)
1055 | BinOp::BitOrEq(_)
1056 | BinOp::ShlEq(_)
1057 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001058 }
1059 }
1060 }
1061
David Tolnay9389c382018-08-27 09:13:37 -07001062 impl Parse for Expr {
1063 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001064 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001065 }
1066 }
1067
Michael Layzell734adb42017-06-07 16:58:31 -04001068 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001069 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001070 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001071 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001072
David Tolnay01218d12018-08-29 18:13:07 -07001073 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001074 fn parse_expr(
1075 input: ParseStream,
1076 mut lhs: Expr,
1077 allow_struct: AllowStruct,
1078 base: Precedence,
1079 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001080 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001081 if input
1082 .fork()
1083 .parse::<BinOp>()
1084 .ok()
1085 .map_or(false, |op| Precedence::of(&op) >= base)
1086 {
David Tolnay01218d12018-08-29 18:13:07 -07001087 let op: BinOp = input.parse()?;
1088 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001089 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001090 loop {
1091 let next = peek_precedence(input);
1092 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001093 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001094 } else {
1095 break;
1096 }
1097 }
David Tolnay90276252018-08-31 10:50:08 -07001098 lhs = if precedence == Precedence::Assign {
1099 Expr::AssignOp(ExprAssignOp {
1100 attrs: Vec::new(),
1101 left: Box::new(lhs),
1102 op: op,
1103 right: Box::new(rhs),
1104 })
1105 } else {
1106 Expr::Binary(ExprBinary {
1107 attrs: Vec::new(),
1108 left: Box::new(lhs),
1109 op: op,
1110 right: Box::new(rhs),
1111 })
1112 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001113 } else if Precedence::Assign >= base
1114 && input.peek(Token![=])
1115 && !input.peek(Token![==])
1116 && !input.peek(Token![=>])
1117 {
David Tolnay01218d12018-08-29 18:13:07 -07001118 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001119 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001120 loop {
1121 let next = peek_precedence(input);
1122 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001123 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001124 } else {
1125 break;
1126 }
1127 }
1128 lhs = Expr::Assign(ExprAssign {
1129 attrs: Vec::new(),
1130 left: Box::new(lhs),
1131 eq_token: eq_token,
1132 right: Box::new(rhs),
1133 });
1134 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1135 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001136 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001137 loop {
1138 let next = peek_precedence(input);
1139 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001140 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001141 } else {
1142 break;
1143 }
1144 }
1145 lhs = Expr::InPlace(ExprInPlace {
1146 attrs: Vec::new(),
1147 place: Box::new(lhs),
1148 arrow_token: arrow_token,
1149 value: Box::new(rhs),
1150 });
1151 } else if Precedence::Range >= base && input.peek(Token![..]) {
1152 let limits: RangeLimits = input.parse()?;
1153 let rhs = if input.is_empty()
1154 || input.peek(Token![,])
1155 || input.peek(Token![;])
1156 || !allow_struct.0 && input.peek(token::Brace)
1157 {
1158 None
1159 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001160 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001161 loop {
1162 let next = peek_precedence(input);
1163 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001164 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001165 } else {
1166 break;
1167 }
1168 }
1169 Some(rhs)
1170 };
1171 lhs = Expr::Range(ExprRange {
1172 attrs: Vec::new(),
1173 from: Some(Box::new(lhs)),
1174 limits: limits,
1175 to: rhs.map(Box::new),
1176 });
1177 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1178 let as_token: Token![as] = input.parse()?;
1179 let ty = input.call(Type::without_plus)?;
1180 lhs = Expr::Cast(ExprCast {
1181 attrs: Vec::new(),
1182 expr: Box::new(lhs),
1183 as_token: as_token,
1184 ty: Box::new(ty),
1185 });
1186 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1187 let colon_token: Token![:] = input.parse()?;
1188 let ty = input.call(Type::without_plus)?;
1189 lhs = Expr::Type(ExprType {
1190 attrs: Vec::new(),
1191 expr: Box::new(lhs),
1192 colon_token: colon_token,
1193 ty: Box::new(ty),
1194 });
1195 } else {
1196 break;
1197 }
1198 }
1199 Ok(lhs)
1200 }
1201
David Tolnay3e541292018-08-30 11:42:15 -07001202 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001203 fn parse_expr(
1204 input: ParseStream,
1205 mut lhs: Expr,
1206 allow_struct: AllowStruct,
1207 base: Precedence,
1208 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001209 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001210 if input
1211 .fork()
1212 .parse::<BinOp>()
1213 .ok()
1214 .map_or(false, |op| Precedence::of(&op) >= base)
1215 {
David Tolnay3e541292018-08-30 11:42:15 -07001216 let op: BinOp = input.parse()?;
1217 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001218 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001219 loop {
1220 let next = peek_precedence(input);
1221 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001222 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001223 } else {
1224 break;
1225 }
1226 }
1227 lhs = Expr::Binary(ExprBinary {
1228 attrs: Vec::new(),
1229 left: Box::new(lhs),
1230 op: op,
1231 right: Box::new(rhs),
1232 });
1233 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1234 let as_token: Token![as] = input.parse()?;
1235 let ty = input.call(Type::without_plus)?;
1236 lhs = Expr::Cast(ExprCast {
1237 attrs: Vec::new(),
1238 expr: Box::new(lhs),
1239 as_token: as_token,
1240 ty: Box::new(ty),
1241 });
1242 } else {
1243 break;
1244 }
1245 }
1246 Ok(lhs)
1247 }
1248
David Tolnay01218d12018-08-29 18:13:07 -07001249 fn peek_precedence(input: ParseStream) -> Precedence {
1250 if let Ok(op) = input.fork().parse() {
1251 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001252 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001253 Precedence::Assign
1254 } else if input.peek(Token![<-]) {
1255 Precedence::Placement
1256 } else if input.peek(Token![..]) {
1257 Precedence::Range
1258 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1259 Precedence::Cast
1260 } else {
1261 Precedence::Any
1262 }
1263 }
1264
David Tolnaybcf26022017-12-25 22:10:52 -05001265 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001266 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001267 let lhs = unary_expr(input, allow_struct)?;
1268 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001269 }
1270
David Tolnaybcf26022017-12-25 22:10:52 -05001271 // <UnOp> <trailer>
1272 // & <trailer>
1273 // &mut <trailer>
1274 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001275 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001276 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001277 let ahead = input.fork();
1278 ahead.call(Attribute::parse_outer)?;
1279 if ahead.peek(Token![&])
1280 || ahead.peek(Token![box])
1281 || ahead.peek(Token![*])
1282 || ahead.peek(Token![!])
1283 || ahead.peek(Token![-])
1284 {
1285 let attrs = input.call(Attribute::parse_outer)?;
1286 if input.peek(Token![&]) {
1287 Ok(Expr::Reference(ExprReference {
1288 attrs: attrs,
1289 and_token: input.parse()?,
1290 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001291 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001292 }))
1293 } else if input.peek(Token![box]) {
1294 Ok(Expr::Box(ExprBox {
1295 attrs: attrs,
1296 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001297 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001298 }))
1299 } else {
1300 Ok(Expr::Unary(ExprUnary {
1301 attrs: attrs,
1302 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001303 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001304 }))
1305 }
1306 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001307 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001308 }
1309 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001310
Michael Layzell734adb42017-06-07 16:58:31 -04001311 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001312 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001313 let ahead = input.fork();
1314 ahead.call(Attribute::parse_outer)?;
1315 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1316 Ok(Expr::Unary(ExprUnary {
1317 attrs: input.call(Attribute::parse_outer)?,
1318 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001319 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001320 }))
1321 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001322 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001323 }
1324 }
Michael Layzell734adb42017-06-07 16:58:31 -04001325
David Tolnaybcf26022017-12-25 22:10:52 -05001326 // <atom> (..<args>) ...
1327 // <atom> . <ident> (..<args>) ...
1328 // <atom> . <ident> ...
1329 // <atom> . <lit> ...
1330 // <atom> [ <expr> ] ...
1331 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001332 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001333 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001334 if input.peek(token::Group) {
1335 return input.call(expr_group).map(Expr::Group);
1336 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001337
David Tolnay577fd312018-09-01 02:26:40 -07001338 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001339
David Tolnay577fd312018-09-01 02:26:40 -07001340 let atom = atom_expr(input, allow_struct)?;
1341 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001342
David Tolnay577fd312018-09-01 02:26:40 -07001343 let inner_attrs = e.replace_attrs(Vec::new());
1344 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001345 e.replace_attrs(attrs);
1346 Ok(e)
1347 }
1348
1349 #[cfg(feature = "full")]
1350 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001351 loop {
1352 if input.peek(token::Paren) {
1353 let content;
1354 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001355 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001356 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001357 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001358 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001359 });
1360 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1361 let dot_token: Token![.] = input.parse()?;
1362 let member: Member = input.parse()?;
1363 let turbofish = if member.is_named() && input.peek(Token![::]) {
1364 Some(MethodTurbofish {
1365 colon2_token: input.parse()?,
1366 lt_token: input.parse()?,
1367 args: {
1368 let mut args = Punctuated::new();
1369 loop {
1370 if input.peek(Token![>]) {
1371 break;
1372 }
David Tolnay310b3262018-08-30 15:33:00 -07001373 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001374 args.push_value(value);
1375 if input.peek(Token![>]) {
1376 break;
1377 }
1378 let punct = input.parse()?;
1379 args.push_punct(punct);
1380 }
1381 args
1382 },
1383 gt_token: input.parse()?,
1384 })
1385 } else {
1386 None
1387 };
1388
1389 if turbofish.is_some() || input.peek(token::Paren) {
1390 if let Member::Named(method) = member {
1391 let content;
1392 e = Expr::MethodCall(ExprMethodCall {
1393 attrs: Vec::new(),
1394 receiver: Box::new(e),
1395 dot_token: dot_token,
1396 method: method,
1397 turbofish: turbofish,
1398 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001399 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001400 });
1401 continue;
1402 }
1403 }
1404
1405 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001406 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001407 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001408 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001409 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001410 });
1411 } else if input.peek(token::Bracket) {
1412 let content;
1413 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001414 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001415 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001416 bracket_token: bracketed!(content in input),
1417 index: content.parse()?,
1418 });
1419 } else if input.peek(Token![?]) {
1420 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001421 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001422 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001423 question_token: input.parse()?,
1424 });
1425 } else {
1426 break;
1427 }
1428 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001429 Ok(e)
1430 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001431
Michael Layzell734adb42017-06-07 16:58:31 -04001432 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001433 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001434 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001435
1436 loop {
1437 if input.peek(token::Paren) {
1438 let content;
1439 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001440 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001441 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001442 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001443 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001444 });
1445 } else if input.peek(Token![.]) {
1446 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001447 attrs: Vec::new(),
1448 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001449 dot_token: input.parse()?,
1450 member: input.parse()?,
1451 });
1452 } else if input.peek(token::Bracket) {
1453 let content;
1454 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001455 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001456 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001457 bracket_token: bracketed!(content in input),
1458 index: content.parse()?,
1459 });
1460 } else {
1461 break;
1462 }
1463 }
1464
1465 Ok(e)
1466 }
Michael Layzell734adb42017-06-07 16:58:31 -04001467
David Tolnaya454c8f2018-01-07 01:01:10 -08001468 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001469 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001470 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001471 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001472 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001473 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001474 } else if input.peek(Lit) {
David Tolnay577fd312018-09-01 02:26:40 -07001475 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001476 } else if input.peek(Token![async])
1477 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1478 {
David Tolnay577fd312018-09-01 02:26:40 -07001479 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001481 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001482 } else if input.peek(Token![|])
1483 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1484 || input.peek(Token![static])
1485 || input.peek(Token![move])
1486 {
David Tolnay577fd312018-09-01 02:26:40 -07001487 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001488 } else if input.peek(Ident)
1489 || input.peek(Token![::])
1490 || input.peek(Token![<])
1491 || input.peek(Token![self])
1492 || input.peek(Token![Self])
1493 || input.peek(Token![super])
1494 || input.peek(Token![extern])
1495 || input.peek(Token![crate])
1496 {
David Tolnay577fd312018-09-01 02:26:40 -07001497 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001499 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001501 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001502 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001503 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001504 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001505 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001506 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001507 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001508 } else if input.peek(Token![let]) {
1509 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001510 } else if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001511 input.call(expr_if).map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001512 } else if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001513 input.call(expr_while).map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 } else if input.peek(Token![for]) {
David Tolnay577fd312018-09-01 02:26:40 -07001515 input.call(expr_for_loop).map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001516 } else if input.peek(Token![loop]) {
David Tolnay577fd312018-09-01 02:26:40 -07001517 input.call(expr_loop).map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 } else if input.peek(Token![match]) {
David Tolnay577fd312018-09-01 02:26:40 -07001519 input.call(expr_match).map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001520 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001521 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001522 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001523 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001524 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001525 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001526 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001527 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001528 } else if input.peek(Lifetime) {
1529 let the_label: Label = input.parse()?;
1530 let mut expr = if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001531 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001532 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001533 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001534 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001535 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001536 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001537 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 } else {
1539 return Err(input.error("expected loop or block expression"));
1540 };
1541 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001542 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001543 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1544 | Expr::Loop(ExprLoop { ref mut label, .. })
1545 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001546 _ => unreachable!(),
1547 }
David Tolnay577fd312018-09-01 02:26:40 -07001548 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001549 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001550 Err(input.error("expected expression"))
1551 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001552 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001553
Michael Layzell734adb42017-06-07 16:58:31 -04001554 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001555 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001556 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001557 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001558 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001559 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001560 } else if input.peek(Ident)
1561 || input.peek(Token![::])
1562 || input.peek(Token![<])
1563 || input.peek(Token![self])
1564 || input.peek(Token![Self])
1565 || input.peek(Token![super])
1566 || input.peek(Token![extern])
1567 || input.peek(Token![crate])
1568 {
1569 input.parse().map(Expr::Path)
1570 } else {
1571 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1572 }
1573 }
1574
1575 #[cfg(feature = "full")]
1576 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1577 let expr: ExprPath = input.parse()?;
1578 if expr.qself.is_some() {
1579 return Ok(Expr::Path(expr));
1580 }
1581
1582 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1583 let mut contains_arguments = false;
1584 for segment in &expr.path.segments {
1585 match segment.arguments {
1586 PathArguments::None => {}
1587 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1588 contains_arguments = true;
1589 }
1590 }
1591 }
1592
1593 if !contains_arguments {
1594 let bang_token: Token![!] = input.parse()?;
1595 let (delimiter, tts) = mac::parse_delimiter(input)?;
1596 return Ok(Expr::Macro(ExprMacro {
1597 attrs: Vec::new(),
1598 mac: Macro {
1599 path: expr.path,
1600 bang_token: bang_token,
1601 delimiter: delimiter,
1602 tts: tts,
1603 },
1604 }));
1605 }
1606 }
1607
1608 if allow_struct.0 && input.peek(token::Brace) {
1609 let outer_attrs = Vec::new();
1610 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1611 } else {
1612 Ok(Expr::Path(expr))
1613 }
1614 }
1615
1616 #[cfg(feature = "full")]
1617 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1618 let content;
1619 let paren_token = parenthesized!(content in input);
1620 let inner_attrs = content.call(Attribute::parse_inner)?;
1621 if content.is_empty() {
1622 return Ok(Expr::Tuple(ExprTuple {
1623 attrs: inner_attrs,
1624 paren_token: paren_token,
1625 elems: Punctuated::new(),
1626 }));
1627 }
1628
1629 let first: Expr = content.parse()?;
1630 if content.is_empty() {
1631 return Ok(Expr::Paren(ExprParen {
1632 attrs: inner_attrs,
1633 paren_token: paren_token,
1634 expr: Box::new(first),
1635 }));
1636 }
1637
1638 let mut elems = Punctuated::new();
1639 elems.push_value(first);
1640 while !content.is_empty() {
1641 let punct = content.parse()?;
1642 elems.push_punct(punct);
1643 if content.is_empty() {
1644 break;
1645 }
1646 let value = content.parse()?;
1647 elems.push_value(value);
1648 }
1649 Ok(Expr::Tuple(ExprTuple {
1650 attrs: inner_attrs,
1651 paren_token: paren_token,
1652 elems: elems,
1653 }))
1654 }
1655
1656 #[cfg(feature = "full")]
1657 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1658 let content;
1659 let bracket_token = bracketed!(content in input);
1660 let inner_attrs = content.call(Attribute::parse_inner)?;
1661 if content.is_empty() {
1662 return Ok(Expr::Array(ExprArray {
1663 attrs: inner_attrs,
1664 bracket_token: bracket_token,
1665 elems: Punctuated::new(),
1666 }));
1667 }
1668
1669 let first: Expr = content.parse()?;
1670 if content.is_empty() || content.peek(Token![,]) {
1671 let mut elems = Punctuated::new();
1672 elems.push_value(first);
1673 while !content.is_empty() {
1674 let punct = content.parse()?;
1675 elems.push_punct(punct);
1676 if content.is_empty() {
1677 break;
1678 }
1679 let value = content.parse()?;
1680 elems.push_value(value);
1681 }
1682 Ok(Expr::Array(ExprArray {
1683 attrs: inner_attrs,
1684 bracket_token: bracket_token,
1685 elems: elems,
1686 }))
1687 } else if content.peek(Token![;]) {
1688 let semi_token: Token![;] = content.parse()?;
1689 let len: Expr = content.parse()?;
1690 Ok(Expr::Repeat(ExprRepeat {
1691 attrs: inner_attrs,
1692 bracket_token: bracket_token,
1693 expr: Box::new(first),
1694 semi_token: semi_token,
1695 len: Box::new(len),
1696 }))
1697 } else {
1698 Err(content.error("expected `,` or `;`"))
1699 }
1700 }
Michael Layzell734adb42017-06-07 16:58:31 -04001701
Michael Layzell734adb42017-06-07 16:58:31 -04001702 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001703 fn expr_early(input: ParseStream) -> Result<Expr> {
1704 let mut attrs = input.call(Attribute::parse_outer)?;
1705 let mut expr = if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001706 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001707 } else if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001708 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001709 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001710 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001711 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001712 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001713 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001714 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001715 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001716 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001717 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001718 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001719 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001720 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001721 } else {
1722 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001723 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001724
1725 attrs.extend(expr.replace_attrs(Vec::new()));
1726 expr.replace_attrs(attrs);
1727
David Tolnay7d2e1db2018-08-30 11:49:04 -07001728 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001729 };
1730
1731 if input.peek(Token![.]) || input.peek(Token![?]) {
1732 expr = trailer_helper(input, expr)?;
1733
1734 attrs.extend(expr.replace_attrs(Vec::new()));
1735 expr.replace_attrs(attrs);
1736
1737 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001738 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001739 }
1740
1741 attrs.extend(expr.replace_attrs(Vec::new()));
1742 expr.replace_attrs(attrs);
1743 Ok(expr)
1744 }
Michael Layzell35418782017-06-07 09:20:25 -04001745
David Tolnay310b3262018-08-30 15:33:00 -07001746 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1747 Ok(ExprLit {
1748 attrs: Vec::new(),
1749 lit: input.parse()?,
1750 })
David Tolnay8c91b882017-12-28 23:04:32 -05001751 }
1752
1753 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001754 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001755 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001756 Ok(ExprGroup {
1757 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001758 group_token: group.token,
1759 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001760 })
1761 }
1762
1763 #[cfg(not(feature = "full"))]
1764 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1765 let content;
1766 Ok(ExprParen {
1767 attrs: Vec::new(),
1768 paren_token: parenthesized!(content in input),
1769 expr: content.parse()?,
1770 })
David Tolnay8c91b882017-12-28 23:04:32 -05001771 }
1772
David Tolnaye98775f2017-12-28 23:17:00 -05001773 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001774 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001775 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001776 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001777 }
1778
1779 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001780 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1781 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001782 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001783 let_token: input.parse()?,
1784 pats: {
1785 let mut pats = Punctuated::new();
1786 let value: Pat = input.parse()?;
1787 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001788 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001789 let punct = input.parse()?;
1790 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001791 let value: Pat = input.parse()?;
1792 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001793 }
1794 pats
1795 },
1796 eq_token: input.parse()?,
1797 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001798 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001799 }
1800
Michael Layzell734adb42017-06-07 16:58:31 -04001801 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001802 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1803 Ok(ExprIf {
1804 attrs: Vec::new(),
1805 if_token: input.parse()?,
1806 cond: Box::new(input.call(expr_no_struct)?),
1807 then_branch: input.parse()?,
1808 else_branch: {
1809 if input.peek(Token![else]) {
1810 Some(input.call(else_block)?)
1811 } else {
1812 None
1813 }
1814 },
1815 })
Alex Crichton954046c2017-05-30 21:49:42 -07001816 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001817
Michael Layzell734adb42017-06-07 16:58:31 -04001818 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001819 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1820 let else_token: Token![else] = input.parse()?;
1821
1822 let lookahead = input.lookahead1();
1823 let else_branch = if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001824 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001825 } else if input.peek(token::Brace) {
1826 Expr::Block(ExprBlock {
1827 attrs: Vec::new(),
1828 label: None,
1829 block: input.parse()?,
1830 })
1831 } else {
1832 return Err(lookahead.error());
1833 };
1834
1835 Ok((else_token, Box::new(else_branch)))
1836 }
David Tolnay939766a2016-09-23 23:48:12 -07001837
Michael Layzell734adb42017-06-07 16:58:31 -04001838 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001839 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1840 let label: Option<Label> = input.parse()?;
1841 let for_token: Token![for] = input.parse()?;
1842 let pat: Pat = input.parse()?;
1843 let in_token: Token![in] = input.parse()?;
1844 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001845
David Tolnay310b3262018-08-30 15:33:00 -07001846 let content;
1847 let brace_token = braced!(content in input);
1848 let inner_attrs = content.call(Attribute::parse_inner)?;
1849 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001850
David Tolnay310b3262018-08-30 15:33:00 -07001851 Ok(ExprForLoop {
1852 attrs: inner_attrs,
1853 label: label,
1854 for_token: for_token,
1855 pat: Box::new(pat),
1856 in_token: in_token,
1857 expr: Box::new(expr),
1858 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001859 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001860 stmts: stmts,
1861 },
1862 })
Alex Crichton954046c2017-05-30 21:49:42 -07001863 }
David Tolnay1978c672016-10-27 22:05:52 -07001864
Michael Layzell734adb42017-06-07 16:58:31 -04001865 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001866 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1867 let label: Option<Label> = input.parse()?;
1868 let loop_token: Token![loop] = input.parse()?;
1869
1870 let content;
1871 let brace_token = braced!(content in input);
1872 let inner_attrs = content.call(Attribute::parse_inner)?;
1873 let stmts = content.call(Block::parse_within)?;
1874
1875 Ok(ExprLoop {
1876 attrs: inner_attrs,
1877 label: label,
1878 loop_token: loop_token,
1879 body: Block {
1880 brace_token: brace_token,
1881 stmts: stmts,
1882 },
1883 })
Alex Crichton954046c2017-05-30 21:49:42 -07001884 }
Arnavion02ef13f2017-04-25 00:54:31 -07001885
Michael Layzell734adb42017-06-07 16:58:31 -04001886 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001887 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1888 let match_token: Token![match] = input.parse()?;
1889 let expr = expr_no_struct(input)?;
1890
1891 let content;
1892 let brace_token = braced!(content in input);
1893 let inner_attrs = content.call(Attribute::parse_inner)?;
1894
1895 let mut arms = Vec::new();
1896 while !content.is_empty() {
Bastien Oriveld29ea392018-10-16 23:50:16 +02001897 arms.push(content.call(Arm::parse)?);
David Tolnay310b3262018-08-30 15:33:00 -07001898 }
1899
1900 Ok(ExprMatch {
1901 attrs: inner_attrs,
1902 match_token: match_token,
1903 expr: Box::new(expr),
1904 brace_token: brace_token,
1905 arms: arms,
1906 })
1907 }
1908
1909 #[cfg(feature = "full")]
1910 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1911 Ok(ExprTryBlock {
1912 attrs: Vec::new(),
1913 try_token: input.parse()?,
1914 block: input.parse()?,
1915 })
1916 }
1917
1918 #[cfg(feature = "full")]
1919 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1920 Ok(ExprYield {
1921 attrs: Vec::new(),
1922 yield_token: input.parse()?,
1923 expr: {
1924 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1925 Some(input.parse()?)
1926 } else {
1927 None
1928 }
1929 },
1930 })
1931 }
1932
1933 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001934 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001935 let asyncness: Option<Token![async]> = input.parse()?;
1936 let movability: Option<Token![static]> = if asyncness.is_none() {
1937 input.parse()?
1938 } else {
1939 None
1940 };
1941 let capture: Option<Token![move]> = input.parse()?;
1942 let or1_token: Token![|] = input.parse()?;
1943
1944 let mut inputs = Punctuated::new();
1945 loop {
1946 if input.peek(Token![|]) {
1947 break;
1948 }
1949 let value = fn_arg(input)?;
1950 inputs.push_value(value);
1951 if input.peek(Token![|]) {
1952 break;
1953 }
1954 let punct: Token![,] = input.parse()?;
1955 inputs.push_punct(punct);
1956 }
1957
1958 let or2_token: Token![|] = input.parse()?;
1959
1960 let (output, body) = if input.peek(Token![->]) {
1961 let arrow_token: Token![->] = input.parse()?;
1962 let ty: Type = input.parse()?;
1963 let body: Block = input.parse()?;
1964 let output = ReturnType::Type(arrow_token, Box::new(ty));
1965 let block = Expr::Block(ExprBlock {
1966 attrs: Vec::new(),
1967 label: None,
1968 block: body,
1969 });
1970 (output, block)
1971 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001972 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001973 (ReturnType::Default, body)
1974 };
1975
1976 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07001977 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09001978 asyncness: asyncness,
1979 movability: movability,
1980 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07001981 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09001982 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07001983 or2_token: or2_token,
1984 output: output,
1985 body: Box::new(body),
1986 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04001987 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001988
1989 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001990 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
1991 Ok(ExprAsync {
1992 attrs: Vec::new(),
1993 async_token: input.parse()?,
1994 capture: input.parse()?,
1995 block: input.parse()?,
1996 })
David Tolnay60291082018-08-28 09:54:49 -07001997 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04001998
Michael Layzell734adb42017-06-07 16:58:31 -04001999 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002000 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2001 let pat: Pat = input.parse()?;
2002
2003 if input.peek(Token![:]) {
2004 Ok(FnArg::Captured(ArgCaptured {
2005 pat: pat,
2006 colon_token: input.parse()?,
2007 ty: input.parse()?,
2008 }))
2009 } else {
2010 Ok(FnArg::Inferred(pat))
2011 }
2012 }
2013
2014 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002015 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2016 let label: Option<Label> = input.parse()?;
2017 let while_token: Token![while] = input.parse()?;
2018 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002019
David Tolnay310b3262018-08-30 15:33:00 -07002020 let content;
2021 let brace_token = braced!(content in input);
2022 let inner_attrs = content.call(Attribute::parse_inner)?;
2023 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002024
David Tolnay310b3262018-08-30 15:33:00 -07002025 Ok(ExprWhile {
2026 attrs: inner_attrs,
2027 label: label,
2028 while_token: while_token,
2029 cond: Box::new(cond),
2030 body: Block {
2031 brace_token: brace_token,
2032 stmts: stmts,
2033 },
2034 })
Alex Crichton954046c2017-05-30 21:49:42 -07002035 }
2036
Michael Layzell734adb42017-06-07 16:58:31 -04002037 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002038 impl Parse for Label {
2039 fn parse(input: ParseStream) -> Result<Self> {
2040 Ok(Label {
2041 name: input.parse()?,
2042 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002043 })
David Tolnay60291082018-08-28 09:54:49 -07002044 }
Alex Crichton954046c2017-05-30 21:49:42 -07002045 }
2046
Michael Layzell734adb42017-06-07 16:58:31 -04002047 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002048 impl Parse for Option<Label> {
2049 fn parse(input: ParseStream) -> Result<Self> {
2050 if input.peek(Lifetime) {
2051 input.parse().map(Some)
2052 } else {
2053 Ok(None)
2054 }
2055 }
2056 }
2057
2058 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002059 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2060 Ok(ExprContinue {
2061 attrs: Vec::new(),
2062 continue_token: input.parse()?,
2063 label: input.parse()?,
2064 })
Alex Crichton954046c2017-05-30 21:49:42 -07002065 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002066
Michael Layzell734adb42017-06-07 16:58:31 -04002067 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002068 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2069 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002070 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002071 break_token: input.parse()?,
2072 label: input.parse()?,
2073 expr: {
2074 if input.is_empty()
2075 || input.peek(Token![,])
2076 || input.peek(Token![;])
2077 || !allow_struct.0 && input.peek(token::Brace)
2078 {
2079 None
2080 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002081 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002082 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002083 }
David Tolnay60291082018-08-28 09:54:49 -07002084 },
2085 })
Alex Crichton954046c2017-05-30 21:49:42 -07002086 }
2087
Michael Layzell734adb42017-06-07 16:58:31 -04002088 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002089 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2090 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002091 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002092 return_token: input.parse()?,
2093 expr: {
2094 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2095 None
2096 } else {
2097 // NOTE: return is greedy and eats blocks after it even when in a
2098 // position where structs are not allowed, such as in if statement
2099 // conditions. For example:
2100 //
2101 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002102 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002103 Some(Box::new(expr))
2104 }
2105 },
2106 })
2107 }
2108
2109 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002110 impl Parse for FieldValue {
2111 fn parse(input: ParseStream) -> Result<Self> {
2112 let member: Member = input.parse()?;
2113 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2114 let colon_token: Token![:] = input.parse()?;
2115 let value: Expr = input.parse()?;
2116 (Some(colon_token), value)
2117 } else if let Member::Named(ref ident) = member {
2118 let value = Expr::Path(ExprPath {
2119 attrs: Vec::new(),
2120 qself: None,
2121 path: Path::from(ident.clone()),
2122 });
2123 (None, value)
2124 } else {
2125 unreachable!()
2126 };
2127
2128 Ok(FieldValue {
2129 attrs: Vec::new(),
2130 member: member,
2131 colon_token: colon_token,
2132 expr: value,
2133 })
2134 }
2135 }
2136
2137 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002138 fn expr_struct_helper(
2139 input: ParseStream,
2140 outer_attrs: Vec<Attribute>,
2141 path: Path,
2142 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002143 let content;
2144 let brace_token = braced!(content in input);
2145 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002146
David Tolnay6e1e5052018-08-30 10:21:48 -07002147 let mut fields = Punctuated::new();
2148 loop {
2149 let attrs = content.call(Attribute::parse_outer)?;
2150 if content.fork().parse::<Member>().is_err() {
2151 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002152 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002153 } else {
2154 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002155 }
David Tolnay60291082018-08-28 09:54:49 -07002156 }
2157
David Tolnay6e1e5052018-08-30 10:21:48 -07002158 fields.push(FieldValue {
2159 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002160 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002161 });
2162
2163 if !content.peek(Token![,]) {
2164 break;
2165 }
2166 let punct: Token![,] = content.parse()?;
2167 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002168 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002169
2170 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2171 let dot2_token: Token![..] = content.parse()?;
2172 let rest: Expr = content.parse()?;
2173 (Some(dot2_token), Some(Box::new(rest)))
2174 } else {
2175 (None, None)
2176 };
2177
2178 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002179 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002180 brace_token: brace_token,
2181 path: path,
2182 fields: fields,
2183 dot2_token: dot2_token,
2184 rest: rest,
2185 })
Alex Crichton954046c2017-05-30 21:49:42 -07002186 }
David Tolnay055a7042016-10-02 19:23:54 -07002187
Michael Layzell734adb42017-06-07 16:58:31 -04002188 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002189 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2190 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002191
David Tolnay310b3262018-08-30 15:33:00 -07002192 let content;
2193 let brace_token = braced!(content in input);
2194 let inner_attrs = content.call(Attribute::parse_inner)?;
2195 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002196
David Tolnay310b3262018-08-30 15:33:00 -07002197 Ok(ExprUnsafe {
2198 attrs: inner_attrs,
2199 unsafe_token: unsafe_token,
2200 block: Block {
2201 brace_token: brace_token,
2202 stmts: stmts,
2203 },
2204 })
Alex Crichton954046c2017-05-30 21:49:42 -07002205 }
David Tolnay055a7042016-10-02 19:23:54 -07002206
Michael Layzell734adb42017-06-07 16:58:31 -04002207 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002208 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2209 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002210
David Tolnay310b3262018-08-30 15:33:00 -07002211 let content;
2212 let brace_token = braced!(content in input);
2213 let inner_attrs = content.call(Attribute::parse_inner)?;
2214 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002215
David Tolnay310b3262018-08-30 15:33:00 -07002216 Ok(ExprBlock {
2217 attrs: inner_attrs,
2218 label: label,
2219 block: Block {
2220 brace_token: brace_token,
2221 stmts: stmts,
2222 },
2223 })
Alex Crichton954046c2017-05-30 21:49:42 -07002224 }
David Tolnay89e05672016-10-02 14:39:42 -07002225
Michael Layzell734adb42017-06-07 16:58:31 -04002226 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002227 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2228 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002229 attrs: Vec::new(),
2230 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002231 limits: input.parse()?,
2232 to: {
2233 if input.is_empty()
2234 || input.peek(Token![,])
2235 || input.peek(Token![;])
2236 || !allow_struct.0 && input.peek(token::Brace)
2237 {
2238 None
2239 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002240 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002241 Some(Box::new(to))
2242 }
2243 },
2244 })
2245 }
David Tolnay438c9052016-10-07 23:24:48 -07002246
Michael Layzell734adb42017-06-07 16:58:31 -04002247 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002248 impl Parse for RangeLimits {
2249 fn parse(input: ParseStream) -> Result<Self> {
2250 let lookahead = input.lookahead1();
2251 if lookahead.peek(Token![..=]) {
2252 input.parse().map(RangeLimits::Closed)
2253 } else if lookahead.peek(Token![...]) {
2254 let dot3: Token![...] = input.parse()?;
2255 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2256 } else if lookahead.peek(Token![..]) {
2257 input.parse().map(RangeLimits::HalfOpen)
2258 } else {
2259 Err(lookahead.error())
2260 }
2261 }
Alex Crichton954046c2017-05-30 21:49:42 -07002262 }
David Tolnay438c9052016-10-07 23:24:48 -07002263
David Tolnay60291082018-08-28 09:54:49 -07002264 impl Parse for ExprPath {
2265 fn parse(input: ParseStream) -> Result<Self> {
2266 #[cfg(not(feature = "full"))]
2267 let attrs = Vec::new();
2268 #[cfg(feature = "full")]
2269 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002270
David Tolnay60291082018-08-28 09:54:49 -07002271 let (qself, path) = path::parsing::qpath(input, true)?;
2272
2273 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002274 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002275 qself: qself,
2276 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002277 })
David Tolnay60291082018-08-28 09:54:49 -07002278 }
Alex Crichton954046c2017-05-30 21:49:42 -07002279 }
David Tolnay42602292016-10-01 22:25:45 -07002280
Michael Layzell734adb42017-06-07 16:58:31 -04002281 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002282 impl Parse for Block {
2283 fn parse(input: ParseStream) -> Result<Self> {
2284 let content;
2285 Ok(Block {
2286 brace_token: braced!(content in input),
2287 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002288 })
David Tolnay60291082018-08-28 09:54:49 -07002289 }
Alex Crichton954046c2017-05-30 21:49:42 -07002290 }
David Tolnay939766a2016-09-23 23:48:12 -07002291
Michael Layzell734adb42017-06-07 16:58:31 -04002292 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002293 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002294 /// Parse the body of a block as zero or more statements, possibly
2295 /// including one trailing expression.
2296 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002297 /// *This function is available if Syn is built with the `"parsing"`
2298 /// feature.*
2299 ///
David Tolnay6b457252018-09-01 15:55:47 -07002300 /// # Example
2301 ///
2302 /// ```
David Tolnaya1c98072018-09-06 08:58:10 -07002303 /// #[macro_use]
2304 /// extern crate syn;
2305 ///
David Tolnay67fea042018-11-24 14:50:20 -08002306 /// use syn::{token, Attribute, Block, Ident, Result, Stmt};
2307 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002308 ///
2309 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002310 /// //
2311 /// // fn playground {
2312 /// // let mut x = 1;
2313 /// // x += 1;
2314 /// // println!("{}", x);
2315 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002316 /// struct MiniFunction {
2317 /// attrs: Vec<Attribute>,
2318 /// fn_token: Token![fn],
2319 /// name: Ident,
2320 /// brace_token: token::Brace,
2321 /// stmts: Vec<Stmt>,
2322 /// }
2323 ///
2324 /// impl Parse for MiniFunction {
2325 /// fn parse(input: ParseStream) -> Result<Self> {
2326 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2327 /// let fn_token: Token![fn] = input.parse()?;
2328 /// let name: Ident = input.parse()?;
2329 ///
2330 /// let content;
2331 /// let brace_token = braced!(content in input);
2332 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2333 /// let stmts = content.call(Block::parse_within)?;
2334 ///
2335 /// Ok(MiniFunction {
2336 /// attrs: {
2337 /// let mut attrs = outer_attrs;
2338 /// attrs.extend(inner_attrs);
2339 /// attrs
2340 /// },
2341 /// fn_token: fn_token,
2342 /// name: name,
2343 /// brace_token: brace_token,
2344 /// stmts: stmts,
2345 /// })
2346 /// }
2347 /// }
2348 /// #
2349 /// # fn main() {}
2350 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002351 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002352 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002353 loop {
2354 while input.peek(Token![;]) {
2355 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002356 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002357 if input.is_empty() {
2358 break;
2359 }
2360 let s = parse_stmt(input, true)?;
2361 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2362 requires_terminator(s)
2363 } else {
2364 false
2365 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002366 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002367 if input.is_empty() {
2368 break;
2369 } else if requires_semicolon {
2370 return Err(input.error("unexpected token"));
2371 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002372 }
2373 Ok(stmts)
2374 }
Alex Crichton954046c2017-05-30 21:49:42 -07002375 }
2376
Michael Layzell734adb42017-06-07 16:58:31 -04002377 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002378 impl Parse for Stmt {
2379 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002380 parse_stmt(input, false)
2381 }
2382 }
David Tolnay939766a2016-09-23 23:48:12 -07002383
David Tolnaye532d6b2018-08-30 16:55:01 -07002384 #[cfg(feature = "full")]
2385 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2386 let ahead = input.fork();
2387 ahead.call(Attribute::parse_outer)?;
2388
David Tolnaye532d6b2018-08-30 16:55:01 -07002389 if {
2390 let ahead = ahead.fork();
2391 // Only parse braces here; paren and bracket will get parsed as
2392 // expression statements
2393 ahead.call(Path::parse_mod_style).is_ok()
2394 && ahead.parse::<Token![!]>().is_ok()
2395 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2396 } {
2397 stmt_mac(input)
2398 } else if ahead.peek(Token![let]) {
2399 stmt_local(input).map(Stmt::Local)
2400 } else if ahead.peek(Token![pub])
2401 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2402 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2403 || ahead.peek(Token![use])
2404 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2405 || ahead.peek(Token![const])
2406 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2407 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2408 || ahead.peek(Token![fn])
2409 || ahead.peek(Token![mod])
2410 || ahead.peek(Token![type])
2411 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2412 || ahead.peek(Token![struct])
2413 || ahead.peek(Token![enum])
2414 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2415 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2416 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002417 || ahead.peek(Token![default])
2418 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
2419 || ahead.peek(Token![impl ])
David Tolnaye532d6b2018-08-30 16:55:01 -07002420 || ahead.peek(Token![macro])
2421 {
2422 input.parse().map(Stmt::Item)
2423 } else {
2424 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002425 }
Alex Crichton954046c2017-05-30 21:49:42 -07002426 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002427
Michael Layzell734adb42017-06-07 16:58:31 -04002428 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002429 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2430 let attrs = input.call(Attribute::parse_outer)?;
2431 let path = input.call(Path::parse_mod_style)?;
2432 let bang_token: Token![!] = input.parse()?;
2433 let ident: Option<Ident> = input.parse()?;
2434 let (delimiter, tts) = mac::parse_delimiter(input)?;
2435 let semi_token: Option<Token![;]> = input.parse()?;
2436
2437 Ok(Stmt::Item(Item::Macro(ItemMacro {
2438 attrs: attrs,
2439 ident: ident,
2440 mac: Macro {
2441 path: path,
2442 bang_token: bang_token,
2443 delimiter: delimiter,
2444 tts: tts,
2445 },
2446 semi_token: semi_token,
2447 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002448 }
David Tolnay84aa0752016-10-02 23:01:13 -07002449
Michael Layzell734adb42017-06-07 16:58:31 -04002450 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002451 fn stmt_local(input: ParseStream) -> Result<Local> {
2452 Ok(Local {
2453 attrs: input.call(Attribute::parse_outer)?,
2454 let_token: input.parse()?,
2455 pats: {
2456 let mut pats = Punctuated::new();
2457 let value: Pat = input.parse()?;
2458 pats.push_value(value);
2459 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2460 let punct = input.parse()?;
2461 pats.push_punct(punct);
2462 let value: Pat = input.parse()?;
2463 pats.push_value(value);
2464 }
2465 pats
2466 },
2467 ty: {
2468 if input.peek(Token![:]) {
2469 let colon_token: Token![:] = input.parse()?;
2470 let ty: Type = input.parse()?;
2471 Some((colon_token, Box::new(ty)))
2472 } else {
2473 None
2474 }
2475 },
2476 init: {
2477 if input.peek(Token![=]) {
2478 let eq_token: Token![=] = input.parse()?;
2479 let init: Expr = input.parse()?;
2480 Some((eq_token, Box::new(init)))
2481 } else {
2482 None
2483 }
2484 },
2485 semi_token: input.parse()?,
2486 })
2487 }
2488
2489 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002490 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002491 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002492 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002493
2494 attrs.extend(e.replace_attrs(Vec::new()));
2495 e.replace_attrs(attrs);
2496
2497 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002498 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002499 }
David Tolnay60291082018-08-28 09:54:49 -07002500
David Tolnayf00a2762018-08-30 17:22:22 -07002501 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002502 Ok(Stmt::Expr(e))
2503 } else {
2504 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002505 }
David Tolnay60291082018-08-28 09:54:49 -07002506 }
2507
2508 #[cfg(feature = "full")]
2509 impl Parse for Pat {
2510 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002511 let lookahead = input.lookahead1();
2512 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002513 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002514 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002515 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002516 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2517 pat_lit_or_range(input)
2518 } else if input.peek(Ident)
2519 && ({
2520 input.peek2(Token![::])
2521 || input.peek2(Token![!])
2522 || input.peek2(token::Brace)
2523 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002524 || input.peek2(Token![..])
2525 && !{
2526 let ahead = input.fork();
2527 ahead.parse::<Ident>()?;
2528 ahead.parse::<RangeLimits>()?;
2529 ahead.is_empty() || ahead.peek(Token![,])
2530 }
David Tolnay8d534b02018-09-02 09:46:05 -07002531 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002532 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002533 || input.peek(Token![::])
2534 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002535 || input.peek(Token![Self])
2536 || input.peek(Token![super])
2537 || input.peek(Token![extern])
2538 || input.peek(Token![crate])
2539 {
2540 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002541 } else if input.peek(Token![ref])
2542 || input.peek(Token![mut])
2543 || input.peek(Token![self])
2544 || input.peek(Ident)
2545 {
David Tolnay310b3262018-08-30 15:33:00 -07002546 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002547 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002548 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002549 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002550 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002551 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002552 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002553 } else {
2554 Err(lookahead.error())
2555 }
2556 }
2557 }
2558
2559 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002560 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2561 let (qself, path) = path::parsing::qpath(input, true)?;
2562
2563 if input.peek(Token![..]) {
2564 return pat_range(input, qself, path).map(Pat::Range);
2565 }
2566
2567 if qself.is_some() {
2568 return Ok(Pat::Path(PatPath {
2569 qself: qself,
2570 path: path,
2571 }));
2572 }
2573
2574 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2575 let mut contains_arguments = false;
2576 for segment in &path.segments {
2577 match segment.arguments {
2578 PathArguments::None => {}
2579 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2580 contains_arguments = true;
2581 }
2582 }
2583 }
2584
2585 if !contains_arguments {
2586 let bang_token: Token![!] = input.parse()?;
2587 let (delimiter, tts) = mac::parse_delimiter(input)?;
2588 return Ok(Pat::Macro(PatMacro {
2589 mac: Macro {
2590 path: path,
2591 bang_token: bang_token,
2592 delimiter: delimiter,
2593 tts: tts,
2594 },
2595 }));
2596 }
2597 }
2598
2599 if input.peek(token::Brace) {
2600 pat_struct(input, path).map(Pat::Struct)
2601 } else if input.peek(token::Paren) {
2602 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2603 } else if input.peek(Token![..]) {
2604 pat_range(input, qself, path).map(Pat::Range)
2605 } else {
2606 Ok(Pat::Path(PatPath {
2607 qself: qself,
2608 path: path,
2609 }))
2610 }
2611 }
2612
2613 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002614 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2615 Ok(PatWild {
2616 underscore_token: input.parse()?,
2617 })
Alex Crichton954046c2017-05-30 21:49:42 -07002618 }
2619
Michael Layzell734adb42017-06-07 16:58:31 -04002620 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002621 fn pat_box(input: ParseStream) -> Result<PatBox> {
2622 Ok(PatBox {
2623 box_token: input.parse()?,
2624 pat: input.parse()?,
2625 })
David Tolnay60291082018-08-28 09:54:49 -07002626 }
2627
2628 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002629 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2630 Ok(PatIdent {
2631 by_ref: input.parse()?,
2632 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002633 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002634 subpat: {
2635 if input.peek(Token![@]) {
2636 let at_token: Token![@] = input.parse()?;
2637 let subpat: Pat = input.parse()?;
2638 Some((at_token, Box::new(subpat)))
2639 } else {
2640 None
2641 }
2642 },
2643 })
David Tolnay60291082018-08-28 09:54:49 -07002644 }
2645
2646 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002647 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002648 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002649 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002650 pat: input.call(pat_tuple)?,
2651 })
2652 }
David Tolnay60291082018-08-28 09:54:49 -07002653
David Tolnay310b3262018-08-30 15:33:00 -07002654 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002655 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002656 let content;
2657 let brace_token = braced!(content in input);
2658
2659 let mut fields = Punctuated::new();
2660 while !content.is_empty() && !content.peek(Token![..]) {
2661 let value = content.call(field_pat)?;
2662 fields.push_value(value);
2663 if !content.peek(Token![,]) {
2664 break;
David Tolnay60291082018-08-28 09:54:49 -07002665 }
David Tolnay310b3262018-08-30 15:33:00 -07002666 let punct: Token![,] = content.parse()?;
2667 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002668 }
David Tolnay310b3262018-08-30 15:33:00 -07002669
2670 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2671 Some(content.parse()?)
2672 } else {
2673 None
2674 };
2675
2676 Ok(PatStruct {
2677 path: path,
2678 brace_token: brace_token,
2679 fields: fields,
2680 dot2_token: dot2_token,
2681 })
2682 }
2683
2684 #[cfg(feature = "full")]
2685 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2686 let boxed: Option<Token![box]> = input.parse()?;
2687 let by_ref: Option<Token![ref]> = input.parse()?;
2688 let mutability: Option<Token![mut]> = input.parse()?;
2689 let member: Member = input.parse()?;
2690
2691 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2692 || member.is_unnamed()
2693 {
2694 return Ok(FieldPat {
2695 attrs: Vec::new(),
2696 member: member,
2697 colon_token: input.parse()?,
2698 pat: input.parse()?,
2699 });
2700 }
2701
2702 let ident = match member {
2703 Member::Named(ident) => ident,
2704 Member::Unnamed(_) => unreachable!(),
2705 };
2706
2707 let mut pat = Pat::Ident(PatIdent {
2708 by_ref: by_ref,
2709 mutability: mutability,
2710 ident: ident.clone(),
2711 subpat: None,
2712 });
2713
2714 if let Some(boxed) = boxed {
2715 pat = Pat::Box(PatBox {
2716 pat: Box::new(pat),
2717 box_token: boxed,
2718 });
2719 }
2720
2721 Ok(FieldPat {
2722 member: Member::Named(ident),
2723 pat: Box::new(pat),
2724 attrs: Vec::new(),
2725 colon_token: None,
2726 })
Alex Crichton954046c2017-05-30 21:49:42 -07002727 }
2728
David Tolnay1501f7e2018-08-27 14:21:03 -07002729 impl Parse for Member {
2730 fn parse(input: ParseStream) -> Result<Self> {
2731 if input.peek(Ident) {
2732 input.parse().map(Member::Named)
2733 } else if input.peek(LitInt) {
2734 input.parse().map(Member::Unnamed)
2735 } else {
2736 Err(input.error("expected identifier or integer"))
2737 }
2738 }
David Tolnay85b69a42017-12-27 20:43:10 -05002739 }
2740
Bastien Oriveld29ea392018-10-16 23:50:16 +02002741 #[cfg(feature = "full")]
2742 impl Parse for Arm {
2743 fn parse(input: ParseStream) -> Result<Arm> {
2744 let requires_comma;
2745 Ok(Arm {
2746 attrs: input.call(Attribute::parse_outer)?,
2747 leading_vert: input.parse()?,
2748 pats: {
2749 let mut pats = Punctuated::new();
2750 let value: Pat = input.parse()?;
2751 pats.push_value(value);
2752 loop {
2753 if !input.peek(Token![|]) {
2754 break;
2755 }
2756 let punct = input.parse()?;
2757 pats.push_punct(punct);
2758 let value: Pat = input.parse()?;
2759 pats.push_value(value);
2760 }
2761 pats
2762 },
2763 guard: {
2764 if input.peek(Token![if]) {
2765 let if_token: Token![if] = input.parse()?;
2766 let guard: Expr = input.parse()?;
2767 Some((if_token, Box::new(guard)))
2768 } else {
2769 None
2770 }
2771 },
2772 fat_arrow_token: input.parse()?,
2773 body: {
2774 let body = input.call(expr_early)?;
2775 requires_comma = requires_terminator(&body);
2776 Box::new(body)
2777 },
2778 comma: {
2779 if requires_comma && !input.is_empty() {
2780 Some(input.parse()?)
2781 } else {
2782 input.parse()?
2783 }
2784 },
2785 })
2786 }
2787 }
2788
David Tolnay1501f7e2018-08-27 14:21:03 -07002789 impl Parse for Index {
2790 fn parse(input: ParseStream) -> Result<Self> {
2791 let lit: LitInt = input.parse()?;
2792 if let IntSuffix::None = lit.suffix() {
2793 Ok(Index {
2794 index: lit.value() as u32,
2795 span: lit.span(),
2796 })
2797 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002798 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002799 }
2800 }
David Tolnay85b69a42017-12-27 20:43:10 -05002801 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002802
Michael Layzell734adb42017-06-07 16:58:31 -04002803 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002804 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2805 Ok(PatRange {
2806 lo: Box::new(Expr::Path(ExprPath {
2807 attrs: Vec::new(),
2808 qself: qself,
2809 path: path,
2810 })),
2811 limits: input.parse()?,
2812 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002813 })
Alex Crichton954046c2017-05-30 21:49:42 -07002814 }
David Tolnay9636c052016-10-02 17:11:17 -07002815
Michael Layzell734adb42017-06-07 16:58:31 -04002816 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002817 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2818 let content;
2819 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002820
David Tolnay310b3262018-08-30 15:33:00 -07002821 let mut front = Punctuated::new();
2822 let mut dot2_token = None::<Token![..]>;
2823 let mut comma_token = None::<Token![,]>;
2824 loop {
2825 if content.is_empty() {
2826 break;
David Tolnay60291082018-08-28 09:54:49 -07002827 }
David Tolnay310b3262018-08-30 15:33:00 -07002828 if content.peek(Token![..]) {
2829 dot2_token = Some(content.parse()?);
2830 comma_token = content.parse()?;
2831 break;
David Tolnay60291082018-08-28 09:54:49 -07002832 }
David Tolnay310b3262018-08-30 15:33:00 -07002833 let value: Pat = content.parse()?;
2834 front.push_value(value);
2835 if content.is_empty() {
2836 break;
2837 }
2838 let punct = content.parse()?;
2839 front.push_punct(punct);
2840 }
2841
David Tolnayf5ebc192018-08-30 18:23:46 -07002842 let mut back = Punctuated::new();
2843 while !content.is_empty() {
2844 let value: Pat = content.parse()?;
2845 back.push_value(value);
2846 if content.is_empty() {
2847 break;
2848 }
2849 let punct = content.parse()?;
2850 back.push_punct(punct);
2851 }
David Tolnay310b3262018-08-30 15:33:00 -07002852
2853 Ok(PatTuple {
2854 paren_token: paren_token,
2855 front: front,
2856 dot2_token: dot2_token,
2857 comma_token: comma_token,
2858 back: back,
2859 })
2860 }
2861
2862 #[cfg(feature = "full")]
2863 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2864 Ok(PatRef {
2865 and_token: input.parse()?,
2866 mutability: input.parse()?,
2867 pat: input.parse()?,
2868 })
2869 }
2870
2871 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002872 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2873 let lo = input.call(pat_lit_expr)?;
2874 if input.peek(Token![..]) {
2875 Ok(Pat::Range(PatRange {
2876 lo: lo,
2877 limits: input.parse()?,
2878 hi: input.call(pat_lit_expr)?,
2879 }))
David Tolnay310b3262018-08-30 15:33:00 -07002880 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002881 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002882 }
2883 }
2884
2885 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002886 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2887 let neg: Option<Token![-]> = input.parse()?;
2888
2889 let lookahead = input.lookahead1();
2890 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002891 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002892 } else if lookahead.peek(Ident)
2893 || lookahead.peek(Token![::])
2894 || lookahead.peek(Token![<])
2895 || lookahead.peek(Token![self])
2896 || lookahead.peek(Token![Self])
2897 || lookahead.peek(Token![super])
2898 || lookahead.peek(Token![extern])
2899 || lookahead.peek(Token![crate])
2900 {
2901 Expr::Path(input.parse()?)
2902 } else {
2903 return Err(lookahead.error());
2904 };
2905
2906 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002907 Expr::Unary(ExprUnary {
2908 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002909 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002910 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002911 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002912 } else {
David Tolnay60291082018-08-28 09:54:49 -07002913 expr
2914 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002915 }
David Tolnay323279a2017-12-29 11:26:32 -05002916
2917 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002918 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2919 let content;
2920 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002921
David Tolnay310b3262018-08-30 15:33:00 -07002922 let mut front = Punctuated::new();
2923 let mut middle = None;
2924 loop {
2925 if content.is_empty() || content.peek(Token![..]) {
2926 break;
David Tolnay60291082018-08-28 09:54:49 -07002927 }
David Tolnay310b3262018-08-30 15:33:00 -07002928 let value: Pat = content.parse()?;
2929 if content.peek(Token![..]) {
2930 middle = Some(Box::new(value));
2931 break;
David Tolnay60291082018-08-28 09:54:49 -07002932 }
David Tolnay310b3262018-08-30 15:33:00 -07002933 front.push_value(value);
2934 if content.is_empty() {
2935 break;
2936 }
2937 let punct = content.parse()?;
2938 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002939 }
David Tolnay310b3262018-08-30 15:33:00 -07002940
2941 let dot2_token: Option<Token![..]> = content.parse()?;
2942 let mut comma_token = None::<Token![,]>;
2943 let mut back = Punctuated::new();
2944 if dot2_token.is_some() {
2945 comma_token = content.parse()?;
2946 if comma_token.is_some() {
2947 loop {
2948 if content.is_empty() {
2949 break;
2950 }
2951 let value: Pat = content.parse()?;
2952 back.push_value(value);
2953 if content.is_empty() {
2954 break;
2955 }
2956 let punct = content.parse()?;
2957 back.push_punct(punct);
2958 }
2959 }
2960 }
2961
2962 Ok(PatSlice {
2963 bracket_token: bracket_token,
2964 front: front,
2965 middle: middle,
2966 dot2_token: dot2_token,
2967 comma_token: comma_token,
2968 back: back,
2969 })
David Tolnay60291082018-08-28 09:54:49 -07002970 }
2971
2972 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07002973 impl Member {
2974 fn is_named(&self) -> bool {
2975 match *self {
2976 Member::Named(_) => true,
2977 Member::Unnamed(_) => false,
2978 }
2979 }
David Tolnay60291082018-08-28 09:54:49 -07002980
2981 fn is_unnamed(&self) -> bool {
2982 match *self {
2983 Member::Named(_) => false,
2984 Member::Unnamed(_) => true,
2985 }
2986 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002987 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002988}
2989
David Tolnayf4bbbd92016-09-23 14:41:55 -07002990#[cfg(feature = "printing")]
2991mod printing {
2992 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07002993
Alex Crichtona74a1c82018-05-16 10:20:44 -07002994 use proc_macro2::{Literal, TokenStream};
2995 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07002996
David Tolnay64023912018-08-31 09:51:12 -07002997 #[cfg(feature = "full")]
2998 use attr::FilterAttrs;
2999 #[cfg(feature = "full")]
3000 use print::TokensOrDefault;
3001
David Tolnaybcf26022017-12-25 22:10:52 -05003002 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003003 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003004 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003005 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003006 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003007 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003008 e.to_tokens(tokens);
3009 });
3010 } else {
3011 e.to_tokens(tokens);
3012 }
3013 }
3014
David Tolnay8c91b882017-12-28 23:04:32 -05003015 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003016 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003017 tokens.append_all(attrs.outer());
3018 }
Michael Layzell734adb42017-06-07 16:58:31 -04003019
David Tolnayd997aef2018-07-21 18:42:31 -07003020 #[cfg(feature = "full")]
3021 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3022 tokens.append_all(attrs.inner());
3023 }
3024
David Tolnay8c91b882017-12-28 23:04:32 -05003025 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003026 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3027
3028 #[cfg(not(feature = "full"))]
3029 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003030
Michael Layzell734adb42017-06-07 16:58:31 -04003031 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003032 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003033 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003034 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003035 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003036 self.expr.to_tokens(tokens);
3037 }
3038 }
3039
Michael Layzell734adb42017-06-07 16:58:31 -04003040 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003041 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003042 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003043 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003044 self.place.to_tokens(tokens);
3045 self.arrow_token.to_tokens(tokens);
3046 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003047 }
3048 }
3049
Michael Layzell734adb42017-06-07 16:58:31 -04003050 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003051 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003052 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003053 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003054 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003055 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003056 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003057 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003058 }
3059 }
3060
3061 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003062 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003063 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003064 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003065 self.paren_token.surround(tokens, |tokens| {
3066 self.args.to_tokens(tokens);
3067 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003068 }
3069 }
3070
Michael Layzell734adb42017-06-07 16:58:31 -04003071 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003072 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003073 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003074 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003075 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003076 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003077 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003078 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003079 self.paren_token.surround(tokens, |tokens| {
3080 self.args.to_tokens(tokens);
3081 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003082 }
3083 }
3084
Michael Layzell734adb42017-06-07 16:58:31 -04003085 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003086 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003087 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003088 self.colon2_token.to_tokens(tokens);
3089 self.lt_token.to_tokens(tokens);
3090 self.args.to_tokens(tokens);
3091 self.gt_token.to_tokens(tokens);
3092 }
3093 }
3094
3095 #[cfg(feature = "full")]
3096 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003097 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003098 match *self {
3099 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3100 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3101 }
3102 }
3103 }
3104
3105 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003106 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003107 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003108 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003109 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003110 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003111 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003112 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003113 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003114 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003115 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003116 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003117 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003118 }
3119 }
3120
3121 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003122 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003123 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003124 self.left.to_tokens(tokens);
3125 self.op.to_tokens(tokens);
3126 self.right.to_tokens(tokens);
3127 }
3128 }
3129
3130 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003131 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003132 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003133 self.op.to_tokens(tokens);
3134 self.expr.to_tokens(tokens);
3135 }
3136 }
3137
David Tolnay8c91b882017-12-28 23:04:32 -05003138 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003139 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003140 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003141 self.lit.to_tokens(tokens);
3142 }
3143 }
3144
Alex Crichton62a0a592017-05-22 13:58:53 -07003145 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003146 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003147 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003148 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003149 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003150 self.ty.to_tokens(tokens);
3151 }
3152 }
3153
David Tolnay0cf94f22017-12-28 23:46:26 -05003154 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003155 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003156 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003157 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003158 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003159 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003160 self.ty.to_tokens(tokens);
3161 }
3162 }
3163
Michael Layzell734adb42017-06-07 16:58:31 -04003164 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003165 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003166 if let Some((ref else_token, ref else_)) = *else_ {
3167 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003168
3169 // If we are not one of the valid expressions to exist in an else
3170 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003171 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003172 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003173 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003174 }
3175 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003176 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003177 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003178 });
3179 }
3180 }
3181 }
3182 }
3183
3184 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003185 impl ToTokens for ExprLet {
3186 fn to_tokens(&self, tokens: &mut TokenStream) {
3187 outer_attrs_to_tokens(&self.attrs, tokens);
3188 self.let_token.to_tokens(tokens);
3189 self.pats.to_tokens(tokens);
3190 self.eq_token.to_tokens(tokens);
3191 wrap_bare_struct(tokens, &self.expr);
3192 }
3193 }
3194
3195 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003196 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003197 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003198 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003199 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003200 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003201 self.then_branch.to_tokens(tokens);
3202 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003203 }
3204 }
3205
Michael Layzell734adb42017-06-07 16:58:31 -04003206 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003207 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003208 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003209 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003210 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003211 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003212 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003213 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003214 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003215 tokens.append_all(&self.body.stmts);
3216 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003217 }
3218 }
3219
Michael Layzell734adb42017-06-07 16:58:31 -04003220 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003221 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003222 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003223 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003224 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003225 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003226 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003227 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003228 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003229 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003230 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003231 tokens.append_all(&self.body.stmts);
3232 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003233 }
3234 }
3235
Michael Layzell734adb42017-06-07 16:58:31 -04003236 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003237 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003238 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003239 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003240 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003241 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003242 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003243 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003244 tokens.append_all(&self.body.stmts);
3245 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003246 }
3247 }
3248
Michael Layzell734adb42017-06-07 16:58:31 -04003249 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003250 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003251 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003252 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003253 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003254 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003255 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003256 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003257 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003258 arm.to_tokens(tokens);
3259 // Ensure that we have a comma after a non-block arm, except
3260 // for the last one.
3261 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003262 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003263 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003264 }
3265 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003266 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003267 }
3268 }
3269
Michael Layzell734adb42017-06-07 16:58:31 -04003270 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003271 impl ToTokens for ExprAsync {
3272 fn to_tokens(&self, tokens: &mut TokenStream) {
3273 outer_attrs_to_tokens(&self.attrs, tokens);
3274 self.async_token.to_tokens(tokens);
3275 self.capture.to_tokens(tokens);
3276 self.block.to_tokens(tokens);
3277 }
3278 }
3279
3280 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003281 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003282 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003283 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003284 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003285 self.block.to_tokens(tokens);
3286 }
3287 }
3288
Michael Layzell734adb42017-06-07 16:58:31 -04003289 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003290 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003291 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003292 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003293 self.yield_token.to_tokens(tokens);
3294 self.expr.to_tokens(tokens);
3295 }
3296 }
3297
3298 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003299 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003300 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003301 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003302 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003303 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003304 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003305 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003306 for input in self.inputs.pairs() {
3307 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003308 FnArg::Captured(ArgCaptured {
3309 ref pat,
3310 ty: Type::Infer(_),
3311 ..
3312 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003313 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003314 }
David Tolnay56080682018-01-06 14:01:52 -08003315 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003316 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003317 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003318 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003319 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003320 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003321 self.body.to_tokens(tokens);
3322 }
3323 }
3324
Michael Layzell734adb42017-06-07 16:58:31 -04003325 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003326 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003327 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003328 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003329 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003330 self.block.brace_token.surround(tokens, |tokens| {
3331 inner_attrs_to_tokens(&self.attrs, tokens);
3332 tokens.append_all(&self.block.stmts);
3333 });
Nika Layzell640832a2017-12-04 13:37:09 -05003334 }
3335 }
3336
3337 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003338 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003339 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003340 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003341 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003342 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003343 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003344 tokens.append_all(&self.block.stmts);
3345 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003346 }
3347 }
3348
Michael Layzell734adb42017-06-07 16:58:31 -04003349 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003350 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003351 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003352 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003353 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003354 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003355 self.right.to_tokens(tokens);
3356 }
3357 }
3358
Michael Layzell734adb42017-06-07 16:58:31 -04003359 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003360 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003361 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003362 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003363 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003364 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003365 self.right.to_tokens(tokens);
3366 }
3367 }
3368
3369 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003370 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003371 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003372 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003373 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003374 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003375 }
3376 }
3377
David Tolnay85b69a42017-12-27 20:43:10 -05003378 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003379 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003380 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003381 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003382 Member::Unnamed(ref index) => index.to_tokens(tokens),
3383 }
3384 }
3385 }
3386
David Tolnay85b69a42017-12-27 20:43:10 -05003387 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003388 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003389 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3390 lit.set_span(self.span);
3391 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003392 }
3393 }
3394
3395 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003396 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003397 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003398 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003399 self.bracket_token.surround(tokens, |tokens| {
3400 self.index.to_tokens(tokens);
3401 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003402 }
3403 }
3404
Michael Layzell734adb42017-06-07 16:58:31 -04003405 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003406 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003407 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003408 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003409 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003410 match self.limits {
3411 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3412 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3413 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003414 self.to.to_tokens(tokens);
3415 }
3416 }
3417
3418 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003419 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003420 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003421 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003422 }
3423 }
3424
Michael Layzell734adb42017-06-07 16:58:31 -04003425 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003426 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003427 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003428 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003429 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003430 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003431 self.expr.to_tokens(tokens);
3432 }
3433 }
3434
Michael Layzell734adb42017-06-07 16:58:31 -04003435 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003436 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003437 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003438 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003439 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003440 self.label.to_tokens(tokens);
3441 self.expr.to_tokens(tokens);
3442 }
3443 }
3444
Michael Layzell734adb42017-06-07 16:58:31 -04003445 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003446 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003447 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003448 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003449 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003450 self.label.to_tokens(tokens);
3451 }
3452 }
3453
Michael Layzell734adb42017-06-07 16:58:31 -04003454 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003455 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003456 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003457 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003458 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003459 self.expr.to_tokens(tokens);
3460 }
3461 }
3462
Michael Layzell734adb42017-06-07 16:58:31 -04003463 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003464 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003465 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003466 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003467 self.mac.to_tokens(tokens);
3468 }
3469 }
3470
3471 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003472 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003473 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003474 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003475 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003476 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003477 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003478 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003479 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003480 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003481 self.rest.to_tokens(tokens);
3482 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003483 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003484 }
3485 }
3486
Michael Layzell734adb42017-06-07 16:58:31 -04003487 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003488 impl ToTokens for ExprRepeat {
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.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003492 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003493 self.expr.to_tokens(tokens);
3494 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003495 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003496 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003497 }
3498 }
3499
David Tolnaye98775f2017-12-28 23:17:00 -05003500 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003501 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003502 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003503 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003504 self.group_token.surround(tokens, |tokens| {
3505 self.expr.to_tokens(tokens);
3506 });
3507 }
3508 }
3509
Alex Crichton62a0a592017-05-22 13:58:53 -07003510 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003511 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003512 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003513 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003514 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003515 self.expr.to_tokens(tokens);
3516 });
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 ExprTry {
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 Crichton62a0a592017-05-22 13:58:53 -07003524 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003525 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003526 }
3527 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003528
David Tolnay2ae520a2017-12-29 11:19:50 -05003529 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003530 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003531 self.tts.to_tokens(tokens);
3532 }
3533 }
3534
Michael Layzell734adb42017-06-07 16:58:31 -04003535 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003536 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003537 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003538 self.name.to_tokens(tokens);
3539 self.colon_token.to_tokens(tokens);
3540 }
3541 }
3542
3543 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003544 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003545 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003546 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003547 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003548 if let Some(ref colon_token) = self.colon_token {
3549 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003550 self.expr.to_tokens(tokens);
3551 }
David Tolnay055a7042016-10-02 19:23:54 -07003552 }
3553 }
3554
Michael Layzell734adb42017-06-07 16:58:31 -04003555 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003556 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003557 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003558 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003559 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003560 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003561 if let Some((ref if_token, ref guard)) = self.guard {
3562 if_token.to_tokens(tokens);
3563 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003564 }
David Tolnaydfb91432018-03-31 19:19:44 +02003565 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003566 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003567 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003568 }
3569 }
3570
Michael Layzell734adb42017-06-07 16:58:31 -04003571 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003572 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003573 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003574 self.underscore_token.to_tokens(tokens);
3575 }
3576 }
3577
Michael Layzell734adb42017-06-07 16:58:31 -04003578 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003579 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003580 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003581 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003582 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003583 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003584 if let Some((ref at_token, ref subpat)) = self.subpat {
3585 at_token.to_tokens(tokens);
3586 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003587 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003588 }
3589 }
3590
Michael Layzell734adb42017-06-07 16:58:31 -04003591 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003592 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003593 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003594 self.path.to_tokens(tokens);
3595 self.brace_token.surround(tokens, |tokens| {
3596 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003597 // NOTE: We need a comma before the dot2 token if it is present.
3598 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003599 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003600 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003601 self.dot2_token.to_tokens(tokens);
3602 });
3603 }
3604 }
3605
Michael Layzell734adb42017-06-07 16:58:31 -04003606 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003607 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003608 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003609 self.path.to_tokens(tokens);
3610 self.pat.to_tokens(tokens);
3611 }
3612 }
3613
Michael Layzell734adb42017-06-07 16:58:31 -04003614 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003615 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003616 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003617 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003618 }
3619 }
3620
Michael Layzell734adb42017-06-07 16:58:31 -04003621 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003622 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003623 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003625 self.front.to_tokens(tokens);
3626 if let Some(ref dot2_token) = self.dot2_token {
3627 if !self.front.empty_or_trailing() {
3628 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003629 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003630 }
David Tolnay41871922017-12-29 01:53:45 -05003631 dot2_token.to_tokens(tokens);
3632 self.comma_token.to_tokens(tokens);
3633 if self.comma_token.is_none() && !self.back.is_empty() {
3634 // Ensure there is a comma after the .. token.
3635 <Token![,]>::default().to_tokens(tokens);
3636 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003637 }
David Tolnay41871922017-12-29 01:53:45 -05003638 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003639 });
3640 }
3641 }
3642
Michael Layzell734adb42017-06-07 16:58:31 -04003643 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003644 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003645 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003646 self.box_token.to_tokens(tokens);
3647 self.pat.to_tokens(tokens);
3648 }
3649 }
3650
Michael Layzell734adb42017-06-07 16:58:31 -04003651 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003652 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003653 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003654 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003655 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003656 self.pat.to_tokens(tokens);
3657 }
3658 }
3659
Michael Layzell734adb42017-06-07 16:58:31 -04003660 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003661 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003662 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003663 self.expr.to_tokens(tokens);
3664 }
3665 }
3666
Michael Layzell734adb42017-06-07 16:58:31 -04003667 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003668 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003669 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003670 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003671 match self.limits {
3672 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003673 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003674 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003675 self.hi.to_tokens(tokens);
3676 }
3677 }
3678
Michael Layzell734adb42017-06-07 16:58:31 -04003679 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003680 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003681 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 self.bracket_token.surround(tokens, |tokens| {
3683 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003684
3685 // If we need a comma before the middle or standalone .. token,
3686 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003687 if !self.front.empty_or_trailing()
3688 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003689 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003690 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003691 }
3692
3693 // If we have an identifier, we always need a .. token.
3694 if self.middle.is_some() {
3695 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003696 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003697 } else if self.dot2_token.is_some() {
3698 self.dot2_token.to_tokens(tokens);
3699 }
3700
3701 // Make sure we have a comma before the back half.
3702 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003703 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003704 self.back.to_tokens(tokens);
3705 } else {
3706 self.comma_token.to_tokens(tokens);
3707 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003709 }
3710 }
3711
Michael Layzell734adb42017-06-07 16:58:31 -04003712 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003713 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003714 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003715 self.mac.to_tokens(tokens);
3716 }
3717 }
3718
3719 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003720 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003721 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003722 self.tts.to_tokens(tokens);
3723 }
3724 }
3725
3726 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003727 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003728 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003729 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003730 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003731 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003732 }
3733 self.pat.to_tokens(tokens);
3734 }
3735 }
3736
Michael Layzell734adb42017-06-07 16:58:31 -04003737 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003738 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003739 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003740 self.brace_token.surround(tokens, |tokens| {
3741 tokens.append_all(&self.stmts);
3742 });
David Tolnay42602292016-10-01 22:25:45 -07003743 }
3744 }
3745
Michael Layzell734adb42017-06-07 16:58:31 -04003746 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003747 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003748 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003749 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003750 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003751 Stmt::Item(ref item) => item.to_tokens(tokens),
3752 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003753 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003754 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003755 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003756 }
David Tolnay42602292016-10-01 22:25:45 -07003757 }
3758 }
3759 }
David Tolnay191e0582016-10-02 18:31:09 -07003760
Michael Layzell734adb42017-06-07 16:58:31 -04003761 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003762 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003763 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003764 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003765 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003766 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003767 if let Some((ref colon_token, ref ty)) = self.ty {
3768 colon_token.to_tokens(tokens);
3769 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003770 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003771 if let Some((ref eq_token, ref init)) = self.init {
3772 eq_token.to_tokens(tokens);
3773 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003774 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003775 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003776 }
3777 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003778}