blob: 4af717579820112c9d9c6ab305aec19a2e24e2d6 [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -07002use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -07003use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -05004#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -05005use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -07006#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -05007use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -07008#[cfg(feature = "extra-traits")]
9use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070010
Alex Crichton62a0a592017-05-22 13:58:53 -070011ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080012 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080013 ///
David Tolnay461d98e2018-01-07 11:07:19 -080014 /// *This type is available if Syn is built with the `"derive"` or `"full"`
15 /// feature.*
16 ///
David Tolnay614a0142018-01-07 10:25:43 -080017 /// # Syntax tree enums
18 ///
19 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
20 /// are designed to be traversed using the following rebinding idiom.
21 ///
David Tolnay95989db2019-01-01 15:05:57 -050022 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080023 /// # use syn::Expr;
24 /// #
25 /// # fn example(expr: Expr) {
26 /// # const IGNORE: &str = stringify! {
27 /// let expr: Expr = /* ... */;
28 /// # };
29 /// match expr {
30 /// Expr::MethodCall(expr) => {
31 /// /* ... */
32 /// }
33 /// Expr::Cast(expr) => {
34 /// /* ... */
35 /// }
David Tolnay9c119122018-09-01 18:47:02 -070036 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080037 /// /* ... */
38 /// }
David Tolnay65336072019-04-22 23:10:52 -070039 ///
David Tolnay614a0142018-01-07 10:25:43 -080040 /// /* ... */
41 /// # _ => {}
David Tolnay65336072019-04-22 23:10:52 -070042 /// # }
David Tolnay614a0142018-01-07 10:25:43 -080043 /// # }
44 /// ```
45 ///
46 /// We begin with a variable `expr` of type `Expr` that has no fields
47 /// (because it is an enum), and by matching on it and rebinding a variable
48 /// with the same name `expr` we effectively imbue our variable with all of
49 /// the data fields provided by the variant that it turned out to be. So for
50 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070051 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
52 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080053 ///
David Tolnay614a0142018-01-07 10:25:43 -080054 /// This approach avoids repeating the variant names twice on every line.
55 ///
David Tolnay95989db2019-01-01 15:05:57 -050056 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080057 /// # use syn::{Expr, ExprMethodCall};
58 /// #
59 /// # fn example(expr: Expr) {
David Tolnay65336072019-04-22 23:10:52 -070060 /// // Repetitive; recommend not doing this.
61 /// match expr {
62 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
David Tolnay614a0142018-01-07 10:25:43 -080063 /// # }
64 /// # _ => {}
65 /// # }
66 /// # }
67 /// ```
68 ///
69 /// In general, the name to which a syntax tree enum variant is bound should
70 /// be a suitable name for the complete syntax tree enum type.
71 ///
David Tolnay95989db2019-01-01 15:05:57 -050072 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080073 /// # use syn::{Expr, ExprField};
74 /// #
David Tolnay65336072019-04-22 23:10:52 -070075 /// # fn example(discriminant: ExprField) {
David Tolnay614a0142018-01-07 10:25:43 -080076 /// // Binding is called `base` which is the name I would use if I were
77 /// // assigning `*discriminant.base` without an `if let`.
David Tolnay65336072019-04-22 23:10:52 -070078 /// if let Expr::Tuple(base) = *discriminant.base {
David Tolnay614a0142018-01-07 10:25:43 -080079 /// # }
80 /// # }
81 /// ```
82 ///
83 /// A sign that you may not be choosing the right variable names is if you
84 /// see names getting repeated in your code, like accessing
85 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -050086 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -080087 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -080088 ///
89 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040090 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -050091 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080092 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -050093 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -070094 }),
Clar Charrd22b5702017-03-10 15:24:56 -050095
David Tolnaya454c8f2018-01-07 01:01:10 -080096 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -080097 ///
98 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040099 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500100 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700101 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500102 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700103 pub value: Box<Expr>,
104 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500105
David Tolnaya454c8f2018-01-07 01:01:10 -0800106 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800107 ///
108 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400109 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500110 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500111 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500112 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500114
David Tolnaya454c8f2018-01-07 01:01:10 -0800115 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800116 ///
117 /// *This type is available if Syn is built with the `"derive"` or
118 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700119 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500122 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500123 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500131 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800132 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500133 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500134 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500135 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500136 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700137 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500138
David Tolnaya454c8f2018-01-07 01:01:10 -0800139 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800140 ///
141 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500142 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500143 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500144 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500145 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700146 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500147
David Tolnaya454c8f2018-01-07 01:01:10 -0800148 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700152 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500153 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700154 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700156 pub right: Box<Expr>,
157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"derive"` or
162 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700163 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500164 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700165 pub op: UnOp,
166 pub expr: Box<Expr>,
167 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500168
David Tolnaya454c8f2018-01-07 01:01:10 -0800169 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800170 ///
171 /// *This type is available if Syn is built with the `"derive"` or
172 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub Lit(ExprLit {
174 pub attrs: Vec<Attribute>,
175 pub lit: Lit,
176 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500177
David Tolnaya454c8f2018-01-07 01:01:10 -0800178 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800179 ///
180 /// *This type is available if Syn is built with the `"derive"` or
181 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700182 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500183 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700184 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800185 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800186 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500192 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800195 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800196 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500198
David Tolnay9c119122018-09-01 18:47:02 -0700199 /// A `let` guard: `let Some(x) = opt`.
200 ///
201 /// *This type is available if Syn is built with the `"full"` feature.*
202 pub Let(ExprLet #full {
203 pub attrs: Vec<Attribute>,
204 pub let_token: Token![let],
205 pub pats: Punctuated<Pat, Token![|]>,
206 pub eq_token: Token![=],
207 pub expr: Box<Expr>,
208 }),
209
David Tolnaya454c8f2018-01-07 01:01:10 -0800210 /// An `if` expression with an optional `else` block: `if expr { ... }
211 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700212 ///
David Tolnay9c119122018-09-01 18:47:02 -0700213 /// The `else` branch expression may only be an `If` or `Block`
214 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800215 ///
216 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400217 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500218 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500219 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700220 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500221 pub then_branch: Block,
222 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700223 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500224
David Tolnaya454c8f2018-01-07 01:01:10 -0800225 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800226 ///
227 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400228 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500229 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500230 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800231 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500232 pub cond: Box<Expr>,
233 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700234 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500235
David Tolnaya454c8f2018-01-07 01:01:10 -0800236 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800237 ///
238 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400239 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500240 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500241 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500242 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500244 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700245 pub expr: Box<Expr>,
246 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700247 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500248
David Tolnaya454c8f2018-01-07 01:01:10 -0800249 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800250 ///
251 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400252 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500253 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500254 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500255 pub loop_token: Token![loop],
256 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700257 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500258
David Tolnaya454c8f2018-01-07 01:01:10 -0800259 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800260 ///
261 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400262 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500263 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800264 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500266 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 pub arms: Vec<Arm>,
268 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500269
David Tolnaya454c8f2018-01-07 01:01:10 -0800270 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800271 ///
272 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400273 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500274 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900275 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200276 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500277 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800278 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500279 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800280 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500281 pub output: ReturnType,
282 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700283 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500284
David Tolnaya454c8f2018-01-07 01:01:10 -0800285 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800286 ///
287 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500288 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500289 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500290 pub unsafe_token: Token![unsafe],
291 pub block: Block,
292 }),
293
David Tolnaya454c8f2018-01-07 01:01:10 -0800294 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800295 ///
296 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400297 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500298 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400299 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700300 pub block: Block,
301 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700302
David Tolnaya454c8f2018-01-07 01:01:10 -0800303 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800304 ///
305 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400306 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500307 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500310 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700311 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500312
David Tolnaya454c8f2018-01-07 01:01:10 -0800313 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800314 ///
315 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400316 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500317 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700318 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500319 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub right: Box<Expr>,
321 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500324 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800325 ///
326 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700327 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500328 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500329 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800330 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500331 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500333
David Tolnay05658502018-01-07 09:56:37 -0800334 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800335 ///
336 /// *This type is available if Syn is built with the `"derive"` or
337 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500341 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500342 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700343 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500344
David Tolnaya454c8f2018-01-07 01:01:10 -0800345 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800346 ///
347 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400348 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500349 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700350 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700351 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500352 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700353 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700354
David Tolnaya454c8f2018-01-07 01:01:10 -0800355 /// A path like `std::mem::replace` possibly containing generic
356 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700357 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800358 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800359 ///
360 /// *This type is available if Syn is built with the `"derive"` or
361 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700362 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500363 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700364 pub qself: Option<QSelf>,
365 pub path: Path,
366 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700367
David Tolnaya454c8f2018-01-07 01:01:10 -0800368 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800369 ///
370 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200371 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500372 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800373 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500374 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700375 pub expr: Box<Expr>,
376 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500377
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A `break`, with an optional label to break and an optional
379 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800380 ///
381 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400382 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500384 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700385 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700386 pub expr: Option<Box<Expr>>,
387 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500388
David Tolnaya454c8f2018-01-07 01:01:10 -0800389 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800390 ///
391 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400392 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500393 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800394 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500395 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500401 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500402 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800403 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700406
David Tolnaya454c8f2018-01-07 01:01:10 -0800407 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800408 ///
409 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500410 pub Macro(ExprMacro #full {
411 pub attrs: Vec<Attribute>,
412 pub mac: Macro,
413 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700414
David Tolnaya454c8f2018-01-07 01:01:10 -0800415 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800417 /// The `rest` provides the value of the remaining fields as in `S { a:
418 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400421 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700423 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500424 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500425 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500426 pub dot2_token: Option<Token![..]>,
427 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700428 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500435 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500437 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800438 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700439 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700440
David Tolnaya454c8f2018-01-07 01:01:10 -0800441 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800442 ///
443 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800444 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500445 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500446 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500447 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700449
David Tolnaya454c8f2018-01-07 01:01:10 -0800450 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400451 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800452 /// This variant is important for faithfully representing the precedence
453 /// of expressions and is related to `None`-delimited spans in a
454 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800455 ///
456 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500457 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500458 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500459 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500460 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400461 }),
462
David Tolnaya454c8f2018-01-07 01:01:10 -0800463 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800464 ///
465 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400466 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500467 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800469 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700471
David Tolnay02a9c6f2018-08-24 18:58:45 -0400472 /// An async block: `async { ... }`.
473 ///
474 /// *This type is available if Syn is built with the `"full"` feature.*
475 pub Async(ExprAsync #full {
476 pub attrs: Vec<Attribute>,
477 pub async_token: Token![async],
478 pub capture: Option<Token![move]>,
479 pub block: Block,
480 }),
481
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400482 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400485 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400487 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub block: Block,
489 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800492 ///
493 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700494 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500495 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800496 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700497 pub expr: Option<Box<Expr>>,
498 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500499
David Tolnaya454c8f2018-01-07 01:01:10 -0800500 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800501 ///
502 /// *This type is available if Syn is built with the `"derive"` or
503 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500504 pub Verbatim(ExprVerbatim #manual_extra_traits {
505 pub tts: TokenStream,
506 }),
507 }
508}
509
510#[cfg(feature = "extra-traits")]
511impl Eq for ExprVerbatim {}
512
513#[cfg(feature = "extra-traits")]
514impl PartialEq for ExprVerbatim {
515 fn eq(&self, other: &Self) -> bool {
516 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
517 }
518}
519
520#[cfg(feature = "extra-traits")]
521impl Hash for ExprVerbatim {
522 fn hash<H>(&self, state: &mut H)
523 where
524 H: Hasher,
525 {
526 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700527 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700528}
529
David Tolnay8c91b882017-12-28 23:04:32 -0500530impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700531 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700532 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500533 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800534 Expr::Box(ExprBox { ref mut attrs, .. })
535 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
536 | Expr::Array(ExprArray { ref mut attrs, .. })
537 | Expr::Call(ExprCall { ref mut attrs, .. })
538 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
539 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
540 | Expr::Binary(ExprBinary { ref mut attrs, .. })
541 | Expr::Unary(ExprUnary { ref mut attrs, .. })
542 | Expr::Lit(ExprLit { ref mut attrs, .. })
543 | Expr::Cast(ExprCast { ref mut attrs, .. })
544 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700545 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800546 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800547 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800548 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
549 | Expr::Loop(ExprLoop { ref mut attrs, .. })
550 | Expr::Match(ExprMatch { ref mut attrs, .. })
551 | Expr::Closure(ExprClosure { ref mut attrs, .. })
552 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
553 | Expr::Block(ExprBlock { ref mut attrs, .. })
554 | Expr::Assign(ExprAssign { ref mut attrs, .. })
555 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
556 | Expr::Field(ExprField { ref mut attrs, .. })
557 | Expr::Index(ExprIndex { ref mut attrs, .. })
558 | Expr::Range(ExprRange { ref mut attrs, .. })
559 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200560 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800561 | Expr::Break(ExprBreak { ref mut attrs, .. })
562 | Expr::Continue(ExprContinue { ref mut attrs, .. })
563 | Expr::Return(ExprReturn { ref mut attrs, .. })
564 | Expr::Macro(ExprMacro { ref mut attrs, .. })
565 | Expr::Struct(ExprStruct { ref mut attrs, .. })
566 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
567 | Expr::Paren(ExprParen { ref mut attrs, .. })
568 | Expr::Group(ExprGroup { ref mut attrs, .. })
569 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400570 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400571 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800572 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700573 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500574 }
575 }
576}
577
David Tolnay85b69a42017-12-27 20:43:10 -0500578ast_enum! {
579 /// A struct or tuple struct field accessed in a struct literal or field
580 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800581 ///
582 /// *This type is available if Syn is built with the `"derive"` or `"full"`
583 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500584 pub enum Member {
585 /// A named field like `self.x`.
586 Named(Ident),
587 /// An unnamed field like `self.0`.
588 Unnamed(Index),
589 }
590}
591
David Tolnay85b69a42017-12-27 20:43:10 -0500592ast_struct! {
593 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800594 ///
595 /// *This type is available if Syn is built with the `"derive"` or `"full"`
596 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500597 pub struct Index #manual_extra_traits {
598 pub index: u32,
599 pub span: Span,
600 }
601}
602
David Tolnay14982012017-12-29 00:49:51 -0500603impl From<usize> for Index {
604 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700605 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500606 Index {
607 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700608 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500609 }
610 }
611}
612
613#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500614impl Eq for Index {}
615
David Tolnay14982012017-12-29 00:49:51 -0500616#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500617impl PartialEq for Index {
618 fn eq(&self, other: &Self) -> bool {
619 self.index == other.index
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500624impl Hash for Index {
625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.index.hash(state);
627 }
628}
629
630#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700631ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800632 /// The `::<>` explicit type parameters passed to a method call:
633 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800634 ///
635 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500636 pub struct MethodTurbofish {
637 pub colon2_token: Token![::],
638 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500639 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500640 pub gt_token: Token![>],
641 }
642}
643
644#[cfg(feature = "full")]
645ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800646 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800647 ///
648 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500649 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800650 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500651 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500653 ///
654 /// NOTE: Identity expressions are represented as Type arguments, as
655 /// they are indistinguishable syntactically.
656 Const(Expr),
657 }
658}
659
660#[cfg(feature = "full")]
661ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700662 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800663 ///
664 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700665 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500666 /// Attributes tagged on the field.
667 pub attrs: Vec<Attribute>,
668
669 /// Name or index of the field.
670 pub member: Member,
671
David Tolnay5d7098a2017-12-29 01:35:24 -0500672 /// The colon in `Struct { x: x }`. If written in shorthand like
673 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500674 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500675
Alex Crichton62a0a592017-05-22 13:58:53 -0700676 /// Value of the field.
677 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700678 }
David Tolnay055a7042016-10-02 19:23:54 -0700679}
680
Michael Layzell734adb42017-06-07 16:58:31 -0400681#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700682ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800683 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800684 ///
685 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500686 pub struct Label {
687 pub name: Lifetime,
688 pub colon_token: Token![:],
689 }
690}
691
692#[cfg(feature = "full")]
693ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800695 ///
696 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700697 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500698 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700699 /// Statements in a block
700 pub stmts: Vec<Stmt>,
701 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700702}
703
Michael Layzell734adb42017-06-07 16:58:31 -0400704#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700705ast_enum! {
706 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub enum Stmt {
710 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800711 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700712
Alex Crichton62a0a592017-05-22 13:58:53 -0700713 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800714 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700715
Alex Crichton62a0a592017-05-22 13:58:53 -0700716 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800717 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700718
David Tolnaya454c8f2018-01-07 01:01:10 -0800719 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800720 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700721 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700722}
723
Michael Layzell734adb42017-06-07 16:58:31 -0400724#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700725ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800726 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700729 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500730 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800731 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200732 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500733 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500734 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500735 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700737}
738
Michael Layzell734adb42017-06-07 16:58:31 -0400739#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700740ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A pattern in a local binding, function signature, match expression, or
742 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800743 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800744 /// *This type is available if Syn is built with the `"full"` feature.*
745 ///
David Tolnay614a0142018-01-07 10:25:43 -0800746 /// # Syntax tree enum
747 ///
748 /// This type is a [syntax tree enum].
749 ///
750 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnayb8dec882019-07-20 09:46:14 -0700751 //
752 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
753 // blocked on https://github.com/rust-lang/rust/issues/62833
Alex Crichton62a0a592017-05-22 13:58:53 -0700754 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800755 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800756 ///
757 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700758 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800759 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700760 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700761
David Tolnaya454c8f2018-01-07 01:01:10 -0800762 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800763 ///
764 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500766 pub by_ref: Option<Token![ref]>,
767 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700768 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500769 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700770 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700771
David Tolnaya454c8f2018-01-07 01:01:10 -0800772 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
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 Struct(PatStruct {
776 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500777 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500778 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800779 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700780 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700781
David Tolnaya454c8f2018-01-07 01:01:10 -0800782 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800783 ///
784 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700785 pub TupleStruct(PatTupleStruct {
786 pub path: Path,
787 pub pat: PatTuple,
788 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700789
David Tolnaya454c8f2018-01-07 01:01:10 -0800790 /// A path pattern like `Color::Red`, optionally qualified with a
791 /// self-type.
792 ///
Daniel Muellerd3d71a12019-01-28 06:10:46 -0800793 /// Unqualified path patterns can legally refer to variants, structs,
794 /// constants or associated constants. Qualified path patterns like
David Tolnaya454c8f2018-01-07 01:01:10 -0800795 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
796 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800797 ///
798 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700799 pub Path(PatPath {
800 pub qself: Option<QSelf>,
801 pub path: Path,
802 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700803
David Tolnaya454c8f2018-01-07 01:01:10 -0800804 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800805 ///
806 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700807 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500808 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500809 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500810 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500811 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500812 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700813 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800814
815 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800816 ///
817 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700818 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800819 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500820 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700821 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800822
823 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800824 ///
825 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700826 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800827 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500828 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500829 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700830 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800831
832 /// A literal pattern: `0`.
833 ///
834 /// This holds an `Expr` rather than a `Lit` because negative numbers
835 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800836 ///
837 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700838 pub Lit(PatLit {
839 pub expr: Box<Expr>,
840 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800841
842 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800843 ///
844 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700845 pub Range(PatRange {
846 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700847 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500848 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700849 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800850
851 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800852 ///
853 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500855 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700857 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500858 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500859 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500860 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700861 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800862
863 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800864 ///
865 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500866 pub Macro(PatMacro {
867 pub mac: Macro,
868 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800869
870 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800871 ///
872 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500873 pub Verbatim(PatVerbatim #manual_extra_traits {
874 pub tts: TokenStream,
875 }),
876 }
877}
878
David Tolnayc43b44e2017-12-30 23:55:54 -0500879#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500880impl Eq for PatVerbatim {}
881
David Tolnayc43b44e2017-12-30 23:55:54 -0500882#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500883impl PartialEq for PatVerbatim {
884 fn eq(&self, other: &Self) -> bool {
885 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
886 }
887}
888
David Tolnayc43b44e2017-12-30 23:55:54 -0500889#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500890impl Hash for PatVerbatim {
891 fn hash<H>(&self, state: &mut H)
892 where
893 H: Hasher,
894 {
895 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700896 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700897}
898
Michael Layzell734adb42017-06-07 16:58:31 -0400899#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700900ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800901 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700902 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800903 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700904 ///
David Tolnay95989db2019-01-01 15:05:57 -0500905 /// ```edition2018
David Tolnaya454c8f2018-01-07 01:01:10 -0800906 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500907 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700908 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800909 /// 0...10 => {
910 /// return true;
911 /// }
912 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500913 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700914 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800915 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500916 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700917 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800918 ///
919 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700920 pub struct Arm {
921 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200922 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500923 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500924 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200925 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700926 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800927 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700928 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700929}
930
Michael Layzell734adb42017-06-07 16:58:31 -0400931#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700932ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800933 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800934 ///
935 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700936 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700937 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800938 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800939 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800940 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800941 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700942 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700943}
944
Michael Layzell734adb42017-06-07 16:58:31 -0400945#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700946ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800947 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700948 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800949 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
950 /// 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 -0800951 ///
952 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700953 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500954 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500955 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500956 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700957 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700958 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700959}
960
Michael Layzell3936ceb2017-07-08 00:28:36 -0400961#[cfg(any(feature = "parsing", feature = "printing"))]
962#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700963fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700964 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500965 match *expr {
966 Expr::Unsafe(..)
967 | Expr::Block(..)
968 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500969 | Expr::Match(..)
970 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500971 | Expr::Loop(..)
972 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400973 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400974 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700975 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400976 }
977}
978
David Tolnayb9c8e322016-09-23 20:48:37 -0700979#[cfg(feature = "parsing")]
980pub mod parsing {
981 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700982
Michael Layzell734adb42017-06-07 16:58:31 -0400983 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -0700984 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -0700985 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -0700986 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700987
David Tolnaybcf26022017-12-25 22:10:52 -0500988 // When we're parsing expressions which occur before blocks, like in an if
989 // statement's condition, we cannot parse a struct literal.
990 //
991 // Struct literals are ambiguous in certain positions
992 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -0700993 #[derive(Copy, Clone)]
994 pub struct AllowStruct(bool);
995
David Tolnay01218d12018-08-29 18:13:07 -0700996 #[derive(Copy, Clone, PartialEq, PartialOrd)]
997 enum Precedence {
998 Any,
999 Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001000 Range,
1001 Or,
1002 And,
1003 Compare,
1004 BitOr,
1005 BitXor,
1006 BitAnd,
1007 Shift,
1008 Arithmetic,
1009 Term,
1010 Cast,
1011 }
1012
1013 impl Precedence {
1014 fn of(op: &BinOp) -> Self {
1015 match *op {
1016 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1017 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1018 BinOp::And(_) => Precedence::And,
1019 BinOp::Or(_) => Precedence::Or,
1020 BinOp::BitXor(_) => Precedence::BitXor,
1021 BinOp::BitAnd(_) => Precedence::BitAnd,
1022 BinOp::BitOr(_) => Precedence::BitOr,
1023 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001024 BinOp::Eq(_)
1025 | BinOp::Lt(_)
1026 | BinOp::Le(_)
1027 | BinOp::Ne(_)
1028 | BinOp::Ge(_)
1029 | BinOp::Gt(_) => Precedence::Compare,
1030 BinOp::AddEq(_)
1031 | BinOp::SubEq(_)
1032 | BinOp::MulEq(_)
1033 | BinOp::DivEq(_)
1034 | BinOp::RemEq(_)
1035 | BinOp::BitXorEq(_)
1036 | BinOp::BitAndEq(_)
1037 | BinOp::BitOrEq(_)
1038 | BinOp::ShlEq(_)
1039 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001040 }
1041 }
1042 }
1043
David Tolnay9389c382018-08-27 09:13:37 -07001044 impl Parse for Expr {
1045 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001046 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001047 }
1048 }
1049
Michael Layzell734adb42017-06-07 16:58:31 -04001050 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001051 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001052 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001053 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001054
David Tolnay01218d12018-08-29 18:13:07 -07001055 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001056 fn parse_expr(
1057 input: ParseStream,
1058 mut lhs: Expr,
1059 allow_struct: AllowStruct,
1060 base: Precedence,
1061 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001062 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001063 if input
1064 .fork()
1065 .parse::<BinOp>()
1066 .ok()
1067 .map_or(false, |op| Precedence::of(&op) >= base)
1068 {
David Tolnay01218d12018-08-29 18:13:07 -07001069 let op: BinOp = input.parse()?;
1070 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001071 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001072 loop {
1073 let next = peek_precedence(input);
1074 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001075 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001076 } else {
1077 break;
1078 }
1079 }
David Tolnay90276252018-08-31 10:50:08 -07001080 lhs = if precedence == Precedence::Assign {
1081 Expr::AssignOp(ExprAssignOp {
1082 attrs: Vec::new(),
1083 left: Box::new(lhs),
1084 op: op,
1085 right: Box::new(rhs),
1086 })
1087 } else {
1088 Expr::Binary(ExprBinary {
1089 attrs: Vec::new(),
1090 left: Box::new(lhs),
1091 op: op,
1092 right: Box::new(rhs),
1093 })
1094 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001095 } else if Precedence::Assign >= base
1096 && input.peek(Token![=])
1097 && !input.peek(Token![==])
1098 && !input.peek(Token![=>])
1099 {
David Tolnay01218d12018-08-29 18:13:07 -07001100 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001101 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001102 loop {
1103 let next = peek_precedence(input);
1104 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001105 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001106 } else {
1107 break;
1108 }
1109 }
1110 lhs = Expr::Assign(ExprAssign {
1111 attrs: Vec::new(),
1112 left: Box::new(lhs),
1113 eq_token: eq_token,
1114 right: Box::new(rhs),
1115 });
David Tolnay01218d12018-08-29 18:13:07 -07001116 } else if Precedence::Range >= base && input.peek(Token![..]) {
1117 let limits: RangeLimits = input.parse()?;
1118 let rhs = if input.is_empty()
1119 || input.peek(Token![,])
1120 || input.peek(Token![;])
1121 || !allow_struct.0 && input.peek(token::Brace)
1122 {
1123 None
1124 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001125 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001126 loop {
1127 let next = peek_precedence(input);
1128 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001129 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001130 } else {
1131 break;
1132 }
1133 }
1134 Some(rhs)
1135 };
1136 lhs = Expr::Range(ExprRange {
1137 attrs: Vec::new(),
1138 from: Some(Box::new(lhs)),
1139 limits: limits,
1140 to: rhs.map(Box::new),
1141 });
1142 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1143 let as_token: Token![as] = input.parse()?;
1144 let ty = input.call(Type::without_plus)?;
1145 lhs = Expr::Cast(ExprCast {
1146 attrs: Vec::new(),
1147 expr: Box::new(lhs),
1148 as_token: as_token,
1149 ty: Box::new(ty),
1150 });
1151 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1152 let colon_token: Token![:] = input.parse()?;
1153 let ty = input.call(Type::without_plus)?;
1154 lhs = Expr::Type(ExprType {
1155 attrs: Vec::new(),
1156 expr: Box::new(lhs),
1157 colon_token: colon_token,
1158 ty: Box::new(ty),
1159 });
1160 } else {
1161 break;
1162 }
1163 }
1164 Ok(lhs)
1165 }
1166
David Tolnay3e541292018-08-30 11:42:15 -07001167 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001168 fn parse_expr(
1169 input: ParseStream,
1170 mut lhs: Expr,
1171 allow_struct: AllowStruct,
1172 base: Precedence,
1173 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001174 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001175 if input
1176 .fork()
1177 .parse::<BinOp>()
1178 .ok()
1179 .map_or(false, |op| Precedence::of(&op) >= base)
1180 {
David Tolnay3e541292018-08-30 11:42:15 -07001181 let op: BinOp = input.parse()?;
1182 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001183 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001184 loop {
1185 let next = peek_precedence(input);
1186 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001187 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001188 } else {
1189 break;
1190 }
1191 }
1192 lhs = Expr::Binary(ExprBinary {
1193 attrs: Vec::new(),
1194 left: Box::new(lhs),
1195 op: op,
1196 right: Box::new(rhs),
1197 });
1198 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1199 let as_token: Token![as] = input.parse()?;
1200 let ty = input.call(Type::without_plus)?;
1201 lhs = Expr::Cast(ExprCast {
1202 attrs: Vec::new(),
1203 expr: Box::new(lhs),
1204 as_token: as_token,
1205 ty: Box::new(ty),
1206 });
1207 } else {
1208 break;
1209 }
1210 }
1211 Ok(lhs)
1212 }
1213
David Tolnay01218d12018-08-29 18:13:07 -07001214 fn peek_precedence(input: ParseStream) -> Precedence {
1215 if let Ok(op) = input.fork().parse() {
1216 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001217 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001218 Precedence::Assign
David Tolnay01218d12018-08-29 18:13:07 -07001219 } else if input.peek(Token![..]) {
1220 Precedence::Range
1221 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1222 Precedence::Cast
1223 } else {
1224 Precedence::Any
1225 }
1226 }
1227
David Tolnaybcf26022017-12-25 22:10:52 -05001228 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001229 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001230 let lhs = unary_expr(input, allow_struct)?;
1231 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001232 }
1233
David Tolnaybcf26022017-12-25 22:10:52 -05001234 // <UnOp> <trailer>
1235 // & <trailer>
1236 // &mut <trailer>
1237 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001238 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001239 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07001240 // TODO: optimize using advance_to
David Tolnay377263f2018-08-27 13:48:30 -07001241 let ahead = input.fork();
1242 ahead.call(Attribute::parse_outer)?;
1243 if ahead.peek(Token![&])
1244 || ahead.peek(Token![box])
1245 || ahead.peek(Token![*])
1246 || ahead.peek(Token![!])
1247 || ahead.peek(Token![-])
1248 {
1249 let attrs = input.call(Attribute::parse_outer)?;
1250 if input.peek(Token![&]) {
1251 Ok(Expr::Reference(ExprReference {
1252 attrs: attrs,
1253 and_token: input.parse()?,
1254 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001255 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001256 }))
1257 } else if input.peek(Token![box]) {
1258 Ok(Expr::Box(ExprBox {
1259 attrs: attrs,
1260 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001261 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001262 }))
1263 } else {
1264 Ok(Expr::Unary(ExprUnary {
1265 attrs: attrs,
1266 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001267 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001268 }))
1269 }
1270 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001271 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001272 }
1273 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001274
Michael Layzell734adb42017-06-07 16:58:31 -04001275 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001276 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07001277 // TODO: optimize using advance_to
David Tolnay377263f2018-08-27 13:48:30 -07001278 let ahead = input.fork();
1279 ahead.call(Attribute::parse_outer)?;
1280 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1281 Ok(Expr::Unary(ExprUnary {
1282 attrs: input.call(Attribute::parse_outer)?,
1283 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001284 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001285 }))
1286 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001287 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001288 }
1289 }
Michael Layzell734adb42017-06-07 16:58:31 -04001290
David Tolnaybcf26022017-12-25 22:10:52 -05001291 // <atom> (..<args>) ...
1292 // <atom> . <ident> (..<args>) ...
1293 // <atom> . <ident> ...
1294 // <atom> . <lit> ...
1295 // <atom> [ <expr> ] ...
1296 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001297 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001298 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001299 if input.peek(token::Group) {
1300 return input.call(expr_group).map(Expr::Group);
1301 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001302
David Tolnay577fd312018-09-01 02:26:40 -07001303 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001304
David Tolnay577fd312018-09-01 02:26:40 -07001305 let atom = atom_expr(input, allow_struct)?;
1306 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001307
David Tolnay577fd312018-09-01 02:26:40 -07001308 let inner_attrs = e.replace_attrs(Vec::new());
1309 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001310 e.replace_attrs(attrs);
1311 Ok(e)
1312 }
1313
1314 #[cfg(feature = "full")]
1315 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001316 loop {
1317 if input.peek(token::Paren) {
1318 let content;
1319 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001320 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001321 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001322 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001323 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001324 });
1325 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1326 let dot_token: Token![.] = input.parse()?;
1327 let member: Member = input.parse()?;
1328 let turbofish = if member.is_named() && input.peek(Token![::]) {
1329 Some(MethodTurbofish {
1330 colon2_token: input.parse()?,
1331 lt_token: input.parse()?,
1332 args: {
1333 let mut args = Punctuated::new();
1334 loop {
1335 if input.peek(Token![>]) {
1336 break;
1337 }
David Tolnay310b3262018-08-30 15:33:00 -07001338 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001339 args.push_value(value);
1340 if input.peek(Token![>]) {
1341 break;
1342 }
1343 let punct = input.parse()?;
1344 args.push_punct(punct);
1345 }
1346 args
1347 },
1348 gt_token: input.parse()?,
1349 })
1350 } else {
1351 None
1352 };
1353
1354 if turbofish.is_some() || input.peek(token::Paren) {
1355 if let Member::Named(method) = member {
1356 let content;
1357 e = Expr::MethodCall(ExprMethodCall {
1358 attrs: Vec::new(),
1359 receiver: Box::new(e),
1360 dot_token: dot_token,
1361 method: method,
1362 turbofish: turbofish,
1363 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001364 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001365 });
1366 continue;
1367 }
1368 }
1369
1370 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001371 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001372 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001373 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001374 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001375 });
1376 } else if input.peek(token::Bracket) {
1377 let content;
1378 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001379 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001380 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001381 bracket_token: bracketed!(content in input),
1382 index: content.parse()?,
1383 });
1384 } else if input.peek(Token![?]) {
1385 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001386 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001387 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001388 question_token: input.parse()?,
1389 });
1390 } else {
1391 break;
1392 }
1393 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001394 Ok(e)
1395 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001396
Michael Layzell734adb42017-06-07 16:58:31 -04001397 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001398 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001399 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001400
1401 loop {
1402 if input.peek(token::Paren) {
1403 let content;
1404 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001405 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001406 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001407 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001408 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001409 });
1410 } else if input.peek(Token![.]) {
1411 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001412 attrs: Vec::new(),
1413 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001414 dot_token: input.parse()?,
1415 member: input.parse()?,
1416 });
1417 } else if input.peek(token::Bracket) {
1418 let content;
1419 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001420 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001421 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001422 bracket_token: bracketed!(content in input),
1423 index: content.parse()?,
1424 });
1425 } else {
1426 break;
1427 }
1428 }
1429
1430 Ok(e)
1431 }
Michael Layzell734adb42017-06-07 16:58:31 -04001432
David Tolnaya454c8f2018-01-07 01:01:10 -08001433 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001434 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001435 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001436 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001437 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001438 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001439 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001440 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001441 } else if input.peek(Token![async])
1442 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1443 {
David Tolnay577fd312018-09-01 02:26:40 -07001444 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001445 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001446 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001447 } else if input.peek(Token![|])
1448 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1449 || input.peek(Token![static])
1450 || input.peek(Token![move])
1451 {
David Tolnay577fd312018-09-01 02:26:40 -07001452 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001453 } else if input.peek(Ident)
1454 || input.peek(Token![::])
1455 || input.peek(Token![<])
1456 || input.peek(Token![self])
1457 || input.peek(Token![Self])
1458 || input.peek(Token![super])
1459 || input.peek(Token![extern])
1460 || input.peek(Token![crate])
1461 {
David Tolnay577fd312018-09-01 02:26:40 -07001462 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001463 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001464 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001465 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001466 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001467 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001468 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001469 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001470 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001471 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001472 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001473 } else if input.peek(Token![let]) {
1474 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001475 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001476 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001477 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001478 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001479 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001480 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001481 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001482 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001483 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001484 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001485 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001486 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001487 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001488 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001489 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001490 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001491 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001492 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001493 } else if input.peek(Lifetime) {
1494 let the_label: Label = input.parse()?;
1495 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001496 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001497 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001498 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001499 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001500 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001501 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001502 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001503 } else {
1504 return Err(input.error("expected loop or block expression"));
1505 };
1506 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001507 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001508 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1509 | Expr::Loop(ExprLoop { ref mut label, .. })
1510 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001511 _ => unreachable!(),
1512 }
David Tolnay577fd312018-09-01 02:26:40 -07001513 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001515 Err(input.error("expected expression"))
1516 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001517 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001518
Michael Layzell734adb42017-06-07 16:58:31 -04001519 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001520 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001521 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001522 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001523 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001524 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001525 } else if input.peek(Ident)
1526 || input.peek(Token![::])
1527 || input.peek(Token![<])
1528 || input.peek(Token![self])
1529 || input.peek(Token![Self])
1530 || input.peek(Token![super])
1531 || input.peek(Token![extern])
1532 || input.peek(Token![crate])
1533 {
1534 input.parse().map(Expr::Path)
1535 } else {
1536 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1537 }
1538 }
1539
1540 #[cfg(feature = "full")]
1541 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1542 let expr: ExprPath = input.parse()?;
1543 if expr.qself.is_some() {
1544 return Ok(Expr::Path(expr));
1545 }
1546
1547 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1548 let mut contains_arguments = false;
1549 for segment in &expr.path.segments {
1550 match segment.arguments {
1551 PathArguments::None => {}
1552 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1553 contains_arguments = true;
1554 }
1555 }
1556 }
1557
1558 if !contains_arguments {
1559 let bang_token: Token![!] = input.parse()?;
1560 let (delimiter, tts) = mac::parse_delimiter(input)?;
1561 return Ok(Expr::Macro(ExprMacro {
1562 attrs: Vec::new(),
1563 mac: Macro {
1564 path: expr.path,
1565 bang_token: bang_token,
1566 delimiter: delimiter,
1567 tts: tts,
1568 },
1569 }));
1570 }
1571 }
1572
1573 if allow_struct.0 && input.peek(token::Brace) {
1574 let outer_attrs = Vec::new();
1575 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1576 } else {
1577 Ok(Expr::Path(expr))
1578 }
1579 }
1580
1581 #[cfg(feature = "full")]
1582 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1583 let content;
1584 let paren_token = parenthesized!(content in input);
1585 let inner_attrs = content.call(Attribute::parse_inner)?;
1586 if content.is_empty() {
1587 return Ok(Expr::Tuple(ExprTuple {
1588 attrs: inner_attrs,
1589 paren_token: paren_token,
1590 elems: Punctuated::new(),
1591 }));
1592 }
1593
1594 let first: Expr = content.parse()?;
1595 if content.is_empty() {
1596 return Ok(Expr::Paren(ExprParen {
1597 attrs: inner_attrs,
1598 paren_token: paren_token,
1599 expr: Box::new(first),
1600 }));
1601 }
1602
1603 let mut elems = Punctuated::new();
1604 elems.push_value(first);
1605 while !content.is_empty() {
1606 let punct = content.parse()?;
1607 elems.push_punct(punct);
1608 if content.is_empty() {
1609 break;
1610 }
1611 let value = content.parse()?;
1612 elems.push_value(value);
1613 }
1614 Ok(Expr::Tuple(ExprTuple {
1615 attrs: inner_attrs,
1616 paren_token: paren_token,
1617 elems: elems,
1618 }))
1619 }
1620
1621 #[cfg(feature = "full")]
1622 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1623 let content;
1624 let bracket_token = bracketed!(content in input);
1625 let inner_attrs = content.call(Attribute::parse_inner)?;
1626 if content.is_empty() {
1627 return Ok(Expr::Array(ExprArray {
1628 attrs: inner_attrs,
1629 bracket_token: bracket_token,
1630 elems: Punctuated::new(),
1631 }));
1632 }
1633
1634 let first: Expr = content.parse()?;
1635 if content.is_empty() || content.peek(Token![,]) {
1636 let mut elems = Punctuated::new();
1637 elems.push_value(first);
1638 while !content.is_empty() {
1639 let punct = content.parse()?;
1640 elems.push_punct(punct);
1641 if content.is_empty() {
1642 break;
1643 }
1644 let value = content.parse()?;
1645 elems.push_value(value);
1646 }
1647 Ok(Expr::Array(ExprArray {
1648 attrs: inner_attrs,
1649 bracket_token: bracket_token,
1650 elems: elems,
1651 }))
1652 } else if content.peek(Token![;]) {
1653 let semi_token: Token![;] = content.parse()?;
1654 let len: Expr = content.parse()?;
1655 Ok(Expr::Repeat(ExprRepeat {
1656 attrs: inner_attrs,
1657 bracket_token: bracket_token,
1658 expr: Box::new(first),
1659 semi_token: semi_token,
1660 len: Box::new(len),
1661 }))
1662 } else {
1663 Err(content.error("expected `,` or `;`"))
1664 }
1665 }
Michael Layzell734adb42017-06-07 16:58:31 -04001666
Michael Layzell734adb42017-06-07 16:58:31 -04001667 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001668 fn expr_early(input: ParseStream) -> Result<Expr> {
1669 let mut attrs = input.call(Attribute::parse_outer)?;
1670 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001671 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001672 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001673 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001674 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001675 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001676 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001677 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001678 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001679 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001680 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001681 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001682 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001683 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001684 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001685 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001686 } else {
1687 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001688 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001689
1690 attrs.extend(expr.replace_attrs(Vec::new()));
1691 expr.replace_attrs(attrs);
1692
David Tolnay7d2e1db2018-08-30 11:49:04 -07001693 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001694 };
1695
1696 if input.peek(Token![.]) || input.peek(Token![?]) {
1697 expr = trailer_helper(input, expr)?;
1698
1699 attrs.extend(expr.replace_attrs(Vec::new()));
1700 expr.replace_attrs(attrs);
1701
1702 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001703 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001704 }
1705
1706 attrs.extend(expr.replace_attrs(Vec::new()));
1707 expr.replace_attrs(attrs);
1708 Ok(expr)
1709 }
Michael Layzell35418782017-06-07 09:20:25 -04001710
Peter Hall04f42792019-04-02 16:58:45 +02001711 impl Parse for ExprLit {
1712 fn parse(input: ParseStream) -> Result<Self> {
1713 Ok(ExprLit {
1714 attrs: Vec::new(),
1715 lit: input.parse()?,
1716 })
1717 }
David Tolnay8c91b882017-12-28 23:04:32 -05001718 }
1719
1720 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001721 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001722 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001723 Ok(ExprGroup {
1724 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001725 group_token: group.token,
1726 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001727 })
1728 }
1729
1730 #[cfg(not(feature = "full"))]
1731 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1732 let content;
1733 Ok(ExprParen {
1734 attrs: Vec::new(),
1735 paren_token: parenthesized!(content in input),
1736 expr: content.parse()?,
1737 })
David Tolnay8c91b882017-12-28 23:04:32 -05001738 }
1739
David Tolnaye98775f2017-12-28 23:17:00 -05001740 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001741 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001742 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001743 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001744 }
1745
1746 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001747 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1748 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001749 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001750 let_token: input.parse()?,
1751 pats: {
1752 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001753 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001754 let value: Pat = input.parse()?;
1755 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001756 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001757 let punct = input.parse()?;
1758 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001759 let value: Pat = input.parse()?;
1760 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001761 }
1762 pats
1763 },
1764 eq_token: input.parse()?,
1765 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001766 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001767 }
1768
Michael Layzell734adb42017-06-07 16:58:31 -04001769 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001770 impl Parse for ExprIf {
1771 fn parse(input: ParseStream) -> Result<Self> {
1772 Ok(ExprIf {
1773 attrs: Vec::new(),
1774 if_token: input.parse()?,
1775 cond: Box::new(input.call(expr_no_struct)?),
1776 then_branch: input.parse()?,
1777 else_branch: {
1778 if input.peek(Token![else]) {
1779 Some(input.call(else_block)?)
1780 } else {
1781 None
1782 }
1783 },
1784 })
1785 }
Alex Crichton954046c2017-05-30 21:49:42 -07001786 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001787
Michael Layzell734adb42017-06-07 16:58:31 -04001788 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001789 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1790 let else_token: Token![else] = input.parse()?;
1791
1792 let lookahead = input.lookahead1();
1793 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001794 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001795 } else if input.peek(token::Brace) {
1796 Expr::Block(ExprBlock {
1797 attrs: Vec::new(),
1798 label: None,
1799 block: input.parse()?,
1800 })
1801 } else {
1802 return Err(lookahead.error());
1803 };
1804
1805 Ok((else_token, Box::new(else_branch)))
1806 }
David Tolnay939766a2016-09-23 23:48:12 -07001807
Michael Layzell734adb42017-06-07 16:58:31 -04001808 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001809 impl Parse for ExprForLoop {
1810 fn parse(input: ParseStream) -> Result<Self> {
1811 let label: Option<Label> = input.parse()?;
1812 let for_token: Token![for] = input.parse()?;
1813 let pat: Pat = input.parse()?;
1814 let in_token: Token![in] = input.parse()?;
1815 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001816
Peter Hall04f42792019-04-02 16:58:45 +02001817 let content;
1818 let brace_token = braced!(content in input);
1819 let inner_attrs = content.call(Attribute::parse_inner)?;
1820 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001821
Peter Hall04f42792019-04-02 16:58:45 +02001822 Ok(ExprForLoop {
1823 attrs: inner_attrs,
1824 label: label,
1825 for_token: for_token,
1826 pat: Box::new(pat),
1827 in_token: in_token,
1828 expr: Box::new(expr),
1829 body: Block {
1830 brace_token: brace_token,
1831 stmts: stmts,
1832 },
1833 })
1834 }
Alex Crichton954046c2017-05-30 21:49:42 -07001835 }
David Tolnay1978c672016-10-27 22:05:52 -07001836
Michael Layzell734adb42017-06-07 16:58:31 -04001837 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001838 impl Parse for ExprLoop {
1839 fn parse(input: ParseStream) -> Result<Self> {
1840 let label: Option<Label> = input.parse()?;
1841 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001842
Peter Hall04f42792019-04-02 16:58:45 +02001843 let content;
1844 let brace_token = braced!(content in input);
1845 let inner_attrs = content.call(Attribute::parse_inner)?;
1846 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001847
Peter Hall04f42792019-04-02 16:58:45 +02001848 Ok(ExprLoop {
1849 attrs: inner_attrs,
1850 label: label,
1851 loop_token: loop_token,
1852 body: Block {
1853 brace_token: brace_token,
1854 stmts: stmts,
1855 },
1856 })
1857 }
Alex Crichton954046c2017-05-30 21:49:42 -07001858 }
Arnavion02ef13f2017-04-25 00:54:31 -07001859
Michael Layzell734adb42017-06-07 16:58:31 -04001860 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001861 impl Parse for ExprMatch {
1862 fn parse(input: ParseStream) -> Result<Self> {
1863 let match_token: Token![match] = input.parse()?;
1864 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001865
Peter Hall55f00f72019-04-02 16:50:57 +02001866 let content;
1867 let brace_token = braced!(content in input);
1868 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001869
Peter Hall55f00f72019-04-02 16:50:57 +02001870 let mut arms = Vec::new();
1871 while !content.is_empty() {
1872 arms.push(content.call(Arm::parse)?);
1873 }
1874
1875 Ok(ExprMatch {
1876 attrs: inner_attrs,
1877 match_token: match_token,
1878 expr: Box::new(expr),
1879 brace_token: brace_token,
1880 arms: arms,
1881 })
David Tolnay310b3262018-08-30 15:33:00 -07001882 }
David Tolnay310b3262018-08-30 15:33:00 -07001883 }
1884
David Tolnaye52022b2019-05-25 00:26:54 -07001885 #[cfg(all(feature = "full", feature = "printing"))]
1886 impl Parse for ExprInPlace {
1887 fn parse(input: ParseStream) -> Result<Self> {
1888 let msg = "placement expression has been removed from Rust and is no longer parsed";
1889 Err(input.error(msg))
1890 }
1891 }
1892
bstriecde20e62019-05-05 13:29:15 -04001893 macro_rules! impl_by_parsing_expr {
David Tolnaye957eb62019-05-07 22:02:51 -07001894 (
1895 $(
1896 $expr_type:ty, $variant:ident, $msg:expr,
1897 )*
1898 ) => {
1899 $(
1900 #[cfg(all(feature = "full", feature = "printing"))]
1901 impl Parse for $expr_type {
1902 fn parse(input: ParseStream) -> Result<Self> {
1903 let mut expr: Expr = input.parse()?;
1904 loop {
1905 match expr {
1906 Expr::$variant(inner) => return Ok(inner),
1907 Expr::Group(next) => expr = *next.expr,
1908 _ => return Err(Error::new_spanned(expr, $msg)),
1909 }
bstrie1626c372019-05-05 13:44:57 -04001910 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001911 }
1912 }
David Tolnaye957eb62019-05-07 22:02:51 -07001913 )*
David Tolnaya58223d2019-05-07 21:58:15 -07001914 };
bstrie7b4f52d2019-04-30 18:44:21 -04001915 }
1916
David Tolnaye957eb62019-05-07 22:02:51 -07001917 impl_by_parsing_expr! {
1918 ExprBox, Box, "expected box expression",
David Tolnaye957eb62019-05-07 22:02:51 -07001919 ExprArray, Array, "expected slice literal expression",
1920 ExprCall, Call, "expected function call expression",
1921 ExprMethodCall, MethodCall, "expected method call expression",
1922 ExprTuple, Tuple, "expected tuple expression",
1923 ExprBinary, Binary, "expected binary operation",
1924 ExprUnary, Unary, "expected unary operation",
1925 ExprCast, Cast, "expected cast expression",
1926 ExprType, Type, "expected type ascription expression",
1927 ExprLet, Let, "expected let guard",
1928 ExprClosure, Closure, "expected closure expression",
1929 ExprUnsafe, Unsafe, "expected unsafe block",
1930 ExprBlock, Block, "expected blocked scope",
1931 ExprAssign, Assign, "expected assignment expression",
1932 ExprAssignOp, AssignOp, "expected compound assignment expression",
1933 ExprField, Field, "expected struct field access",
1934 ExprIndex, Index, "expected indexing expression",
1935 ExprRange, Range, "expected range expression",
1936 ExprReference, Reference, "expected referencing operation",
1937 ExprBreak, Break, "expected break expression",
1938 ExprContinue, Continue, "expected continue expression",
1939 ExprReturn, Return, "expected return expression",
1940 ExprMacro, Macro, "expected macro invocation expression",
1941 ExprStruct, Struct, "expected struct literal expression",
1942 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
1943 ExprParen, Paren, "expected parenthesized expression",
1944 ExprTry, Try, "expected try expression",
1945 ExprAsync, Async, "expected async block",
1946 ExprTryBlock, TryBlock, "expected try block",
1947 ExprYield, Yield, "expected yield expression",
1948 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001949
David Tolnay310b3262018-08-30 15:33:00 -07001950 #[cfg(feature = "full")]
1951 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1952 Ok(ExprTryBlock {
1953 attrs: Vec::new(),
1954 try_token: input.parse()?,
1955 block: input.parse()?,
1956 })
1957 }
1958
1959 #[cfg(feature = "full")]
1960 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1961 Ok(ExprYield {
1962 attrs: Vec::new(),
1963 yield_token: input.parse()?,
1964 expr: {
1965 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1966 Some(input.parse()?)
1967 } else {
1968 None
1969 }
1970 },
1971 })
1972 }
1973
1974 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001975 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001976 let asyncness: Option<Token![async]> = input.parse()?;
1977 let movability: Option<Token![static]> = if asyncness.is_none() {
1978 input.parse()?
1979 } else {
1980 None
1981 };
1982 let capture: Option<Token![move]> = input.parse()?;
1983 let or1_token: Token![|] = input.parse()?;
1984
1985 let mut inputs = Punctuated::new();
1986 loop {
1987 if input.peek(Token![|]) {
1988 break;
1989 }
1990 let value = fn_arg(input)?;
1991 inputs.push_value(value);
1992 if input.peek(Token![|]) {
1993 break;
1994 }
1995 let punct: Token![,] = input.parse()?;
1996 inputs.push_punct(punct);
1997 }
1998
1999 let or2_token: Token![|] = input.parse()?;
2000
2001 let (output, body) = if input.peek(Token![->]) {
2002 let arrow_token: Token![->] = input.parse()?;
2003 let ty: Type = input.parse()?;
2004 let body: Block = input.parse()?;
2005 let output = ReturnType::Type(arrow_token, Box::new(ty));
2006 let block = Expr::Block(ExprBlock {
2007 attrs: Vec::new(),
2008 label: None,
2009 block: body,
2010 });
2011 (output, block)
2012 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002013 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002014 (ReturnType::Default, body)
2015 };
2016
2017 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002018 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002019 asyncness: asyncness,
2020 movability: movability,
2021 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002022 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002023 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002024 or2_token: or2_token,
2025 output: output,
2026 body: Box::new(body),
2027 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002028 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002029
2030 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002031 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2032 Ok(ExprAsync {
2033 attrs: Vec::new(),
2034 async_token: input.parse()?,
2035 capture: input.parse()?,
2036 block: input.parse()?,
2037 })
David Tolnay60291082018-08-28 09:54:49 -07002038 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002039
Michael Layzell734adb42017-06-07 16:58:31 -04002040 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002041 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2042 let pat: Pat = input.parse()?;
2043
2044 if input.peek(Token![:]) {
2045 Ok(FnArg::Captured(ArgCaptured {
2046 pat: pat,
2047 colon_token: input.parse()?,
2048 ty: input.parse()?,
2049 }))
2050 } else {
2051 Ok(FnArg::Inferred(pat))
2052 }
2053 }
2054
2055 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002056 impl Parse for ExprWhile {
2057 fn parse(input: ParseStream) -> Result<Self> {
2058 let label: Option<Label> = input.parse()?;
2059 let while_token: Token![while] = input.parse()?;
2060 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002061
Peter Hall04f42792019-04-02 16:58:45 +02002062 let content;
2063 let brace_token = braced!(content in input);
2064 let inner_attrs = content.call(Attribute::parse_inner)?;
2065 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002066
Peter Hall04f42792019-04-02 16:58:45 +02002067 Ok(ExprWhile {
2068 attrs: inner_attrs,
2069 label: label,
2070 while_token: while_token,
2071 cond: Box::new(cond),
2072 body: Block {
2073 brace_token: brace_token,
2074 stmts: stmts,
2075 },
2076 })
2077 }
Alex Crichton954046c2017-05-30 21:49:42 -07002078 }
2079
Michael Layzell734adb42017-06-07 16:58:31 -04002080 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002081 impl Parse for Label {
2082 fn parse(input: ParseStream) -> Result<Self> {
2083 Ok(Label {
2084 name: input.parse()?,
2085 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002086 })
David Tolnay60291082018-08-28 09:54:49 -07002087 }
Alex Crichton954046c2017-05-30 21:49:42 -07002088 }
2089
Michael Layzell734adb42017-06-07 16:58:31 -04002090 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002091 impl Parse for Option<Label> {
2092 fn parse(input: ParseStream) -> Result<Self> {
2093 if input.peek(Lifetime) {
2094 input.parse().map(Some)
2095 } else {
2096 Ok(None)
2097 }
2098 }
2099 }
2100
2101 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002102 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2103 Ok(ExprContinue {
2104 attrs: Vec::new(),
2105 continue_token: input.parse()?,
2106 label: input.parse()?,
2107 })
Alex Crichton954046c2017-05-30 21:49:42 -07002108 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002109
Michael Layzell734adb42017-06-07 16:58:31 -04002110 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002111 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2112 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002113 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002114 break_token: input.parse()?,
2115 label: input.parse()?,
2116 expr: {
2117 if input.is_empty()
2118 || input.peek(Token![,])
2119 || input.peek(Token![;])
2120 || !allow_struct.0 && input.peek(token::Brace)
2121 {
2122 None
2123 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002124 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002125 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002126 }
David Tolnay60291082018-08-28 09:54:49 -07002127 },
2128 })
Alex Crichton954046c2017-05-30 21:49:42 -07002129 }
2130
Michael Layzell734adb42017-06-07 16:58:31 -04002131 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002132 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2133 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002134 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002135 return_token: input.parse()?,
2136 expr: {
2137 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2138 None
2139 } else {
2140 // NOTE: return is greedy and eats blocks after it even when in a
2141 // position where structs are not allowed, such as in if statement
2142 // conditions. For example:
2143 //
2144 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002145 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002146 Some(Box::new(expr))
2147 }
2148 },
2149 })
2150 }
2151
2152 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002153 impl Parse for FieldValue {
2154 fn parse(input: ParseStream) -> Result<Self> {
2155 let member: Member = input.parse()?;
2156 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2157 let colon_token: Token![:] = input.parse()?;
2158 let value: Expr = input.parse()?;
2159 (Some(colon_token), value)
2160 } else if let Member::Named(ref ident) = member {
2161 let value = Expr::Path(ExprPath {
2162 attrs: Vec::new(),
2163 qself: None,
2164 path: Path::from(ident.clone()),
2165 });
2166 (None, value)
2167 } else {
2168 unreachable!()
2169 };
2170
2171 Ok(FieldValue {
2172 attrs: Vec::new(),
2173 member: member,
2174 colon_token: colon_token,
2175 expr: value,
2176 })
2177 }
2178 }
2179
2180 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002181 fn expr_struct_helper(
2182 input: ParseStream,
2183 outer_attrs: Vec<Attribute>,
2184 path: Path,
2185 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002186 let content;
2187 let brace_token = braced!(content in input);
2188 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002189
David Tolnay6e1e5052018-08-30 10:21:48 -07002190 let mut fields = Punctuated::new();
2191 loop {
2192 let attrs = content.call(Attribute::parse_outer)?;
David Tolnay3e22c0b2019-06-23 16:58:38 -07002193 // TODO: optimize using advance_to
David Tolnay6e1e5052018-08-30 10:21:48 -07002194 if content.fork().parse::<Member>().is_err() {
2195 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002196 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002197 } else {
2198 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002199 }
David Tolnay60291082018-08-28 09:54:49 -07002200 }
2201
David Tolnay6e1e5052018-08-30 10:21:48 -07002202 fields.push(FieldValue {
2203 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002204 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002205 });
2206
2207 if !content.peek(Token![,]) {
2208 break;
2209 }
2210 let punct: Token![,] = content.parse()?;
2211 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002212 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002213
2214 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2215 let dot2_token: Token![..] = content.parse()?;
2216 let rest: Expr = content.parse()?;
2217 (Some(dot2_token), Some(Box::new(rest)))
2218 } else {
2219 (None, None)
2220 };
2221
2222 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002223 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002224 brace_token: brace_token,
2225 path: path,
2226 fields: fields,
2227 dot2_token: dot2_token,
2228 rest: rest,
2229 })
Alex Crichton954046c2017-05-30 21:49:42 -07002230 }
David Tolnay055a7042016-10-02 19:23:54 -07002231
Michael Layzell734adb42017-06-07 16:58:31 -04002232 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002233 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2234 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002235
David Tolnay310b3262018-08-30 15:33:00 -07002236 let content;
2237 let brace_token = braced!(content in input);
2238 let inner_attrs = content.call(Attribute::parse_inner)?;
2239 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002240
David Tolnay310b3262018-08-30 15:33:00 -07002241 Ok(ExprUnsafe {
2242 attrs: inner_attrs,
2243 unsafe_token: unsafe_token,
2244 block: Block {
2245 brace_token: brace_token,
2246 stmts: stmts,
2247 },
2248 })
Alex Crichton954046c2017-05-30 21:49:42 -07002249 }
David Tolnay055a7042016-10-02 19:23:54 -07002250
Michael Layzell734adb42017-06-07 16:58:31 -04002251 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002252 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2253 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002254
David Tolnay310b3262018-08-30 15:33:00 -07002255 let content;
2256 let brace_token = braced!(content in input);
2257 let inner_attrs = content.call(Attribute::parse_inner)?;
2258 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002259
David Tolnay310b3262018-08-30 15:33:00 -07002260 Ok(ExprBlock {
2261 attrs: inner_attrs,
2262 label: label,
2263 block: Block {
2264 brace_token: brace_token,
2265 stmts: stmts,
2266 },
2267 })
Alex Crichton954046c2017-05-30 21:49:42 -07002268 }
David Tolnay89e05672016-10-02 14:39:42 -07002269
Michael Layzell734adb42017-06-07 16:58:31 -04002270 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002271 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2272 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002273 attrs: Vec::new(),
2274 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002275 limits: input.parse()?,
2276 to: {
2277 if input.is_empty()
2278 || input.peek(Token![,])
2279 || input.peek(Token![;])
2280 || !allow_struct.0 && input.peek(token::Brace)
2281 {
2282 None
2283 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002284 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002285 Some(Box::new(to))
2286 }
2287 },
2288 })
2289 }
David Tolnay438c9052016-10-07 23:24:48 -07002290
Michael Layzell734adb42017-06-07 16:58:31 -04002291 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002292 impl Parse for RangeLimits {
2293 fn parse(input: ParseStream) -> Result<Self> {
2294 let lookahead = input.lookahead1();
2295 if lookahead.peek(Token![..=]) {
2296 input.parse().map(RangeLimits::Closed)
2297 } else if lookahead.peek(Token![...]) {
2298 let dot3: Token![...] = input.parse()?;
2299 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2300 } else if lookahead.peek(Token![..]) {
2301 input.parse().map(RangeLimits::HalfOpen)
2302 } else {
2303 Err(lookahead.error())
2304 }
2305 }
Alex Crichton954046c2017-05-30 21:49:42 -07002306 }
David Tolnay438c9052016-10-07 23:24:48 -07002307
David Tolnay60291082018-08-28 09:54:49 -07002308 impl Parse for ExprPath {
2309 fn parse(input: ParseStream) -> Result<Self> {
2310 #[cfg(not(feature = "full"))]
2311 let attrs = Vec::new();
2312 #[cfg(feature = "full")]
2313 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002314
David Tolnay60291082018-08-28 09:54:49 -07002315 let (qself, path) = path::parsing::qpath(input, true)?;
2316
2317 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002318 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002319 qself: qself,
2320 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002321 })
David Tolnay60291082018-08-28 09:54:49 -07002322 }
Alex Crichton954046c2017-05-30 21:49:42 -07002323 }
David Tolnay42602292016-10-01 22:25:45 -07002324
Michael Layzell734adb42017-06-07 16:58:31 -04002325 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002326 impl Parse for Block {
2327 fn parse(input: ParseStream) -> Result<Self> {
2328 let content;
2329 Ok(Block {
2330 brace_token: braced!(content in input),
2331 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002332 })
David Tolnay60291082018-08-28 09:54:49 -07002333 }
Alex Crichton954046c2017-05-30 21:49:42 -07002334 }
David Tolnay939766a2016-09-23 23:48:12 -07002335
Michael Layzell734adb42017-06-07 16:58:31 -04002336 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002337 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002338 /// Parse the body of a block as zero or more statements, possibly
2339 /// including one trailing expression.
2340 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002341 /// *This function is available if Syn is built with the `"parsing"`
2342 /// feature.*
2343 ///
David Tolnay6b457252018-09-01 15:55:47 -07002344 /// # Example
2345 ///
David Tolnay95989db2019-01-01 15:05:57 -05002346 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002347 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002348 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002349 ///
2350 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002351 /// //
2352 /// // fn playground {
2353 /// // let mut x = 1;
2354 /// // x += 1;
2355 /// // println!("{}", x);
2356 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002357 /// struct MiniFunction {
2358 /// attrs: Vec<Attribute>,
2359 /// fn_token: Token![fn],
2360 /// name: Ident,
2361 /// brace_token: token::Brace,
2362 /// stmts: Vec<Stmt>,
2363 /// }
2364 ///
2365 /// impl Parse for MiniFunction {
2366 /// fn parse(input: ParseStream) -> Result<Self> {
2367 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2368 /// let fn_token: Token![fn] = input.parse()?;
2369 /// let name: Ident = input.parse()?;
2370 ///
2371 /// let content;
2372 /// let brace_token = braced!(content in input);
2373 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2374 /// let stmts = content.call(Block::parse_within)?;
2375 ///
2376 /// Ok(MiniFunction {
2377 /// attrs: {
2378 /// let mut attrs = outer_attrs;
2379 /// attrs.extend(inner_attrs);
2380 /// attrs
2381 /// },
2382 /// fn_token: fn_token,
2383 /// name: name,
2384 /// brace_token: brace_token,
2385 /// stmts: stmts,
2386 /// })
2387 /// }
2388 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002389 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002390 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002391 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002392 loop {
2393 while input.peek(Token![;]) {
2394 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002395 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002396 if input.is_empty() {
2397 break;
2398 }
2399 let s = parse_stmt(input, true)?;
2400 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2401 requires_terminator(s)
2402 } else {
2403 false
2404 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002405 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002406 if input.is_empty() {
2407 break;
2408 } else if requires_semicolon {
2409 return Err(input.error("unexpected token"));
2410 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002411 }
2412 Ok(stmts)
2413 }
Alex Crichton954046c2017-05-30 21:49:42 -07002414 }
2415
Michael Layzell734adb42017-06-07 16:58:31 -04002416 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002417 impl Parse for Stmt {
2418 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002419 parse_stmt(input, false)
2420 }
2421 }
David Tolnay939766a2016-09-23 23:48:12 -07002422
David Tolnaye532d6b2018-08-30 16:55:01 -07002423 #[cfg(feature = "full")]
2424 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07002425 // TODO: optimize using advance_to
David Tolnaye532d6b2018-08-30 16:55:01 -07002426 let ahead = input.fork();
2427 ahead.call(Attribute::parse_outer)?;
2428
David Tolnaye532d6b2018-08-30 16:55:01 -07002429 if {
2430 let ahead = ahead.fork();
2431 // Only parse braces here; paren and bracket will get parsed as
2432 // expression statements
2433 ahead.call(Path::parse_mod_style).is_ok()
2434 && ahead.parse::<Token![!]>().is_ok()
2435 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2436 } {
2437 stmt_mac(input)
2438 } else if ahead.peek(Token![let]) {
2439 stmt_local(input).map(Stmt::Local)
2440 } else if ahead.peek(Token![pub])
2441 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2442 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2443 || ahead.peek(Token![use])
2444 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2445 || ahead.peek(Token![const])
2446 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2447 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2448 || ahead.peek(Token![fn])
2449 || ahead.peek(Token![mod])
2450 || ahead.peek(Token![type])
2451 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2452 || ahead.peek(Token![struct])
2453 || ahead.peek(Token![enum])
2454 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2455 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2456 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002457 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002458 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2459 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002460 || ahead.peek(Token![macro])
2461 {
2462 input.parse().map(Stmt::Item)
2463 } else {
2464 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002465 }
Alex Crichton954046c2017-05-30 21:49:42 -07002466 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002467
Michael Layzell734adb42017-06-07 16:58:31 -04002468 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002469 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2470 let attrs = input.call(Attribute::parse_outer)?;
2471 let path = input.call(Path::parse_mod_style)?;
2472 let bang_token: Token![!] = input.parse()?;
2473 let ident: Option<Ident> = input.parse()?;
2474 let (delimiter, tts) = mac::parse_delimiter(input)?;
2475 let semi_token: Option<Token![;]> = input.parse()?;
2476
2477 Ok(Stmt::Item(Item::Macro(ItemMacro {
2478 attrs: attrs,
2479 ident: ident,
2480 mac: Macro {
2481 path: path,
2482 bang_token: bang_token,
2483 delimiter: delimiter,
2484 tts: tts,
2485 },
2486 semi_token: semi_token,
2487 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002488 }
David Tolnay84aa0752016-10-02 23:01:13 -07002489
Michael Layzell734adb42017-06-07 16:58:31 -04002490 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002491 fn stmt_local(input: ParseStream) -> Result<Local> {
2492 Ok(Local {
2493 attrs: input.call(Attribute::parse_outer)?,
2494 let_token: input.parse()?,
2495 pats: {
2496 let mut pats = Punctuated::new();
2497 let value: Pat = input.parse()?;
2498 pats.push_value(value);
2499 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2500 let punct = input.parse()?;
2501 pats.push_punct(punct);
2502 let value: Pat = input.parse()?;
2503 pats.push_value(value);
2504 }
2505 pats
2506 },
2507 ty: {
2508 if input.peek(Token![:]) {
2509 let colon_token: Token![:] = input.parse()?;
2510 let ty: Type = input.parse()?;
2511 Some((colon_token, Box::new(ty)))
2512 } else {
2513 None
2514 }
2515 },
2516 init: {
2517 if input.peek(Token![=]) {
2518 let eq_token: Token![=] = input.parse()?;
2519 let init: Expr = input.parse()?;
2520 Some((eq_token, Box::new(init)))
2521 } else {
2522 None
2523 }
2524 },
2525 semi_token: input.parse()?,
2526 })
2527 }
2528
2529 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002530 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002531 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002532 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002533
2534 attrs.extend(e.replace_attrs(Vec::new()));
2535 e.replace_attrs(attrs);
2536
2537 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002538 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002539 }
David Tolnay60291082018-08-28 09:54:49 -07002540
David Tolnayf00a2762018-08-30 17:22:22 -07002541 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002542 Ok(Stmt::Expr(e))
2543 } else {
2544 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002545 }
David Tolnay60291082018-08-28 09:54:49 -07002546 }
2547
2548 #[cfg(feature = "full")]
2549 impl Parse for Pat {
2550 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002551 let lookahead = input.lookahead1();
2552 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002553 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002554 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002555 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002556 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2557 pat_lit_or_range(input)
2558 } else if input.peek(Ident)
2559 && ({
2560 input.peek2(Token![::])
2561 || input.peek2(Token![!])
2562 || input.peek2(token::Brace)
2563 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002564 || input.peek2(Token![..])
2565 && !{
2566 let ahead = input.fork();
2567 ahead.parse::<Ident>()?;
2568 ahead.parse::<RangeLimits>()?;
2569 ahead.is_empty() || ahead.peek(Token![,])
2570 }
David Tolnay8d534b02018-09-02 09:46:05 -07002571 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002572 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002573 || input.peek(Token![::])
2574 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002575 || input.peek(Token![Self])
2576 || input.peek(Token![super])
2577 || input.peek(Token![extern])
2578 || input.peek(Token![crate])
2579 {
2580 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002581 } else if input.peek(Token![ref])
2582 || input.peek(Token![mut])
2583 || input.peek(Token![self])
2584 || input.peek(Ident)
2585 {
David Tolnay310b3262018-08-30 15:33:00 -07002586 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002587 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002588 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002589 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002590 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002591 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002592 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002593 } else {
2594 Err(lookahead.error())
2595 }
2596 }
2597 }
2598
2599 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002600 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2601 let (qself, path) = path::parsing::qpath(input, true)?;
2602
2603 if input.peek(Token![..]) {
2604 return pat_range(input, qself, path).map(Pat::Range);
2605 }
2606
2607 if qself.is_some() {
2608 return Ok(Pat::Path(PatPath {
2609 qself: qself,
2610 path: path,
2611 }));
2612 }
2613
2614 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2615 let mut contains_arguments = false;
2616 for segment in &path.segments {
2617 match segment.arguments {
2618 PathArguments::None => {}
2619 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2620 contains_arguments = true;
2621 }
2622 }
2623 }
2624
2625 if !contains_arguments {
2626 let bang_token: Token![!] = input.parse()?;
2627 let (delimiter, tts) = mac::parse_delimiter(input)?;
2628 return Ok(Pat::Macro(PatMacro {
2629 mac: Macro {
2630 path: path,
2631 bang_token: bang_token,
2632 delimiter: delimiter,
2633 tts: tts,
2634 },
2635 }));
2636 }
2637 }
2638
2639 if input.peek(token::Brace) {
2640 pat_struct(input, path).map(Pat::Struct)
2641 } else if input.peek(token::Paren) {
2642 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2643 } else if input.peek(Token![..]) {
2644 pat_range(input, qself, path).map(Pat::Range)
2645 } else {
2646 Ok(Pat::Path(PatPath {
2647 qself: qself,
2648 path: path,
2649 }))
2650 }
2651 }
2652
2653 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002654 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2655 Ok(PatWild {
2656 underscore_token: input.parse()?,
2657 })
Alex Crichton954046c2017-05-30 21:49:42 -07002658 }
2659
Michael Layzell734adb42017-06-07 16:58:31 -04002660 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002661 fn pat_box(input: ParseStream) -> Result<PatBox> {
2662 Ok(PatBox {
2663 box_token: input.parse()?,
2664 pat: input.parse()?,
2665 })
David Tolnay60291082018-08-28 09:54:49 -07002666 }
2667
2668 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002669 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2670 Ok(PatIdent {
2671 by_ref: input.parse()?,
2672 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002673 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002674 subpat: {
2675 if input.peek(Token![@]) {
2676 let at_token: Token![@] = input.parse()?;
2677 let subpat: Pat = input.parse()?;
2678 Some((at_token, Box::new(subpat)))
2679 } else {
2680 None
2681 }
2682 },
2683 })
David Tolnay60291082018-08-28 09:54:49 -07002684 }
2685
2686 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002687 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002688 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002689 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002690 pat: input.call(pat_tuple)?,
2691 })
2692 }
David Tolnay60291082018-08-28 09:54:49 -07002693
David Tolnay310b3262018-08-30 15:33:00 -07002694 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002695 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002696 let content;
2697 let brace_token = braced!(content in input);
2698
2699 let mut fields = Punctuated::new();
2700 while !content.is_empty() && !content.peek(Token![..]) {
2701 let value = content.call(field_pat)?;
2702 fields.push_value(value);
2703 if !content.peek(Token![,]) {
2704 break;
David Tolnay60291082018-08-28 09:54:49 -07002705 }
David Tolnay310b3262018-08-30 15:33:00 -07002706 let punct: Token![,] = content.parse()?;
2707 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002708 }
David Tolnay310b3262018-08-30 15:33:00 -07002709
2710 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2711 Some(content.parse()?)
2712 } else {
2713 None
2714 };
2715
2716 Ok(PatStruct {
2717 path: path,
2718 brace_token: brace_token,
2719 fields: fields,
2720 dot2_token: dot2_token,
2721 })
2722 }
2723
2724 #[cfg(feature = "full")]
2725 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2726 let boxed: Option<Token![box]> = input.parse()?;
2727 let by_ref: Option<Token![ref]> = input.parse()?;
2728 let mutability: Option<Token![mut]> = input.parse()?;
2729 let member: Member = input.parse()?;
2730
2731 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2732 || member.is_unnamed()
2733 {
2734 return Ok(FieldPat {
2735 attrs: Vec::new(),
2736 member: member,
2737 colon_token: input.parse()?,
2738 pat: input.parse()?,
2739 });
2740 }
2741
2742 let ident = match member {
2743 Member::Named(ident) => ident,
2744 Member::Unnamed(_) => unreachable!(),
2745 };
2746
2747 let mut pat = Pat::Ident(PatIdent {
2748 by_ref: by_ref,
2749 mutability: mutability,
2750 ident: ident.clone(),
2751 subpat: None,
2752 });
2753
2754 if let Some(boxed) = boxed {
2755 pat = Pat::Box(PatBox {
2756 pat: Box::new(pat),
2757 box_token: boxed,
2758 });
2759 }
2760
2761 Ok(FieldPat {
2762 member: Member::Named(ident),
2763 pat: Box::new(pat),
2764 attrs: Vec::new(),
2765 colon_token: None,
2766 })
Alex Crichton954046c2017-05-30 21:49:42 -07002767 }
2768
David Tolnay1501f7e2018-08-27 14:21:03 -07002769 impl Parse for Member {
2770 fn parse(input: ParseStream) -> Result<Self> {
2771 if input.peek(Ident) {
2772 input.parse().map(Member::Named)
2773 } else if input.peek(LitInt) {
2774 input.parse().map(Member::Unnamed)
2775 } else {
2776 Err(input.error("expected identifier or integer"))
2777 }
2778 }
David Tolnay85b69a42017-12-27 20:43:10 -05002779 }
2780
Bastien Oriveld29ea392018-10-16 23:50:16 +02002781 #[cfg(feature = "full")]
2782 impl Parse for Arm {
2783 fn parse(input: ParseStream) -> Result<Arm> {
2784 let requires_comma;
2785 Ok(Arm {
2786 attrs: input.call(Attribute::parse_outer)?,
2787 leading_vert: input.parse()?,
2788 pats: {
2789 let mut pats = Punctuated::new();
2790 let value: Pat = input.parse()?;
2791 pats.push_value(value);
2792 loop {
2793 if !input.peek(Token![|]) {
2794 break;
2795 }
2796 let punct = input.parse()?;
2797 pats.push_punct(punct);
2798 let value: Pat = input.parse()?;
2799 pats.push_value(value);
2800 }
2801 pats
2802 },
2803 guard: {
2804 if input.peek(Token![if]) {
2805 let if_token: Token![if] = input.parse()?;
2806 let guard: Expr = input.parse()?;
2807 Some((if_token, Box::new(guard)))
2808 } else {
2809 None
2810 }
2811 },
2812 fat_arrow_token: input.parse()?,
2813 body: {
2814 let body = input.call(expr_early)?;
2815 requires_comma = requires_terminator(&body);
2816 Box::new(body)
2817 },
2818 comma: {
2819 if requires_comma && !input.is_empty() {
2820 Some(input.parse()?)
2821 } else {
2822 input.parse()?
2823 }
2824 },
2825 })
2826 }
2827 }
2828
David Tolnay1501f7e2018-08-27 14:21:03 -07002829 impl Parse for Index {
2830 fn parse(input: ParseStream) -> Result<Self> {
2831 let lit: LitInt = input.parse()?;
2832 if let IntSuffix::None = lit.suffix() {
2833 Ok(Index {
2834 index: lit.value() as u32,
2835 span: lit.span(),
2836 })
2837 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002838 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002839 }
2840 }
David Tolnay85b69a42017-12-27 20:43:10 -05002841 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002842
Michael Layzell734adb42017-06-07 16:58:31 -04002843 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002844 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2845 Ok(PatRange {
2846 lo: Box::new(Expr::Path(ExprPath {
2847 attrs: Vec::new(),
2848 qself: qself,
2849 path: path,
2850 })),
2851 limits: input.parse()?,
2852 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002853 })
Alex Crichton954046c2017-05-30 21:49:42 -07002854 }
David Tolnay9636c052016-10-02 17:11:17 -07002855
Michael Layzell734adb42017-06-07 16:58:31 -04002856 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002857 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2858 let content;
2859 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002860
David Tolnay310b3262018-08-30 15:33:00 -07002861 let mut front = Punctuated::new();
2862 let mut dot2_token = None::<Token![..]>;
2863 let mut comma_token = None::<Token![,]>;
2864 loop {
2865 if content.is_empty() {
2866 break;
David Tolnay60291082018-08-28 09:54:49 -07002867 }
David Tolnay310b3262018-08-30 15:33:00 -07002868 if content.peek(Token![..]) {
2869 dot2_token = Some(content.parse()?);
2870 comma_token = content.parse()?;
2871 break;
David Tolnay60291082018-08-28 09:54:49 -07002872 }
David Tolnay310b3262018-08-30 15:33:00 -07002873 let value: Pat = content.parse()?;
2874 front.push_value(value);
2875 if content.is_empty() {
2876 break;
2877 }
2878 let punct = content.parse()?;
2879 front.push_punct(punct);
2880 }
2881
David Tolnayf5ebc192018-08-30 18:23:46 -07002882 let mut back = Punctuated::new();
2883 while !content.is_empty() {
2884 let value: Pat = content.parse()?;
2885 back.push_value(value);
2886 if content.is_empty() {
2887 break;
2888 }
2889 let punct = content.parse()?;
2890 back.push_punct(punct);
2891 }
David Tolnay310b3262018-08-30 15:33:00 -07002892
2893 Ok(PatTuple {
2894 paren_token: paren_token,
2895 front: front,
2896 dot2_token: dot2_token,
2897 comma_token: comma_token,
2898 back: back,
2899 })
2900 }
2901
2902 #[cfg(feature = "full")]
2903 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2904 Ok(PatRef {
2905 and_token: input.parse()?,
2906 mutability: input.parse()?,
2907 pat: input.parse()?,
2908 })
2909 }
2910
2911 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002912 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2913 let lo = input.call(pat_lit_expr)?;
2914 if input.peek(Token![..]) {
2915 Ok(Pat::Range(PatRange {
2916 lo: lo,
2917 limits: input.parse()?,
2918 hi: input.call(pat_lit_expr)?,
2919 }))
David Tolnay310b3262018-08-30 15:33:00 -07002920 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002921 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002922 }
2923 }
2924
2925 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002926 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2927 let neg: Option<Token![-]> = input.parse()?;
2928
2929 let lookahead = input.lookahead1();
2930 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002931 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002932 } else if lookahead.peek(Ident)
2933 || lookahead.peek(Token![::])
2934 || lookahead.peek(Token![<])
2935 || lookahead.peek(Token![self])
2936 || lookahead.peek(Token![Self])
2937 || lookahead.peek(Token![super])
2938 || lookahead.peek(Token![extern])
2939 || lookahead.peek(Token![crate])
2940 {
2941 Expr::Path(input.parse()?)
2942 } else {
2943 return Err(lookahead.error());
2944 };
2945
2946 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002947 Expr::Unary(ExprUnary {
2948 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002949 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002950 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002951 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002952 } else {
David Tolnay60291082018-08-28 09:54:49 -07002953 expr
2954 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002955 }
David Tolnay323279a2017-12-29 11:26:32 -05002956
2957 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002958 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2959 let content;
2960 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002961
David Tolnay310b3262018-08-30 15:33:00 -07002962 let mut front = Punctuated::new();
2963 let mut middle = None;
2964 loop {
2965 if content.is_empty() || content.peek(Token![..]) {
2966 break;
David Tolnay60291082018-08-28 09:54:49 -07002967 }
David Tolnay310b3262018-08-30 15:33:00 -07002968 let value: Pat = content.parse()?;
2969 if content.peek(Token![..]) {
2970 middle = Some(Box::new(value));
2971 break;
David Tolnay60291082018-08-28 09:54:49 -07002972 }
David Tolnay310b3262018-08-30 15:33:00 -07002973 front.push_value(value);
2974 if content.is_empty() {
2975 break;
2976 }
2977 let punct = content.parse()?;
2978 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002979 }
David Tolnay310b3262018-08-30 15:33:00 -07002980
2981 let dot2_token: Option<Token![..]> = content.parse()?;
2982 let mut comma_token = None::<Token![,]>;
2983 let mut back = Punctuated::new();
2984 if dot2_token.is_some() {
2985 comma_token = content.parse()?;
2986 if comma_token.is_some() {
2987 loop {
2988 if content.is_empty() {
2989 break;
2990 }
2991 let value: Pat = content.parse()?;
2992 back.push_value(value);
2993 if content.is_empty() {
2994 break;
2995 }
2996 let punct = content.parse()?;
2997 back.push_punct(punct);
2998 }
2999 }
3000 }
3001
3002 Ok(PatSlice {
3003 bracket_token: bracket_token,
3004 front: front,
3005 middle: middle,
3006 dot2_token: dot2_token,
3007 comma_token: comma_token,
3008 back: back,
3009 })
David Tolnay60291082018-08-28 09:54:49 -07003010 }
3011
3012 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003013 impl Member {
3014 fn is_named(&self) -> bool {
3015 match *self {
3016 Member::Named(_) => true,
3017 Member::Unnamed(_) => false,
3018 }
3019 }
David Tolnay60291082018-08-28 09:54:49 -07003020
3021 fn is_unnamed(&self) -> bool {
3022 match *self {
3023 Member::Named(_) => false,
3024 Member::Unnamed(_) => true,
3025 }
3026 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003027 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003028}
3029
David Tolnayf4bbbd92016-09-23 14:41:55 -07003030#[cfg(feature = "printing")]
3031mod printing {
3032 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003033
Alex Crichtona74a1c82018-05-16 10:20:44 -07003034 use proc_macro2::{Literal, TokenStream};
3035 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003036
David Tolnay64023912018-08-31 09:51:12 -07003037 #[cfg(feature = "full")]
3038 use attr::FilterAttrs;
3039 #[cfg(feature = "full")]
3040 use print::TokensOrDefault;
3041
David Tolnaybcf26022017-12-25 22:10:52 -05003042 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003043 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003044 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003045 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003046 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003047 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003048 e.to_tokens(tokens);
3049 });
3050 } else {
3051 e.to_tokens(tokens);
3052 }
3053 }
3054
David Tolnay8c91b882017-12-28 23:04:32 -05003055 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003056 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003057 tokens.append_all(attrs.outer());
3058 }
Michael Layzell734adb42017-06-07 16:58:31 -04003059
David Tolnayd997aef2018-07-21 18:42:31 -07003060 #[cfg(feature = "full")]
3061 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3062 tokens.append_all(attrs.inner());
3063 }
3064
David Tolnay8c91b882017-12-28 23:04:32 -05003065 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003066 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3067
3068 #[cfg(not(feature = "full"))]
3069 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003070
Michael Layzell734adb42017-06-07 16:58:31 -04003071 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003072 impl ToTokens for ExprBox {
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);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003075 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003076 self.expr.to_tokens(tokens);
3077 }
3078 }
3079
Michael Layzell734adb42017-06-07 16:58:31 -04003080 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003081 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003082 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003083 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003084 self.place.to_tokens(tokens);
3085 self.arrow_token.to_tokens(tokens);
3086 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003087 }
3088 }
3089
Michael Layzell734adb42017-06-07 16:58:31 -04003090 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003091 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003092 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003093 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003094 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003095 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003096 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003097 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003098 }
3099 }
3100
3101 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003102 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003103 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003104 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003105 self.paren_token.surround(tokens, |tokens| {
3106 self.args.to_tokens(tokens);
3107 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003108 }
3109 }
3110
Michael Layzell734adb42017-06-07 16:58:31 -04003111 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003112 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003113 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003114 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003115 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003116 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003117 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003118 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003119 self.paren_token.surround(tokens, |tokens| {
3120 self.args.to_tokens(tokens);
3121 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003122 }
3123 }
3124
Michael Layzell734adb42017-06-07 16:58:31 -04003125 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003126 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003127 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003128 self.colon2_token.to_tokens(tokens);
3129 self.lt_token.to_tokens(tokens);
3130 self.args.to_tokens(tokens);
3131 self.gt_token.to_tokens(tokens);
3132 }
3133 }
3134
3135 #[cfg(feature = "full")]
3136 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003137 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003138 match *self {
3139 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3140 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3141 }
3142 }
3143 }
3144
3145 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003146 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003147 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003148 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003149 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003150 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003151 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003152 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003153 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003154 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003155 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003156 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003157 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003158 }
3159 }
3160
3161 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003162 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003163 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003164 self.left.to_tokens(tokens);
3165 self.op.to_tokens(tokens);
3166 self.right.to_tokens(tokens);
3167 }
3168 }
3169
3170 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003171 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003172 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003173 self.op.to_tokens(tokens);
3174 self.expr.to_tokens(tokens);
3175 }
3176 }
3177
David Tolnay8c91b882017-12-28 23:04:32 -05003178 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003179 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003180 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003181 self.lit.to_tokens(tokens);
3182 }
3183 }
3184
Alex Crichton62a0a592017-05-22 13:58:53 -07003185 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003186 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003187 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003189 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003190 self.ty.to_tokens(tokens);
3191 }
3192 }
3193
David Tolnay0cf94f22017-12-28 23:46:26 -05003194 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003195 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003196 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003197 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003199 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003200 self.ty.to_tokens(tokens);
3201 }
3202 }
3203
Michael Layzell734adb42017-06-07 16:58:31 -04003204 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003205 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003206 if let Some((ref else_token, ref else_)) = *else_ {
3207 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003208
3209 // If we are not one of the valid expressions to exist in an else
3210 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003211 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003212 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003213 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003214 }
3215 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003216 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003217 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003218 });
3219 }
3220 }
3221 }
3222 }
3223
3224 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003225 impl ToTokens for ExprLet {
3226 fn to_tokens(&self, tokens: &mut TokenStream) {
3227 outer_attrs_to_tokens(&self.attrs, tokens);
3228 self.let_token.to_tokens(tokens);
3229 self.pats.to_tokens(tokens);
3230 self.eq_token.to_tokens(tokens);
3231 wrap_bare_struct(tokens, &self.expr);
3232 }
3233 }
3234
3235 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003236 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003237 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003238 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003239 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003240 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003241 self.then_branch.to_tokens(tokens);
3242 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003243 }
3244 }
3245
Michael Layzell734adb42017-06-07 16:58:31 -04003246 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003247 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003248 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003249 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003250 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003251 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003252 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003253 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003254 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003255 tokens.append_all(&self.body.stmts);
3256 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003257 }
3258 }
3259
Michael Layzell734adb42017-06-07 16:58:31 -04003260 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003261 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003262 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003263 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003264 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003265 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003266 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003267 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003268 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003269 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003270 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003271 tokens.append_all(&self.body.stmts);
3272 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003273 }
3274 }
3275
Michael Layzell734adb42017-06-07 16:58:31 -04003276 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003277 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003278 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003279 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003280 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003281 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003282 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003283 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003284 tokens.append_all(&self.body.stmts);
3285 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003286 }
3287 }
3288
Michael Layzell734adb42017-06-07 16:58:31 -04003289 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003290 impl ToTokens for ExprMatch {
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 Crichtonccbb45d2017-05-23 10:58:24 -07003293 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003294 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003295 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003296 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003297 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003298 arm.to_tokens(tokens);
3299 // Ensure that we have a comma after a non-block arm, except
3300 // for the last one.
3301 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003302 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003303 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003304 }
3305 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003306 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003307 }
3308 }
3309
Michael Layzell734adb42017-06-07 16:58:31 -04003310 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003311 impl ToTokens for ExprAsync {
3312 fn to_tokens(&self, tokens: &mut TokenStream) {
3313 outer_attrs_to_tokens(&self.attrs, tokens);
3314 self.async_token.to_tokens(tokens);
3315 self.capture.to_tokens(tokens);
3316 self.block.to_tokens(tokens);
3317 }
3318 }
3319
3320 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003321 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003322 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003323 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003324 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003325 self.block.to_tokens(tokens);
3326 }
3327 }
3328
Michael Layzell734adb42017-06-07 16:58:31 -04003329 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003330 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003331 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003332 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003333 self.yield_token.to_tokens(tokens);
3334 self.expr.to_tokens(tokens);
3335 }
3336 }
3337
3338 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003339 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003340 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003341 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003342 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003343 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003344 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003345 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003346 for input in self.inputs.pairs() {
3347 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003348 FnArg::Captured(ArgCaptured {
3349 ref pat,
3350 ty: Type::Infer(_),
3351 ..
3352 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003353 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003354 }
David Tolnay56080682018-01-06 14:01:52 -08003355 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003356 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003357 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003358 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003359 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003360 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003361 self.body.to_tokens(tokens);
3362 }
3363 }
3364
Michael Layzell734adb42017-06-07 16:58:31 -04003365 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003366 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003367 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003368 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003369 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003370 self.block.brace_token.surround(tokens, |tokens| {
3371 inner_attrs_to_tokens(&self.attrs, tokens);
3372 tokens.append_all(&self.block.stmts);
3373 });
Nika Layzell640832a2017-12-04 13:37:09 -05003374 }
3375 }
3376
3377 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003378 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003379 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003380 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003381 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003382 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003383 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003384 tokens.append_all(&self.block.stmts);
3385 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003386 }
3387 }
3388
Michael Layzell734adb42017-06-07 16:58:31 -04003389 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003390 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003391 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003392 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003393 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003394 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003395 self.right.to_tokens(tokens);
3396 }
3397 }
3398
Michael Layzell734adb42017-06-07 16:58:31 -04003399 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003401 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003402 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003403 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003404 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003405 self.right.to_tokens(tokens);
3406 }
3407 }
3408
3409 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003410 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003411 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003412 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003413 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003414 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003415 }
3416 }
3417
David Tolnay85b69a42017-12-27 20:43:10 -05003418 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003419 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003420 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003421 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003422 Member::Unnamed(ref index) => index.to_tokens(tokens),
3423 }
3424 }
3425 }
3426
David Tolnay85b69a42017-12-27 20:43:10 -05003427 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003428 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003429 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3430 lit.set_span(self.span);
3431 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003432 }
3433 }
3434
3435 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003436 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003437 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003438 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003439 self.bracket_token.surround(tokens, |tokens| {
3440 self.index.to_tokens(tokens);
3441 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003442 }
3443 }
3444
Michael Layzell734adb42017-06-07 16:58:31 -04003445 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003446 impl ToTokens for ExprRange {
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 Crichton62a0a592017-05-22 13:58:53 -07003449 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003450 match self.limits {
3451 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3452 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3453 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003454 self.to.to_tokens(tokens);
3455 }
3456 }
3457
3458 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003459 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003460 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003461 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003462 }
3463 }
3464
Michael Layzell734adb42017-06-07 16:58:31 -04003465 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003466 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003467 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003468 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003469 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003470 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003471 self.expr.to_tokens(tokens);
3472 }
3473 }
3474
Michael Layzell734adb42017-06-07 16:58:31 -04003475 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003476 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003477 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003478 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003479 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003480 self.label.to_tokens(tokens);
3481 self.expr.to_tokens(tokens);
3482 }
3483 }
3484
Michael Layzell734adb42017-06-07 16:58:31 -04003485 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003487 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003488 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003489 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003490 self.label.to_tokens(tokens);
3491 }
3492 }
3493
Michael Layzell734adb42017-06-07 16:58:31 -04003494 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003495 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003496 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003497 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003498 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003499 self.expr.to_tokens(tokens);
3500 }
3501 }
3502
Michael Layzell734adb42017-06-07 16:58:31 -04003503 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003504 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003505 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003506 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003507 self.mac.to_tokens(tokens);
3508 }
3509 }
3510
3511 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003512 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003513 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003514 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003515 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003516 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003517 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003518 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003519 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003520 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003521 self.rest.to_tokens(tokens);
3522 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003523 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003524 }
3525 }
3526
Michael Layzell734adb42017-06-07 16:58:31 -04003527 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003528 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003529 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003530 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003531 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003532 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003533 self.expr.to_tokens(tokens);
3534 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003535 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003536 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003537 }
3538 }
3539
David Tolnaye98775f2017-12-28 23:17:00 -05003540 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003541 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003542 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003543 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003544 self.group_token.surround(tokens, |tokens| {
3545 self.expr.to_tokens(tokens);
3546 });
3547 }
3548 }
3549
Alex Crichton62a0a592017-05-22 13:58:53 -07003550 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003551 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003552 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003553 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003554 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003555 self.expr.to_tokens(tokens);
3556 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003557 }
3558 }
3559
Michael Layzell734adb42017-06-07 16:58:31 -04003560 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003561 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003562 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003563 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003564 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003565 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003566 }
3567 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003568
David Tolnay2ae520a2017-12-29 11:19:50 -05003569 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003570 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003571 self.tts.to_tokens(tokens);
3572 }
3573 }
3574
Michael Layzell734adb42017-06-07 16:58:31 -04003575 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003576 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003577 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003578 self.name.to_tokens(tokens);
3579 self.colon_token.to_tokens(tokens);
3580 }
3581 }
3582
3583 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003584 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003585 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003586 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003587 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003588 if let Some(ref colon_token) = self.colon_token {
3589 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003590 self.expr.to_tokens(tokens);
3591 }
David Tolnay055a7042016-10-02 19:23:54 -07003592 }
3593 }
3594
Michael Layzell734adb42017-06-07 16:58:31 -04003595 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003596 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003597 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003598 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003599 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003600 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003601 if let Some((ref if_token, ref guard)) = self.guard {
3602 if_token.to_tokens(tokens);
3603 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003604 }
David Tolnaydfb91432018-03-31 19:19:44 +02003605 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003606 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003607 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003608 }
3609 }
3610
Michael Layzell734adb42017-06-07 16:58:31 -04003611 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003612 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003613 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003614 self.underscore_token.to_tokens(tokens);
3615 }
3616 }
3617
Michael Layzell734adb42017-06-07 16:58:31 -04003618 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003619 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003620 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003621 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003622 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003623 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003624 if let Some((ref at_token, ref subpat)) = self.subpat {
3625 at_token.to_tokens(tokens);
3626 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003627 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003628 }
3629 }
3630
Michael Layzell734adb42017-06-07 16:58:31 -04003631 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003632 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003633 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003634 self.path.to_tokens(tokens);
3635 self.brace_token.surround(tokens, |tokens| {
3636 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003637 // NOTE: We need a comma before the dot2 token if it is present.
3638 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003639 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003640 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003641 self.dot2_token.to_tokens(tokens);
3642 });
3643 }
3644 }
3645
Michael Layzell734adb42017-06-07 16:58:31 -04003646 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003647 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003648 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003649 self.path.to_tokens(tokens);
3650 self.pat.to_tokens(tokens);
3651 }
3652 }
3653
Michael Layzell734adb42017-06-07 16:58:31 -04003654 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003655 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003656 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003657 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003658 }
3659 }
3660
Michael Layzell734adb42017-06-07 16:58:31 -04003661 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003663 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003664 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003665 self.front.to_tokens(tokens);
3666 if let Some(ref dot2_token) = self.dot2_token {
3667 if !self.front.empty_or_trailing() {
3668 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003669 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003670 }
David Tolnay41871922017-12-29 01:53:45 -05003671 dot2_token.to_tokens(tokens);
3672 self.comma_token.to_tokens(tokens);
3673 if self.comma_token.is_none() && !self.back.is_empty() {
3674 // Ensure there is a comma after the .. token.
3675 <Token![,]>::default().to_tokens(tokens);
3676 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003677 }
David Tolnay41871922017-12-29 01:53:45 -05003678 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003679 });
3680 }
3681 }
3682
Michael Layzell734adb42017-06-07 16:58:31 -04003683 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003684 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003685 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003686 self.box_token.to_tokens(tokens);
3687 self.pat.to_tokens(tokens);
3688 }
3689 }
3690
Michael Layzell734adb42017-06-07 16:58:31 -04003691 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003692 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003693 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003694 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003695 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003696 self.pat.to_tokens(tokens);
3697 }
3698 }
3699
Michael Layzell734adb42017-06-07 16:58:31 -04003700 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003702 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003703 self.expr.to_tokens(tokens);
3704 }
3705 }
3706
Michael Layzell734adb42017-06-07 16:58:31 -04003707 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003709 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003710 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003711 match self.limits {
3712 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
Jeb Rosen918e8de2019-06-19 18:42:43 -07003713 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003714 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003715 self.hi.to_tokens(tokens);
3716 }
3717 }
3718
Michael Layzell734adb42017-06-07 16:58:31 -04003719 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003720 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003721 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003722 self.bracket_token.surround(tokens, |tokens| {
3723 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003724
3725 // If we need a comma before the middle or standalone .. token,
3726 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003727 if !self.front.empty_or_trailing()
3728 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003729 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003730 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003731 }
3732
3733 // If we have an identifier, we always need a .. token.
3734 if self.middle.is_some() {
3735 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003736 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003737 } else if self.dot2_token.is_some() {
3738 self.dot2_token.to_tokens(tokens);
3739 }
3740
3741 // Make sure we have a comma before the back half.
3742 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003743 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003744 self.back.to_tokens(tokens);
3745 } else {
3746 self.comma_token.to_tokens(tokens);
3747 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003748 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003749 }
3750 }
3751
Michael Layzell734adb42017-06-07 16:58:31 -04003752 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003753 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003754 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003755 self.mac.to_tokens(tokens);
3756 }
3757 }
3758
3759 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003760 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003761 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003762 self.tts.to_tokens(tokens);
3763 }
3764 }
3765
3766 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003767 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003768 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003769 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003770 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003771 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003772 }
3773 self.pat.to_tokens(tokens);
3774 }
3775 }
3776
Michael Layzell734adb42017-06-07 16:58:31 -04003777 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003778 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003779 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003780 self.brace_token.surround(tokens, |tokens| {
3781 tokens.append_all(&self.stmts);
3782 });
David Tolnay42602292016-10-01 22:25:45 -07003783 }
3784 }
3785
Michael Layzell734adb42017-06-07 16:58:31 -04003786 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003787 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003788 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003789 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003790 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003791 Stmt::Item(ref item) => item.to_tokens(tokens),
3792 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003793 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003794 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003795 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003796 }
David Tolnay42602292016-10-01 22:25:45 -07003797 }
3798 }
3799 }
David Tolnay191e0582016-10-02 18:31:09 -07003800
Michael Layzell734adb42017-06-07 16:58:31 -04003801 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003802 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003803 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003804 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003805 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003806 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003807 if let Some((ref colon_token, ref ty)) = self.ty {
3808 colon_token.to_tokens(tokens);
3809 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003810 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003811 if let Some((ref eq_token, ref init)) = self.init {
3812 eq_token.to_tokens(tokens);
3813 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003814 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003815 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003816 }
3817 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003818}