blob: 7f43fb96e4574d39941082b92650d81115d2e458 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -070014#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -050015use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
David Tolnay9c119122018-09-01 18:47:02 -070044 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080045 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070058 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
59 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080060 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnay9c119122018-09-01 18:47:02 -0700219 /// A `let` guard: `let Some(x) = opt`.
220 ///
221 /// *This type is available if Syn is built with the `"full"` feature.*
222 pub Let(ExprLet #full {
223 pub attrs: Vec<Attribute>,
224 pub let_token: Token![let],
225 pub pats: Punctuated<Pat, Token![|]>,
226 pub eq_token: Token![=],
227 pub expr: Box<Expr>,
228 }),
229
David Tolnaya454c8f2018-01-07 01:01:10 -0800230 /// An `if` expression with an optional `else` block: `if expr { ... }
231 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 ///
David Tolnay9c119122018-09-01 18:47:02 -0700233 /// The `else` branch expression may only be an `If` or `Block`
234 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800235 ///
236 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400237 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500238 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500239 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700240 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500241 pub then_branch: Block,
242 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500244
David Tolnaya454c8f2018-01-07 01:01:10 -0800245 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800246 ///
247 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400248 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500249 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500250 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800251 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500252 pub cond: Box<Expr>,
253 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700254 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500255
David Tolnaya454c8f2018-01-07 01:01:10 -0800256 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800257 ///
258 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400259 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500260 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500261 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500262 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700263 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500264 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
266 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500268
David Tolnaya454c8f2018-01-07 01:01:10 -0800269 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800270 ///
271 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400272 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500273 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500274 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500275 pub loop_token: Token![loop],
276 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700277 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500278
David Tolnaya454c8f2018-01-07 01:01:10 -0800279 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800280 ///
281 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400282 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500283 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800284 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700285 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500286 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700287 pub arms: Vec<Arm>,
288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900295 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200296 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500297 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800298 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500299 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800300 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500301 pub output: ReturnType,
302 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700303 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500304
David Tolnaya454c8f2018-01-07 01:01:10 -0800305 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800306 ///
307 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500308 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500309 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500310 pub unsafe_token: Token![unsafe],
311 pub block: Block,
312 }),
313
David Tolnaya454c8f2018-01-07 01:01:10 -0800314 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800315 ///
316 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400317 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500318 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400319 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub block: Block,
321 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800324 ///
325 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400326 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500327 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700328 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800329 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500330 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700331 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500332
David Tolnaya454c8f2018-01-07 01:01:10 -0800333 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800334 ///
335 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400336 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500337 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500339 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub right: Box<Expr>,
341 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500342
David Tolnaya454c8f2018-01-07 01:01:10 -0800343 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500344 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700347 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500349 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500351 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnay05658502018-01-07 09:56:37 -0800354 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"derive"` or
357 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700358 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500359 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700360 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500361 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500362 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700363 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500364
David Tolnaya454c8f2018-01-07 01:01:10 -0800365 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400368 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700370 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700371 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500372 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700374
David Tolnaya454c8f2018-01-07 01:01:10 -0800375 /// A path like `std::mem::replace` possibly containing generic
376 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700377 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800379 ///
380 /// *This type is available if Syn is built with the `"derive"` or
381 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700382 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 pub qself: Option<QSelf>,
385 pub path: Path,
386 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700387
David Tolnaya454c8f2018-01-07 01:01:10 -0800388 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800389 ///
390 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200391 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500392 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800393 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500394 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700395 pub expr: Box<Expr>,
396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `break`, with an optional label to break and an optional
399 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400402 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500403 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700405 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700406 pub expr: Option<Box<Expr>>,
407 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400412 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500415 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500417
David Tolnaya454c8f2018-01-07 01:01:10 -0800418 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500421 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800423 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500424 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700425 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700426
David Tolnaya454c8f2018-01-07 01:01:10 -0800427 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800428 ///
429 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500430 pub Macro(ExprMacro #full {
431 pub attrs: Vec<Attribute>,
432 pub mac: Macro,
433 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700434
David Tolnaya454c8f2018-01-07 01:01:10 -0800435 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800437 /// The `rest` provides the value of the remaining fields as in `S { a:
438 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800439 ///
440 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400441 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500442 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700443 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500444 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500445 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500446 pub dot2_token: Option<Token![..]>,
447 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700449
David Tolnaya454c8f2018-01-07 01:01:10 -0800450 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800451 ///
452 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400453 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500454 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500455 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700456 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500457 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800458 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700459 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700460
David Tolnaya454c8f2018-01-07 01:01:10 -0800461 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800462 ///
463 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800464 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500465 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500466 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700469
David Tolnaya454c8f2018-01-07 01:01:10 -0800470 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400471 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800472 /// This variant is important for faithfully representing the precedence
473 /// of expressions and is related to `None`-delimited spans in a
474 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800475 ///
476 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500477 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500478 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500479 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500480 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400481 }),
482
David Tolnaya454c8f2018-01-07 01:01:10 -0800483 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800484 ///
485 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400486 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500487 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800489 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700490 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700491
David Tolnay02a9c6f2018-08-24 18:58:45 -0400492 /// An async block: `async { ... }`.
493 ///
494 /// *This type is available if Syn is built with the `"full"` feature.*
495 pub Async(ExprAsync #full {
496 pub attrs: Vec<Attribute>,
497 pub async_token: Token![async],
498 pub capture: Option<Token![move]>,
499 pub block: Block,
500 }),
501
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400502 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800503 ///
504 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400505 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500506 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400507 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700508 pub block: Block,
509 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700510
David Tolnaya454c8f2018-01-07 01:01:10 -0800511 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800512 ///
513 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700514 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500515 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800516 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700517 pub expr: Option<Box<Expr>>,
518 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500519
David Tolnaya454c8f2018-01-07 01:01:10 -0800520 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800521 ///
522 /// *This type is available if Syn is built with the `"derive"` or
523 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500524 pub Verbatim(ExprVerbatim #manual_extra_traits {
525 pub tts: TokenStream,
526 }),
527 }
528}
529
530#[cfg(feature = "extra-traits")]
531impl Eq for ExprVerbatim {}
532
533#[cfg(feature = "extra-traits")]
534impl PartialEq for ExprVerbatim {
535 fn eq(&self, other: &Self) -> bool {
536 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
537 }
538}
539
540#[cfg(feature = "extra-traits")]
541impl Hash for ExprVerbatim {
542 fn hash<H>(&self, state: &mut H)
543 where
544 H: Hasher,
545 {
546 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700547 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700548}
549
David Tolnay8c91b882017-12-28 23:04:32 -0500550impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700551 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700552 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500553 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800554 Expr::Box(ExprBox { ref mut attrs, .. })
555 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
556 | Expr::Array(ExprArray { ref mut attrs, .. })
557 | Expr::Call(ExprCall { ref mut attrs, .. })
558 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
559 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
560 | Expr::Binary(ExprBinary { ref mut attrs, .. })
561 | Expr::Unary(ExprUnary { ref mut attrs, .. })
562 | Expr::Lit(ExprLit { ref mut attrs, .. })
563 | Expr::Cast(ExprCast { ref mut attrs, .. })
564 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700565 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800566 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800567 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800568 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
569 | Expr::Loop(ExprLoop { ref mut attrs, .. })
570 | Expr::Match(ExprMatch { ref mut attrs, .. })
571 | Expr::Closure(ExprClosure { ref mut attrs, .. })
572 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
573 | Expr::Block(ExprBlock { ref mut attrs, .. })
574 | Expr::Assign(ExprAssign { ref mut attrs, .. })
575 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
576 | Expr::Field(ExprField { ref mut attrs, .. })
577 | Expr::Index(ExprIndex { ref mut attrs, .. })
578 | Expr::Range(ExprRange { ref mut attrs, .. })
579 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200580 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800581 | Expr::Break(ExprBreak { ref mut attrs, .. })
582 | Expr::Continue(ExprContinue { ref mut attrs, .. })
583 | Expr::Return(ExprReturn { ref mut attrs, .. })
584 | Expr::Macro(ExprMacro { ref mut attrs, .. })
585 | Expr::Struct(ExprStruct { ref mut attrs, .. })
586 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
587 | Expr::Paren(ExprParen { ref mut attrs, .. })
588 | Expr::Group(ExprGroup { ref mut attrs, .. })
589 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400590 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400591 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800592 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700593 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500594 }
595 }
596}
597
David Tolnay85b69a42017-12-27 20:43:10 -0500598ast_enum! {
599 /// A struct or tuple struct field accessed in a struct literal or field
600 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800601 ///
602 /// *This type is available if Syn is built with the `"derive"` or `"full"`
603 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500604 pub enum Member {
605 /// A named field like `self.x`.
606 Named(Ident),
607 /// An unnamed field like `self.0`.
608 Unnamed(Index),
609 }
610}
611
David Tolnay85b69a42017-12-27 20:43:10 -0500612ast_struct! {
613 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800614 ///
615 /// *This type is available if Syn is built with the `"derive"` or `"full"`
616 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500617 pub struct Index #manual_extra_traits {
618 pub index: u32,
619 pub span: Span,
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623impl From<usize> for Index {
624 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700625 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500626 Index {
627 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700628 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500629 }
630 }
631}
632
633#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500634impl Eq for Index {}
635
David Tolnay14982012017-12-29 00:49:51 -0500636#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500637impl PartialEq for Index {
638 fn eq(&self, other: &Self) -> bool {
639 self.index == other.index
640 }
641}
642
David Tolnay14982012017-12-29 00:49:51 -0500643#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500644impl Hash for Index {
645 fn hash<H: Hasher>(&self, state: &mut H) {
646 self.index.hash(state);
647 }
648}
649
650#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700651ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// The `::<>` explicit type parameters passed to a method call:
653 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800654 ///
655 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500656 pub struct MethodTurbofish {
657 pub colon2_token: Token![::],
658 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500659 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500660 pub gt_token: Token![>],
661 }
662}
663
664#[cfg(feature = "full")]
665ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800666 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800667 ///
668 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500669 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800670 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500671 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800672 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500673 ///
674 /// NOTE: Identity expressions are represented as Type arguments, as
675 /// they are indistinguishable syntactically.
676 Const(Expr),
677 }
678}
679
680#[cfg(feature = "full")]
681ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700682 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800683 ///
684 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700685 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500686 /// Attributes tagged on the field.
687 pub attrs: Vec<Attribute>,
688
689 /// Name or index of the field.
690 pub member: Member,
691
David Tolnay5d7098a2017-12-29 01:35:24 -0500692 /// The colon in `Struct { x: x }`. If written in shorthand like
693 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500694 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500695
Alex Crichton62a0a592017-05-22 13:58:53 -0700696 /// Value of the field.
697 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700698 }
David Tolnay055a7042016-10-02 19:23:54 -0700699}
700
Michael Layzell734adb42017-06-07 16:58:31 -0400701#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700702ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800703 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800704 ///
705 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500706 pub struct Label {
707 pub name: Lifetime,
708 pub colon_token: Token![:],
709 }
710}
711
712#[cfg(feature = "full")]
713ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800714 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800715 ///
716 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700717 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500718 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700719 /// Statements in a block
720 pub stmts: Vec<Stmt>,
721 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700722}
723
Michael Layzell734adb42017-06-07 16:58:31 -0400724#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700725ast_enum! {
726 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700729 pub enum Stmt {
730 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800731 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700732
Alex Crichton62a0a592017-05-22 13:58:53 -0700733 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800734 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700735
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800737 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700738
David Tolnaya454c8f2018-01-07 01:01:10 -0800739 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800740 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700742}
743
Michael Layzell734adb42017-06-07 16:58:31 -0400744#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700745ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800746 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800747 ///
748 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700749 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500750 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800751 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200752 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500753 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500754 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500755 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700756 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700757}
758
Michael Layzell734adb42017-06-07 16:58:31 -0400759#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700760ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800761 /// A pattern in a local binding, function signature, match expression, or
762 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800763 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800764 /// *This type is available if Syn is built with the `"full"` feature.*
765 ///
David Tolnay614a0142018-01-07 10:25:43 -0800766 /// # Syntax tree enum
767 ///
768 /// This type is a [syntax tree enum].
769 ///
770 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700771 // Clippy false positive
772 // https://github.com/Manishearth/rust-clippy/issues/1241
773 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
774 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800775 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800776 ///
777 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700778 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800779 pub underscore_token: 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 pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
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 Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500786 pub by_ref: Option<Token![ref]>,
787 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700788 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500789 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700790 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700791
David Tolnaya454c8f2018-01-07 01:01:10 -0800792 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800793 ///
794 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700795 pub Struct(PatStruct {
796 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500797 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500798 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800799 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700800 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700801
David Tolnaya454c8f2018-01-07 01:01:10 -0800802 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800803 ///
804 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700805 pub TupleStruct(PatTupleStruct {
806 pub path: Path,
807 pub pat: PatTuple,
808 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700809
David Tolnaya454c8f2018-01-07 01:01:10 -0800810 /// A path pattern like `Color::Red`, optionally qualified with a
811 /// self-type.
812 ///
813 /// Unquailfied path patterns can legally refer to variants, structs,
814 /// constants or associated constants. Quailfied path patterns like
815 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
816 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800817 ///
818 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700819 pub Path(PatPath {
820 pub qself: Option<QSelf>,
821 pub path: Path,
822 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700823
David Tolnaya454c8f2018-01-07 01:01:10 -0800824 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800825 ///
826 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500828 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500829 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500830 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500831 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500832 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700833 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800834
835 /// A box pattern: `box v`.
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 Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800839 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500840 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700841 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800842
843 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800844 ///
845 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800847 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500848 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500849 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700850 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800851
852 /// A literal pattern: `0`.
853 ///
854 /// This holds an `Expr` rather than a `Lit` because negative numbers
855 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800856 ///
857 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700858 pub Lit(PatLit {
859 pub expr: Box<Expr>,
860 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800861
862 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800863 ///
864 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 pub Range(PatRange {
866 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700867 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500868 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700869 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800870
871 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800872 ///
873 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700874 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500875 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500876 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700877 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500878 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500879 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500880 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700881 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800882
883 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800884 ///
885 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500886 pub Macro(PatMacro {
887 pub mac: Macro,
888 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800889
890 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800891 ///
892 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500893 pub Verbatim(PatVerbatim #manual_extra_traits {
894 pub tts: TokenStream,
895 }),
896 }
897}
898
David Tolnayc43b44e2017-12-30 23:55:54 -0500899#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500900impl Eq for PatVerbatim {}
901
David Tolnayc43b44e2017-12-30 23:55:54 -0500902#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500903impl PartialEq for PatVerbatim {
904 fn eq(&self, other: &Self) -> bool {
905 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
906 }
907}
908
David Tolnayc43b44e2017-12-30 23:55:54 -0500909#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500910impl Hash for PatVerbatim {
911 fn hash<H>(&self, state: &mut H)
912 where
913 H: Hasher,
914 {
915 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700916 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700917}
918
Michael Layzell734adb42017-06-07 16:58:31 -0400919#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700920ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800921 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700922 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800923 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700924 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500925 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800926 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500927 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700928 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800929 /// 0...10 => {
930 /// return true;
931 /// }
932 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500933 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700934 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800935 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500936 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700937 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800938 ///
939 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700940 pub struct Arm {
941 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200942 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500943 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500944 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200945 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800947 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700948 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700949}
950
Michael Layzell734adb42017-06-07 16:58:31 -0400951#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700952ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800954 ///
955 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700956 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700957 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800958 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800959 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800960 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800961 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700962 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700963}
964
Michael Layzell734adb42017-06-07 16:58:31 -0400965#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700966ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800967 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700968 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800969 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
970 /// 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 -0800971 ///
972 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700973 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500974 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500975 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500976 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700977 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700978 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700979}
980
Michael Layzell3936ceb2017-07-08 00:28:36 -0400981#[cfg(any(feature = "parsing", feature = "printing"))]
982#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700983fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700984 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500985 match *expr {
986 Expr::Unsafe(..)
987 | Expr::Block(..)
988 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500989 | Expr::Match(..)
990 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500991 | Expr::Loop(..)
992 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400993 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400994 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700995 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400996 }
997}
998
David Tolnayb9c8e322016-09-23 20:48:37 -0700999#[cfg(feature = "parsing")]
1000pub mod parsing {
1001 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -07001002
Michael Layzell734adb42017-06-07 16:58:31 -04001003 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -07001004 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -07001005 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -07001006 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001007
David Tolnaybcf26022017-12-25 22:10:52 -05001008 // When we're parsing expressions which occur before blocks, like in an if
1009 // statement's condition, we cannot parse a struct literal.
1010 //
1011 // Struct literals are ambiguous in certain positions
1012 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001013 #[derive(Copy, Clone)]
1014 pub struct AllowStruct(bool);
1015
David Tolnay01218d12018-08-29 18:13:07 -07001016 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1017 enum Precedence {
1018 Any,
1019 Assign,
1020 Placement,
1021 Range,
1022 Or,
1023 And,
1024 Compare,
1025 BitOr,
1026 BitXor,
1027 BitAnd,
1028 Shift,
1029 Arithmetic,
1030 Term,
1031 Cast,
1032 }
1033
1034 impl Precedence {
1035 fn of(op: &BinOp) -> Self {
1036 match *op {
1037 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1038 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1039 BinOp::And(_) => Precedence::And,
1040 BinOp::Or(_) => Precedence::Or,
1041 BinOp::BitXor(_) => Precedence::BitXor,
1042 BinOp::BitAnd(_) => Precedence::BitAnd,
1043 BinOp::BitOr(_) => Precedence::BitOr,
1044 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001045 BinOp::Eq(_)
1046 | BinOp::Lt(_)
1047 | BinOp::Le(_)
1048 | BinOp::Ne(_)
1049 | BinOp::Ge(_)
1050 | BinOp::Gt(_) => Precedence::Compare,
1051 BinOp::AddEq(_)
1052 | BinOp::SubEq(_)
1053 | BinOp::MulEq(_)
1054 | BinOp::DivEq(_)
1055 | BinOp::RemEq(_)
1056 | BinOp::BitXorEq(_)
1057 | BinOp::BitAndEq(_)
1058 | BinOp::BitOrEq(_)
1059 | BinOp::ShlEq(_)
1060 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001061 }
1062 }
1063 }
1064
David Tolnay9389c382018-08-27 09:13:37 -07001065 impl Parse for Expr {
1066 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001067 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001068 }
1069 }
1070
Michael Layzell734adb42017-06-07 16:58:31 -04001071 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001072 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001073 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001074 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001075
David Tolnay01218d12018-08-29 18:13:07 -07001076 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001077 fn parse_expr(
1078 input: ParseStream,
1079 mut lhs: Expr,
1080 allow_struct: AllowStruct,
1081 base: Precedence,
1082 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001083 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001084 if input
1085 .fork()
1086 .parse::<BinOp>()
1087 .ok()
1088 .map_or(false, |op| Precedence::of(&op) >= base)
1089 {
David Tolnay01218d12018-08-29 18:13:07 -07001090 let op: BinOp = input.parse()?;
1091 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001092 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001093 loop {
1094 let next = peek_precedence(input);
1095 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001096 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001097 } else {
1098 break;
1099 }
1100 }
David Tolnay90276252018-08-31 10:50:08 -07001101 lhs = if precedence == Precedence::Assign {
1102 Expr::AssignOp(ExprAssignOp {
1103 attrs: Vec::new(),
1104 left: Box::new(lhs),
1105 op: op,
1106 right: Box::new(rhs),
1107 })
1108 } else {
1109 Expr::Binary(ExprBinary {
1110 attrs: Vec::new(),
1111 left: Box::new(lhs),
1112 op: op,
1113 right: Box::new(rhs),
1114 })
1115 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001116 } else if Precedence::Assign >= base
1117 && input.peek(Token![=])
1118 && !input.peek(Token![==])
1119 && !input.peek(Token![=>])
1120 {
David Tolnay01218d12018-08-29 18:13:07 -07001121 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001122 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001123 loop {
1124 let next = peek_precedence(input);
1125 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001126 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001127 } else {
1128 break;
1129 }
1130 }
1131 lhs = Expr::Assign(ExprAssign {
1132 attrs: Vec::new(),
1133 left: Box::new(lhs),
1134 eq_token: eq_token,
1135 right: Box::new(rhs),
1136 });
1137 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1138 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001139 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001140 loop {
1141 let next = peek_precedence(input);
1142 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001143 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001144 } else {
1145 break;
1146 }
1147 }
1148 lhs = Expr::InPlace(ExprInPlace {
1149 attrs: Vec::new(),
1150 place: Box::new(lhs),
1151 arrow_token: arrow_token,
1152 value: Box::new(rhs),
1153 });
1154 } else if Precedence::Range >= base && input.peek(Token![..]) {
1155 let limits: RangeLimits = input.parse()?;
1156 let rhs = if input.is_empty()
1157 || input.peek(Token![,])
1158 || input.peek(Token![;])
1159 || !allow_struct.0 && input.peek(token::Brace)
1160 {
1161 None
1162 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001163 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001164 loop {
1165 let next = peek_precedence(input);
1166 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001167 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001168 } else {
1169 break;
1170 }
1171 }
1172 Some(rhs)
1173 };
1174 lhs = Expr::Range(ExprRange {
1175 attrs: Vec::new(),
1176 from: Some(Box::new(lhs)),
1177 limits: limits,
1178 to: rhs.map(Box::new),
1179 });
1180 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1181 let as_token: Token![as] = input.parse()?;
1182 let ty = input.call(Type::without_plus)?;
1183 lhs = Expr::Cast(ExprCast {
1184 attrs: Vec::new(),
1185 expr: Box::new(lhs),
1186 as_token: as_token,
1187 ty: Box::new(ty),
1188 });
1189 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1190 let colon_token: Token![:] = input.parse()?;
1191 let ty = input.call(Type::without_plus)?;
1192 lhs = Expr::Type(ExprType {
1193 attrs: Vec::new(),
1194 expr: Box::new(lhs),
1195 colon_token: colon_token,
1196 ty: Box::new(ty),
1197 });
1198 } else {
1199 break;
1200 }
1201 }
1202 Ok(lhs)
1203 }
1204
David Tolnay3e541292018-08-30 11:42:15 -07001205 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001206 fn parse_expr(
1207 input: ParseStream,
1208 mut lhs: Expr,
1209 allow_struct: AllowStruct,
1210 base: Precedence,
1211 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001212 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001213 if input
1214 .fork()
1215 .parse::<BinOp>()
1216 .ok()
1217 .map_or(false, |op| Precedence::of(&op) >= base)
1218 {
David Tolnay3e541292018-08-30 11:42:15 -07001219 let op: BinOp = input.parse()?;
1220 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001221 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001222 loop {
1223 let next = peek_precedence(input);
1224 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001225 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001226 } else {
1227 break;
1228 }
1229 }
1230 lhs = Expr::Binary(ExprBinary {
1231 attrs: Vec::new(),
1232 left: Box::new(lhs),
1233 op: op,
1234 right: Box::new(rhs),
1235 });
1236 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1237 let as_token: Token![as] = input.parse()?;
1238 let ty = input.call(Type::without_plus)?;
1239 lhs = Expr::Cast(ExprCast {
1240 attrs: Vec::new(),
1241 expr: Box::new(lhs),
1242 as_token: as_token,
1243 ty: Box::new(ty),
1244 });
1245 } else {
1246 break;
1247 }
1248 }
1249 Ok(lhs)
1250 }
1251
David Tolnay01218d12018-08-29 18:13:07 -07001252 fn peek_precedence(input: ParseStream) -> Precedence {
1253 if let Ok(op) = input.fork().parse() {
1254 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001255 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001256 Precedence::Assign
1257 } else if input.peek(Token![<-]) {
1258 Precedence::Placement
1259 } else if input.peek(Token![..]) {
1260 Precedence::Range
1261 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1262 Precedence::Cast
1263 } else {
1264 Precedence::Any
1265 }
1266 }
1267
David Tolnaybcf26022017-12-25 22:10:52 -05001268 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001269 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001270 let lhs = unary_expr(input, allow_struct)?;
1271 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001272 }
1273
David Tolnaybcf26022017-12-25 22:10:52 -05001274 // <UnOp> <trailer>
1275 // & <trailer>
1276 // &mut <trailer>
1277 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001278 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001279 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001280 let ahead = input.fork();
1281 ahead.call(Attribute::parse_outer)?;
1282 if ahead.peek(Token![&])
1283 || ahead.peek(Token![box])
1284 || ahead.peek(Token![*])
1285 || ahead.peek(Token![!])
1286 || ahead.peek(Token![-])
1287 {
1288 let attrs = input.call(Attribute::parse_outer)?;
1289 if input.peek(Token![&]) {
1290 Ok(Expr::Reference(ExprReference {
1291 attrs: attrs,
1292 and_token: input.parse()?,
1293 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001294 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001295 }))
1296 } else if input.peek(Token![box]) {
1297 Ok(Expr::Box(ExprBox {
1298 attrs: attrs,
1299 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001300 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001301 }))
1302 } else {
1303 Ok(Expr::Unary(ExprUnary {
1304 attrs: attrs,
1305 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001306 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001307 }))
1308 }
1309 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001310 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001311 }
1312 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001313
Michael Layzell734adb42017-06-07 16:58:31 -04001314 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001315 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001316 let ahead = input.fork();
1317 ahead.call(Attribute::parse_outer)?;
1318 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1319 Ok(Expr::Unary(ExprUnary {
1320 attrs: input.call(Attribute::parse_outer)?,
1321 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001322 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001323 }))
1324 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001325 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001326 }
1327 }
Michael Layzell734adb42017-06-07 16:58:31 -04001328
David Tolnaybcf26022017-12-25 22:10:52 -05001329 // <atom> (..<args>) ...
1330 // <atom> . <ident> (..<args>) ...
1331 // <atom> . <ident> ...
1332 // <atom> . <lit> ...
1333 // <atom> [ <expr> ] ...
1334 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001335 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001336 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001337 if input.peek(token::Group) {
1338 return input.call(expr_group).map(Expr::Group);
1339 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001340
David Tolnay577fd312018-09-01 02:26:40 -07001341 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001342
David Tolnay577fd312018-09-01 02:26:40 -07001343 let atom = atom_expr(input, allow_struct)?;
1344 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001345
David Tolnay577fd312018-09-01 02:26:40 -07001346 let inner_attrs = e.replace_attrs(Vec::new());
1347 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001348 e.replace_attrs(attrs);
1349 Ok(e)
1350 }
1351
1352 #[cfg(feature = "full")]
1353 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001354 loop {
1355 if input.peek(token::Paren) {
1356 let content;
1357 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001358 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001359 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001360 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001361 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001362 });
1363 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1364 let dot_token: Token![.] = input.parse()?;
1365 let member: Member = input.parse()?;
1366 let turbofish = if member.is_named() && input.peek(Token![::]) {
1367 Some(MethodTurbofish {
1368 colon2_token: input.parse()?,
1369 lt_token: input.parse()?,
1370 args: {
1371 let mut args = Punctuated::new();
1372 loop {
1373 if input.peek(Token![>]) {
1374 break;
1375 }
David Tolnay310b3262018-08-30 15:33:00 -07001376 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001377 args.push_value(value);
1378 if input.peek(Token![>]) {
1379 break;
1380 }
1381 let punct = input.parse()?;
1382 args.push_punct(punct);
1383 }
1384 args
1385 },
1386 gt_token: input.parse()?,
1387 })
1388 } else {
1389 None
1390 };
1391
1392 if turbofish.is_some() || input.peek(token::Paren) {
1393 if let Member::Named(method) = member {
1394 let content;
1395 e = Expr::MethodCall(ExprMethodCall {
1396 attrs: Vec::new(),
1397 receiver: Box::new(e),
1398 dot_token: dot_token,
1399 method: method,
1400 turbofish: turbofish,
1401 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001402 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001403 });
1404 continue;
1405 }
1406 }
1407
1408 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001409 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001410 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001411 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001412 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001413 });
1414 } else if input.peek(token::Bracket) {
1415 let content;
1416 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001417 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001418 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001419 bracket_token: bracketed!(content in input),
1420 index: content.parse()?,
1421 });
1422 } else if input.peek(Token![?]) {
1423 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001424 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001425 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001426 question_token: input.parse()?,
1427 });
1428 } else {
1429 break;
1430 }
1431 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001432 Ok(e)
1433 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001434
Michael Layzell734adb42017-06-07 16:58:31 -04001435 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001436 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001437 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001438
1439 loop {
1440 if input.peek(token::Paren) {
1441 let content;
1442 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001443 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001444 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001445 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001446 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001447 });
1448 } else if input.peek(Token![.]) {
1449 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001450 attrs: Vec::new(),
1451 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001452 dot_token: input.parse()?,
1453 member: input.parse()?,
1454 });
1455 } else if input.peek(token::Bracket) {
1456 let content;
1457 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001458 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001459 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001460 bracket_token: bracketed!(content in input),
1461 index: content.parse()?,
1462 });
1463 } else {
1464 break;
1465 }
1466 }
1467
1468 Ok(e)
1469 }
Michael Layzell734adb42017-06-07 16:58:31 -04001470
David Tolnaya454c8f2018-01-07 01:01:10 -08001471 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001472 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001473 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001474 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001475 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001476 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001477 } else if input.peek(Lit) {
David Tolnay577fd312018-09-01 02:26:40 -07001478 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001479 } else if input.peek(Token![async])
1480 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1481 {
David Tolnay577fd312018-09-01 02:26:40 -07001482 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001483 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001484 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001485 } else if input.peek(Token![|])
1486 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1487 || input.peek(Token![static])
1488 || input.peek(Token![move])
1489 {
David Tolnay577fd312018-09-01 02:26:40 -07001490 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001491 } else if input.peek(Ident)
1492 || input.peek(Token![::])
1493 || input.peek(Token![<])
1494 || input.peek(Token![self])
1495 || input.peek(Token![Self])
1496 || input.peek(Token![super])
1497 || input.peek(Token![extern])
1498 || input.peek(Token![crate])
1499 {
David Tolnay577fd312018-09-01 02:26:40 -07001500 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001501 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001502 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001503 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001504 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001505 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001506 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001507 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001508 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001509 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001510 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001511 } else if input.peek(Token![let]) {
1512 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001513 } else if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001514 input.call(expr_if).map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001515 } else if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001516 input.call(expr_while).map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001517 } else if input.peek(Token![for]) {
David Tolnay577fd312018-09-01 02:26:40 -07001518 input.call(expr_for_loop).map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001519 } else if input.peek(Token![loop]) {
David Tolnay577fd312018-09-01 02:26:40 -07001520 input.call(expr_loop).map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001521 } else if input.peek(Token![match]) {
David Tolnay577fd312018-09-01 02:26:40 -07001522 input.call(expr_match).map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001523 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001524 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001525 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001526 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001527 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001528 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001530 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001531 } else if input.peek(Lifetime) {
1532 let the_label: Label = input.parse()?;
1533 let mut expr = if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001534 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001535 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001536 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001537 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001538 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001539 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001540 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001541 } else {
1542 return Err(input.error("expected loop or block expression"));
1543 };
1544 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001545 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001546 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1547 | Expr::Loop(ExprLoop { ref mut label, .. })
1548 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001549 _ => unreachable!(),
1550 }
David Tolnay577fd312018-09-01 02:26:40 -07001551 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001552 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001553 Err(input.error("expected expression"))
1554 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001555 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001556
Michael Layzell734adb42017-06-07 16:58:31 -04001557 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001558 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001559 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001560 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001561 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001562 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001563 } else if input.peek(Ident)
1564 || input.peek(Token![::])
1565 || input.peek(Token![<])
1566 || input.peek(Token![self])
1567 || input.peek(Token![Self])
1568 || input.peek(Token![super])
1569 || input.peek(Token![extern])
1570 || input.peek(Token![crate])
1571 {
1572 input.parse().map(Expr::Path)
1573 } else {
1574 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1575 }
1576 }
1577
1578 #[cfg(feature = "full")]
1579 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1580 let expr: ExprPath = input.parse()?;
1581 if expr.qself.is_some() {
1582 return Ok(Expr::Path(expr));
1583 }
1584
1585 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1586 let mut contains_arguments = false;
1587 for segment in &expr.path.segments {
1588 match segment.arguments {
1589 PathArguments::None => {}
1590 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1591 contains_arguments = true;
1592 }
1593 }
1594 }
1595
1596 if !contains_arguments {
1597 let bang_token: Token![!] = input.parse()?;
1598 let (delimiter, tts) = mac::parse_delimiter(input)?;
1599 return Ok(Expr::Macro(ExprMacro {
1600 attrs: Vec::new(),
1601 mac: Macro {
1602 path: expr.path,
1603 bang_token: bang_token,
1604 delimiter: delimiter,
1605 tts: tts,
1606 },
1607 }));
1608 }
1609 }
1610
1611 if allow_struct.0 && input.peek(token::Brace) {
1612 let outer_attrs = Vec::new();
1613 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1614 } else {
1615 Ok(Expr::Path(expr))
1616 }
1617 }
1618
1619 #[cfg(feature = "full")]
1620 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1621 let content;
1622 let paren_token = parenthesized!(content in input);
1623 let inner_attrs = content.call(Attribute::parse_inner)?;
1624 if content.is_empty() {
1625 return Ok(Expr::Tuple(ExprTuple {
1626 attrs: inner_attrs,
1627 paren_token: paren_token,
1628 elems: Punctuated::new(),
1629 }));
1630 }
1631
1632 let first: Expr = content.parse()?;
1633 if content.is_empty() {
1634 return Ok(Expr::Paren(ExprParen {
1635 attrs: inner_attrs,
1636 paren_token: paren_token,
1637 expr: Box::new(first),
1638 }));
1639 }
1640
1641 let mut elems = Punctuated::new();
1642 elems.push_value(first);
1643 while !content.is_empty() {
1644 let punct = content.parse()?;
1645 elems.push_punct(punct);
1646 if content.is_empty() {
1647 break;
1648 }
1649 let value = content.parse()?;
1650 elems.push_value(value);
1651 }
1652 Ok(Expr::Tuple(ExprTuple {
1653 attrs: inner_attrs,
1654 paren_token: paren_token,
1655 elems: elems,
1656 }))
1657 }
1658
1659 #[cfg(feature = "full")]
1660 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1661 let content;
1662 let bracket_token = bracketed!(content in input);
1663 let inner_attrs = content.call(Attribute::parse_inner)?;
1664 if content.is_empty() {
1665 return Ok(Expr::Array(ExprArray {
1666 attrs: inner_attrs,
1667 bracket_token: bracket_token,
1668 elems: Punctuated::new(),
1669 }));
1670 }
1671
1672 let first: Expr = content.parse()?;
1673 if content.is_empty() || content.peek(Token![,]) {
1674 let mut elems = Punctuated::new();
1675 elems.push_value(first);
1676 while !content.is_empty() {
1677 let punct = content.parse()?;
1678 elems.push_punct(punct);
1679 if content.is_empty() {
1680 break;
1681 }
1682 let value = content.parse()?;
1683 elems.push_value(value);
1684 }
1685 Ok(Expr::Array(ExprArray {
1686 attrs: inner_attrs,
1687 bracket_token: bracket_token,
1688 elems: elems,
1689 }))
1690 } else if content.peek(Token![;]) {
1691 let semi_token: Token![;] = content.parse()?;
1692 let len: Expr = content.parse()?;
1693 Ok(Expr::Repeat(ExprRepeat {
1694 attrs: inner_attrs,
1695 bracket_token: bracket_token,
1696 expr: Box::new(first),
1697 semi_token: semi_token,
1698 len: Box::new(len),
1699 }))
1700 } else {
1701 Err(content.error("expected `,` or `;`"))
1702 }
1703 }
Michael Layzell734adb42017-06-07 16:58:31 -04001704
Michael Layzell734adb42017-06-07 16:58:31 -04001705 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001706 fn expr_early(input: ParseStream) -> Result<Expr> {
1707 let mut attrs = input.call(Attribute::parse_outer)?;
1708 let mut expr = if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001709 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001710 } else if input.peek(Token![while]) {
David Tolnay9c119122018-09-01 18:47:02 -07001711 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001712 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001713 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001714 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001715 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001716 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001717 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001718 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001719 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001720 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001721 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001722 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001723 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001724 } else {
1725 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001726 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001727
1728 attrs.extend(expr.replace_attrs(Vec::new()));
1729 expr.replace_attrs(attrs);
1730
David Tolnay7d2e1db2018-08-30 11:49:04 -07001731 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001732 };
1733
1734 if input.peek(Token![.]) || input.peek(Token![?]) {
1735 expr = trailer_helper(input, expr)?;
1736
1737 attrs.extend(expr.replace_attrs(Vec::new()));
1738 expr.replace_attrs(attrs);
1739
1740 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001741 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001742 }
1743
1744 attrs.extend(expr.replace_attrs(Vec::new()));
1745 expr.replace_attrs(attrs);
1746 Ok(expr)
1747 }
Michael Layzell35418782017-06-07 09:20:25 -04001748
David Tolnay310b3262018-08-30 15:33:00 -07001749 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1750 Ok(ExprLit {
1751 attrs: Vec::new(),
1752 lit: input.parse()?,
1753 })
David Tolnay8c91b882017-12-28 23:04:32 -05001754 }
1755
1756 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001757 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001758 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001759 Ok(ExprGroup {
1760 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001761 group_token: group.token,
1762 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001763 })
1764 }
1765
1766 #[cfg(not(feature = "full"))]
1767 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1768 let content;
1769 Ok(ExprParen {
1770 attrs: Vec::new(),
1771 paren_token: parenthesized!(content in input),
1772 expr: content.parse()?,
1773 })
David Tolnay8c91b882017-12-28 23:04:32 -05001774 }
1775
David Tolnaye98775f2017-12-28 23:17:00 -05001776 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001777 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001778 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001779 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001780 }
1781
1782 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001783 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1784 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001785 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001786 let_token: input.parse()?,
1787 pats: {
1788 let mut pats = Punctuated::new();
1789 let value: Pat = input.parse()?;
1790 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001791 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001792 let punct = input.parse()?;
1793 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001794 let value: Pat = input.parse()?;
1795 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001796 }
1797 pats
1798 },
1799 eq_token: input.parse()?,
1800 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001801 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001802 }
1803
Michael Layzell734adb42017-06-07 16:58:31 -04001804 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001805 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1806 Ok(ExprIf {
1807 attrs: Vec::new(),
1808 if_token: input.parse()?,
1809 cond: Box::new(input.call(expr_no_struct)?),
1810 then_branch: input.parse()?,
1811 else_branch: {
1812 if input.peek(Token![else]) {
1813 Some(input.call(else_block)?)
1814 } else {
1815 None
1816 }
1817 },
1818 })
Alex Crichton954046c2017-05-30 21:49:42 -07001819 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001820
Michael Layzell734adb42017-06-07 16:58:31 -04001821 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001822 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1823 let else_token: Token![else] = input.parse()?;
1824
1825 let lookahead = input.lookahead1();
1826 let else_branch = if input.peek(Token![if]) {
David Tolnay9c119122018-09-01 18:47:02 -07001827 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001828 } else if input.peek(token::Brace) {
1829 Expr::Block(ExprBlock {
1830 attrs: Vec::new(),
1831 label: None,
1832 block: input.parse()?,
1833 })
1834 } else {
1835 return Err(lookahead.error());
1836 };
1837
1838 Ok((else_token, Box::new(else_branch)))
1839 }
David Tolnay939766a2016-09-23 23:48:12 -07001840
Michael Layzell734adb42017-06-07 16:58:31 -04001841 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001842 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1843 let label: Option<Label> = input.parse()?;
1844 let for_token: Token![for] = input.parse()?;
1845 let pat: Pat = input.parse()?;
1846 let in_token: Token![in] = input.parse()?;
1847 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001848
David Tolnay310b3262018-08-30 15:33:00 -07001849 let content;
1850 let brace_token = braced!(content in input);
1851 let inner_attrs = content.call(Attribute::parse_inner)?;
1852 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001853
David Tolnay310b3262018-08-30 15:33:00 -07001854 Ok(ExprForLoop {
1855 attrs: inner_attrs,
1856 label: label,
1857 for_token: for_token,
1858 pat: Box::new(pat),
1859 in_token: in_token,
1860 expr: Box::new(expr),
1861 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001862 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001863 stmts: stmts,
1864 },
1865 })
Alex Crichton954046c2017-05-30 21:49:42 -07001866 }
David Tolnay1978c672016-10-27 22:05:52 -07001867
Michael Layzell734adb42017-06-07 16:58:31 -04001868 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001869 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1870 let label: Option<Label> = input.parse()?;
1871 let loop_token: Token![loop] = input.parse()?;
1872
1873 let content;
1874 let brace_token = braced!(content in input);
1875 let inner_attrs = content.call(Attribute::parse_inner)?;
1876 let stmts = content.call(Block::parse_within)?;
1877
1878 Ok(ExprLoop {
1879 attrs: inner_attrs,
1880 label: label,
1881 loop_token: loop_token,
1882 body: Block {
1883 brace_token: brace_token,
1884 stmts: stmts,
1885 },
1886 })
Alex Crichton954046c2017-05-30 21:49:42 -07001887 }
Arnavion02ef13f2017-04-25 00:54:31 -07001888
Michael Layzell734adb42017-06-07 16:58:31 -04001889 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001890 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1891 let match_token: Token![match] = input.parse()?;
1892 let expr = expr_no_struct(input)?;
1893
1894 let content;
1895 let brace_token = braced!(content in input);
1896 let inner_attrs = content.call(Attribute::parse_inner)?;
1897
1898 let mut arms = Vec::new();
1899 while !content.is_empty() {
Bastien Oriveld29ea392018-10-16 23:50:16 +02001900 arms.push(content.call(Arm::parse)?);
David Tolnay310b3262018-08-30 15:33:00 -07001901 }
1902
1903 Ok(ExprMatch {
1904 attrs: inner_attrs,
1905 match_token: match_token,
1906 expr: Box::new(expr),
1907 brace_token: brace_token,
1908 arms: arms,
1909 })
1910 }
1911
1912 #[cfg(feature = "full")]
1913 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1914 Ok(ExprTryBlock {
1915 attrs: Vec::new(),
1916 try_token: input.parse()?,
1917 block: input.parse()?,
1918 })
1919 }
1920
1921 #[cfg(feature = "full")]
1922 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1923 Ok(ExprYield {
1924 attrs: Vec::new(),
1925 yield_token: input.parse()?,
1926 expr: {
1927 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1928 Some(input.parse()?)
1929 } else {
1930 None
1931 }
1932 },
1933 })
1934 }
1935
1936 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001937 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001938 let asyncness: Option<Token![async]> = input.parse()?;
1939 let movability: Option<Token![static]> = if asyncness.is_none() {
1940 input.parse()?
1941 } else {
1942 None
1943 };
1944 let capture: Option<Token![move]> = input.parse()?;
1945 let or1_token: Token![|] = input.parse()?;
1946
1947 let mut inputs = Punctuated::new();
1948 loop {
1949 if input.peek(Token![|]) {
1950 break;
1951 }
1952 let value = fn_arg(input)?;
1953 inputs.push_value(value);
1954 if input.peek(Token![|]) {
1955 break;
1956 }
1957 let punct: Token![,] = input.parse()?;
1958 inputs.push_punct(punct);
1959 }
1960
1961 let or2_token: Token![|] = input.parse()?;
1962
1963 let (output, body) = if input.peek(Token![->]) {
1964 let arrow_token: Token![->] = input.parse()?;
1965 let ty: Type = input.parse()?;
1966 let body: Block = input.parse()?;
1967 let output = ReturnType::Type(arrow_token, Box::new(ty));
1968 let block = Expr::Block(ExprBlock {
1969 attrs: Vec::new(),
1970 label: None,
1971 block: body,
1972 });
1973 (output, block)
1974 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001975 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001976 (ReturnType::Default, body)
1977 };
1978
1979 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07001980 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09001981 asyncness: asyncness,
1982 movability: movability,
1983 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07001984 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09001985 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07001986 or2_token: or2_token,
1987 output: output,
1988 body: Box::new(body),
1989 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04001990 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001991
1992 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001993 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
1994 Ok(ExprAsync {
1995 attrs: Vec::new(),
1996 async_token: input.parse()?,
1997 capture: input.parse()?,
1998 block: input.parse()?,
1999 })
David Tolnay60291082018-08-28 09:54:49 -07002000 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002001
Michael Layzell734adb42017-06-07 16:58:31 -04002002 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002003 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2004 let pat: Pat = input.parse()?;
2005
2006 if input.peek(Token![:]) {
2007 Ok(FnArg::Captured(ArgCaptured {
2008 pat: pat,
2009 colon_token: input.parse()?,
2010 ty: input.parse()?,
2011 }))
2012 } else {
2013 Ok(FnArg::Inferred(pat))
2014 }
2015 }
2016
2017 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002018 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2019 let label: Option<Label> = input.parse()?;
2020 let while_token: Token![while] = input.parse()?;
2021 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002022
David Tolnay310b3262018-08-30 15:33:00 -07002023 let content;
2024 let brace_token = braced!(content in input);
2025 let inner_attrs = content.call(Attribute::parse_inner)?;
2026 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002027
David Tolnay310b3262018-08-30 15:33:00 -07002028 Ok(ExprWhile {
2029 attrs: inner_attrs,
2030 label: label,
2031 while_token: while_token,
2032 cond: Box::new(cond),
2033 body: Block {
2034 brace_token: brace_token,
2035 stmts: stmts,
2036 },
2037 })
Alex Crichton954046c2017-05-30 21:49:42 -07002038 }
2039
Michael Layzell734adb42017-06-07 16:58:31 -04002040 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002041 impl Parse for Label {
2042 fn parse(input: ParseStream) -> Result<Self> {
2043 Ok(Label {
2044 name: input.parse()?,
2045 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002046 })
David Tolnay60291082018-08-28 09:54:49 -07002047 }
Alex Crichton954046c2017-05-30 21:49:42 -07002048 }
2049
Michael Layzell734adb42017-06-07 16:58:31 -04002050 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002051 impl Parse for Option<Label> {
2052 fn parse(input: ParseStream) -> Result<Self> {
2053 if input.peek(Lifetime) {
2054 input.parse().map(Some)
2055 } else {
2056 Ok(None)
2057 }
2058 }
2059 }
2060
2061 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002062 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2063 Ok(ExprContinue {
2064 attrs: Vec::new(),
2065 continue_token: input.parse()?,
2066 label: input.parse()?,
2067 })
Alex Crichton954046c2017-05-30 21:49:42 -07002068 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002069
Michael Layzell734adb42017-06-07 16:58:31 -04002070 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002071 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2072 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002073 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002074 break_token: input.parse()?,
2075 label: input.parse()?,
2076 expr: {
2077 if input.is_empty()
2078 || input.peek(Token![,])
2079 || input.peek(Token![;])
2080 || !allow_struct.0 && input.peek(token::Brace)
2081 {
2082 None
2083 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002084 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002085 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002086 }
David Tolnay60291082018-08-28 09:54:49 -07002087 },
2088 })
Alex Crichton954046c2017-05-30 21:49:42 -07002089 }
2090
Michael Layzell734adb42017-06-07 16:58:31 -04002091 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002092 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2093 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002094 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002095 return_token: input.parse()?,
2096 expr: {
2097 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2098 None
2099 } else {
2100 // NOTE: return is greedy and eats blocks after it even when in a
2101 // position where structs are not allowed, such as in if statement
2102 // conditions. For example:
2103 //
2104 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002105 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002106 Some(Box::new(expr))
2107 }
2108 },
2109 })
2110 }
2111
2112 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002113 impl Parse for FieldValue {
2114 fn parse(input: ParseStream) -> Result<Self> {
2115 let member: Member = input.parse()?;
2116 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2117 let colon_token: Token![:] = input.parse()?;
2118 let value: Expr = input.parse()?;
2119 (Some(colon_token), value)
2120 } else if let Member::Named(ref ident) = member {
2121 let value = Expr::Path(ExprPath {
2122 attrs: Vec::new(),
2123 qself: None,
2124 path: Path::from(ident.clone()),
2125 });
2126 (None, value)
2127 } else {
2128 unreachable!()
2129 };
2130
2131 Ok(FieldValue {
2132 attrs: Vec::new(),
2133 member: member,
2134 colon_token: colon_token,
2135 expr: value,
2136 })
2137 }
2138 }
2139
2140 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002141 fn expr_struct_helper(
2142 input: ParseStream,
2143 outer_attrs: Vec<Attribute>,
2144 path: Path,
2145 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002146 let content;
2147 let brace_token = braced!(content in input);
2148 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002149
David Tolnay6e1e5052018-08-30 10:21:48 -07002150 let mut fields = Punctuated::new();
2151 loop {
2152 let attrs = content.call(Attribute::parse_outer)?;
2153 if content.fork().parse::<Member>().is_err() {
2154 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002155 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002156 } else {
2157 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002158 }
David Tolnay60291082018-08-28 09:54:49 -07002159 }
2160
David Tolnay6e1e5052018-08-30 10:21:48 -07002161 fields.push(FieldValue {
2162 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002163 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002164 });
2165
2166 if !content.peek(Token![,]) {
2167 break;
2168 }
2169 let punct: Token![,] = content.parse()?;
2170 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002171 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002172
2173 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2174 let dot2_token: Token![..] = content.parse()?;
2175 let rest: Expr = content.parse()?;
2176 (Some(dot2_token), Some(Box::new(rest)))
2177 } else {
2178 (None, None)
2179 };
2180
2181 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002182 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002183 brace_token: brace_token,
2184 path: path,
2185 fields: fields,
2186 dot2_token: dot2_token,
2187 rest: rest,
2188 })
Alex Crichton954046c2017-05-30 21:49:42 -07002189 }
David Tolnay055a7042016-10-02 19:23:54 -07002190
Michael Layzell734adb42017-06-07 16:58:31 -04002191 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002192 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2193 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002194
David Tolnay310b3262018-08-30 15:33:00 -07002195 let content;
2196 let brace_token = braced!(content in input);
2197 let inner_attrs = content.call(Attribute::parse_inner)?;
2198 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002199
David Tolnay310b3262018-08-30 15:33:00 -07002200 Ok(ExprUnsafe {
2201 attrs: inner_attrs,
2202 unsafe_token: unsafe_token,
2203 block: Block {
2204 brace_token: brace_token,
2205 stmts: stmts,
2206 },
2207 })
Alex Crichton954046c2017-05-30 21:49:42 -07002208 }
David Tolnay055a7042016-10-02 19:23:54 -07002209
Michael Layzell734adb42017-06-07 16:58:31 -04002210 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002211 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2212 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002213
David Tolnay310b3262018-08-30 15:33:00 -07002214 let content;
2215 let brace_token = braced!(content in input);
2216 let inner_attrs = content.call(Attribute::parse_inner)?;
2217 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002218
David Tolnay310b3262018-08-30 15:33:00 -07002219 Ok(ExprBlock {
2220 attrs: inner_attrs,
2221 label: label,
2222 block: Block {
2223 brace_token: brace_token,
2224 stmts: stmts,
2225 },
2226 })
Alex Crichton954046c2017-05-30 21:49:42 -07002227 }
David Tolnay89e05672016-10-02 14:39:42 -07002228
Michael Layzell734adb42017-06-07 16:58:31 -04002229 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002230 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2231 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002232 attrs: Vec::new(),
2233 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002234 limits: input.parse()?,
2235 to: {
2236 if input.is_empty()
2237 || input.peek(Token![,])
2238 || input.peek(Token![;])
2239 || !allow_struct.0 && input.peek(token::Brace)
2240 {
2241 None
2242 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002243 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002244 Some(Box::new(to))
2245 }
2246 },
2247 })
2248 }
David Tolnay438c9052016-10-07 23:24:48 -07002249
Michael Layzell734adb42017-06-07 16:58:31 -04002250 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002251 impl Parse for RangeLimits {
2252 fn parse(input: ParseStream) -> Result<Self> {
2253 let lookahead = input.lookahead1();
2254 if lookahead.peek(Token![..=]) {
2255 input.parse().map(RangeLimits::Closed)
2256 } else if lookahead.peek(Token![...]) {
2257 let dot3: Token![...] = input.parse()?;
2258 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2259 } else if lookahead.peek(Token![..]) {
2260 input.parse().map(RangeLimits::HalfOpen)
2261 } else {
2262 Err(lookahead.error())
2263 }
2264 }
Alex Crichton954046c2017-05-30 21:49:42 -07002265 }
David Tolnay438c9052016-10-07 23:24:48 -07002266
David Tolnay60291082018-08-28 09:54:49 -07002267 impl Parse for ExprPath {
2268 fn parse(input: ParseStream) -> Result<Self> {
2269 #[cfg(not(feature = "full"))]
2270 let attrs = Vec::new();
2271 #[cfg(feature = "full")]
2272 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002273
David Tolnay60291082018-08-28 09:54:49 -07002274 let (qself, path) = path::parsing::qpath(input, true)?;
2275
2276 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002277 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002278 qself: qself,
2279 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002280 })
David Tolnay60291082018-08-28 09:54:49 -07002281 }
Alex Crichton954046c2017-05-30 21:49:42 -07002282 }
David Tolnay42602292016-10-01 22:25:45 -07002283
Michael Layzell734adb42017-06-07 16:58:31 -04002284 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002285 impl Parse for Block {
2286 fn parse(input: ParseStream) -> Result<Self> {
2287 let content;
2288 Ok(Block {
2289 brace_token: braced!(content in input),
2290 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002291 })
David Tolnay60291082018-08-28 09:54:49 -07002292 }
Alex Crichton954046c2017-05-30 21:49:42 -07002293 }
David Tolnay939766a2016-09-23 23:48:12 -07002294
Michael Layzell734adb42017-06-07 16:58:31 -04002295 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002296 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002297 /// Parse the body of a block as zero or more statements, possibly
2298 /// including one trailing expression.
2299 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002300 /// *This function is available if Syn is built with the `"parsing"`
2301 /// feature.*
2302 ///
David Tolnay6b457252018-09-01 15:55:47 -07002303 /// # Example
2304 ///
2305 /// ```
David Tolnaya1c98072018-09-06 08:58:10 -07002306 /// #[macro_use]
2307 /// extern crate syn;
2308 ///
2309 /// use syn::{token, Attribute, Block, Ident, Stmt};
David Tolnay6b457252018-09-01 15:55:47 -07002310 /// use syn::parse::{Parse, ParseStream, Result};
2311 ///
2312 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002313 /// //
2314 /// // fn playground {
2315 /// // let mut x = 1;
2316 /// // x += 1;
2317 /// // println!("{}", x);
2318 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002319 /// struct MiniFunction {
2320 /// attrs: Vec<Attribute>,
2321 /// fn_token: Token![fn],
2322 /// name: Ident,
2323 /// brace_token: token::Brace,
2324 /// stmts: Vec<Stmt>,
2325 /// }
2326 ///
2327 /// impl Parse for MiniFunction {
2328 /// fn parse(input: ParseStream) -> Result<Self> {
2329 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2330 /// let fn_token: Token![fn] = input.parse()?;
2331 /// let name: Ident = input.parse()?;
2332 ///
2333 /// let content;
2334 /// let brace_token = braced!(content in input);
2335 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2336 /// let stmts = content.call(Block::parse_within)?;
2337 ///
2338 /// Ok(MiniFunction {
2339 /// attrs: {
2340 /// let mut attrs = outer_attrs;
2341 /// attrs.extend(inner_attrs);
2342 /// attrs
2343 /// },
2344 /// fn_token: fn_token,
2345 /// name: name,
2346 /// brace_token: brace_token,
2347 /// stmts: stmts,
2348 /// })
2349 /// }
2350 /// }
2351 /// #
2352 /// # fn main() {}
2353 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002354 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002355 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002356 loop {
2357 while input.peek(Token![;]) {
2358 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002359 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002360 if input.is_empty() {
2361 break;
2362 }
2363 let s = parse_stmt(input, true)?;
2364 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2365 requires_terminator(s)
2366 } else {
2367 false
2368 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002369 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002370 if input.is_empty() {
2371 break;
2372 } else if requires_semicolon {
2373 return Err(input.error("unexpected token"));
2374 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002375 }
2376 Ok(stmts)
2377 }
Alex Crichton954046c2017-05-30 21:49:42 -07002378 }
2379
Michael Layzell734adb42017-06-07 16:58:31 -04002380 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002381 impl Parse for Stmt {
2382 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002383 parse_stmt(input, false)
2384 }
2385 }
David Tolnay939766a2016-09-23 23:48:12 -07002386
David Tolnaye532d6b2018-08-30 16:55:01 -07002387 #[cfg(feature = "full")]
2388 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2389 let ahead = input.fork();
2390 ahead.call(Attribute::parse_outer)?;
2391
David Tolnaye532d6b2018-08-30 16:55:01 -07002392 if {
2393 let ahead = ahead.fork();
2394 // Only parse braces here; paren and bracket will get parsed as
2395 // expression statements
2396 ahead.call(Path::parse_mod_style).is_ok()
2397 && ahead.parse::<Token![!]>().is_ok()
2398 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2399 } {
2400 stmt_mac(input)
2401 } else if ahead.peek(Token![let]) {
2402 stmt_local(input).map(Stmt::Local)
2403 } else if ahead.peek(Token![pub])
2404 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2405 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2406 || ahead.peek(Token![use])
2407 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2408 || ahead.peek(Token![const])
2409 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2410 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2411 || ahead.peek(Token![fn])
2412 || ahead.peek(Token![mod])
2413 || ahead.peek(Token![type])
2414 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2415 || ahead.peek(Token![struct])
2416 || ahead.peek(Token![enum])
2417 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2418 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2419 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002420 || ahead.peek(Token![default])
2421 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
2422 || ahead.peek(Token![impl ])
David Tolnaye532d6b2018-08-30 16:55:01 -07002423 || ahead.peek(Token![macro])
2424 {
2425 input.parse().map(Stmt::Item)
2426 } else {
2427 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002428 }
Alex Crichton954046c2017-05-30 21:49:42 -07002429 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002430
Michael Layzell734adb42017-06-07 16:58:31 -04002431 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002432 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2433 let attrs = input.call(Attribute::parse_outer)?;
2434 let path = input.call(Path::parse_mod_style)?;
2435 let bang_token: Token![!] = input.parse()?;
2436 let ident: Option<Ident> = input.parse()?;
2437 let (delimiter, tts) = mac::parse_delimiter(input)?;
2438 let semi_token: Option<Token![;]> = input.parse()?;
2439
2440 Ok(Stmt::Item(Item::Macro(ItemMacro {
2441 attrs: attrs,
2442 ident: ident,
2443 mac: Macro {
2444 path: path,
2445 bang_token: bang_token,
2446 delimiter: delimiter,
2447 tts: tts,
2448 },
2449 semi_token: semi_token,
2450 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002451 }
David Tolnay84aa0752016-10-02 23:01:13 -07002452
Michael Layzell734adb42017-06-07 16:58:31 -04002453 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002454 fn stmt_local(input: ParseStream) -> Result<Local> {
2455 Ok(Local {
2456 attrs: input.call(Attribute::parse_outer)?,
2457 let_token: input.parse()?,
2458 pats: {
2459 let mut pats = Punctuated::new();
2460 let value: Pat = input.parse()?;
2461 pats.push_value(value);
2462 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2463 let punct = input.parse()?;
2464 pats.push_punct(punct);
2465 let value: Pat = input.parse()?;
2466 pats.push_value(value);
2467 }
2468 pats
2469 },
2470 ty: {
2471 if input.peek(Token![:]) {
2472 let colon_token: Token![:] = input.parse()?;
2473 let ty: Type = input.parse()?;
2474 Some((colon_token, Box::new(ty)))
2475 } else {
2476 None
2477 }
2478 },
2479 init: {
2480 if input.peek(Token![=]) {
2481 let eq_token: Token![=] = input.parse()?;
2482 let init: Expr = input.parse()?;
2483 Some((eq_token, Box::new(init)))
2484 } else {
2485 None
2486 }
2487 },
2488 semi_token: input.parse()?,
2489 })
2490 }
2491
2492 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002493 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002494 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002495 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002496
2497 attrs.extend(e.replace_attrs(Vec::new()));
2498 e.replace_attrs(attrs);
2499
2500 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002501 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002502 }
David Tolnay60291082018-08-28 09:54:49 -07002503
David Tolnayf00a2762018-08-30 17:22:22 -07002504 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002505 Ok(Stmt::Expr(e))
2506 } else {
2507 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002508 }
David Tolnay60291082018-08-28 09:54:49 -07002509 }
2510
2511 #[cfg(feature = "full")]
2512 impl Parse for Pat {
2513 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002514 let lookahead = input.lookahead1();
2515 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002516 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002517 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002518 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002519 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2520 pat_lit_or_range(input)
2521 } else if input.peek(Ident)
2522 && ({
2523 input.peek2(Token![::])
2524 || input.peek2(Token![!])
2525 || input.peek2(token::Brace)
2526 || input.peek2(token::Paren)
2527 || input.peek2(Token![..]) && !{
2528 let ahead = input.fork();
2529 ahead.parse::<Ident>()?;
2530 ahead.parse::<RangeLimits>()?;
2531 ahead.is_empty() || ahead.peek(Token![,])
2532 }
2533 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002534 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002535 || input.peek(Token![::])
2536 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002537 || input.peek(Token![Self])
2538 || input.peek(Token![super])
2539 || input.peek(Token![extern])
2540 || input.peek(Token![crate])
2541 {
2542 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002543 } else if input.peek(Token![ref])
2544 || input.peek(Token![mut])
2545 || input.peek(Token![self])
2546 || input.peek(Ident)
2547 {
David Tolnay310b3262018-08-30 15:33:00 -07002548 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002549 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002550 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002551 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002552 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002553 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002554 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002555 } else {
2556 Err(lookahead.error())
2557 }
2558 }
2559 }
2560
2561 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002562 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2563 let (qself, path) = path::parsing::qpath(input, true)?;
2564
2565 if input.peek(Token![..]) {
2566 return pat_range(input, qself, path).map(Pat::Range);
2567 }
2568
2569 if qself.is_some() {
2570 return Ok(Pat::Path(PatPath {
2571 qself: qself,
2572 path: path,
2573 }));
2574 }
2575
2576 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2577 let mut contains_arguments = false;
2578 for segment in &path.segments {
2579 match segment.arguments {
2580 PathArguments::None => {}
2581 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2582 contains_arguments = true;
2583 }
2584 }
2585 }
2586
2587 if !contains_arguments {
2588 let bang_token: Token![!] = input.parse()?;
2589 let (delimiter, tts) = mac::parse_delimiter(input)?;
2590 return Ok(Pat::Macro(PatMacro {
2591 mac: Macro {
2592 path: path,
2593 bang_token: bang_token,
2594 delimiter: delimiter,
2595 tts: tts,
2596 },
2597 }));
2598 }
2599 }
2600
2601 if input.peek(token::Brace) {
2602 pat_struct(input, path).map(Pat::Struct)
2603 } else if input.peek(token::Paren) {
2604 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2605 } else if input.peek(Token![..]) {
2606 pat_range(input, qself, path).map(Pat::Range)
2607 } else {
2608 Ok(Pat::Path(PatPath {
2609 qself: qself,
2610 path: path,
2611 }))
2612 }
2613 }
2614
2615 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002616 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2617 Ok(PatWild {
2618 underscore_token: input.parse()?,
2619 })
Alex Crichton954046c2017-05-30 21:49:42 -07002620 }
2621
Michael Layzell734adb42017-06-07 16:58:31 -04002622 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002623 fn pat_box(input: ParseStream) -> Result<PatBox> {
2624 Ok(PatBox {
2625 box_token: input.parse()?,
2626 pat: input.parse()?,
2627 })
David Tolnay60291082018-08-28 09:54:49 -07002628 }
2629
2630 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002631 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2632 Ok(PatIdent {
2633 by_ref: input.parse()?,
2634 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002635 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002636 subpat: {
2637 if input.peek(Token![@]) {
2638 let at_token: Token![@] = input.parse()?;
2639 let subpat: Pat = input.parse()?;
2640 Some((at_token, Box::new(subpat)))
2641 } else {
2642 None
2643 }
2644 },
2645 })
David Tolnay60291082018-08-28 09:54:49 -07002646 }
2647
2648 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002649 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002650 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002651 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002652 pat: input.call(pat_tuple)?,
2653 })
2654 }
David Tolnay60291082018-08-28 09:54:49 -07002655
David Tolnay310b3262018-08-30 15:33:00 -07002656 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002657 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002658 let content;
2659 let brace_token = braced!(content in input);
2660
2661 let mut fields = Punctuated::new();
2662 while !content.is_empty() && !content.peek(Token![..]) {
2663 let value = content.call(field_pat)?;
2664 fields.push_value(value);
2665 if !content.peek(Token![,]) {
2666 break;
David Tolnay60291082018-08-28 09:54:49 -07002667 }
David Tolnay310b3262018-08-30 15:33:00 -07002668 let punct: Token![,] = content.parse()?;
2669 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002670 }
David Tolnay310b3262018-08-30 15:33:00 -07002671
2672 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2673 Some(content.parse()?)
2674 } else {
2675 None
2676 };
2677
2678 Ok(PatStruct {
2679 path: path,
2680 brace_token: brace_token,
2681 fields: fields,
2682 dot2_token: dot2_token,
2683 })
2684 }
2685
2686 #[cfg(feature = "full")]
2687 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2688 let boxed: Option<Token![box]> = input.parse()?;
2689 let by_ref: Option<Token![ref]> = input.parse()?;
2690 let mutability: Option<Token![mut]> = input.parse()?;
2691 let member: Member = input.parse()?;
2692
2693 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2694 || member.is_unnamed()
2695 {
2696 return Ok(FieldPat {
2697 attrs: Vec::new(),
2698 member: member,
2699 colon_token: input.parse()?,
2700 pat: input.parse()?,
2701 });
2702 }
2703
2704 let ident = match member {
2705 Member::Named(ident) => ident,
2706 Member::Unnamed(_) => unreachable!(),
2707 };
2708
2709 let mut pat = Pat::Ident(PatIdent {
2710 by_ref: by_ref,
2711 mutability: mutability,
2712 ident: ident.clone(),
2713 subpat: None,
2714 });
2715
2716 if let Some(boxed) = boxed {
2717 pat = Pat::Box(PatBox {
2718 pat: Box::new(pat),
2719 box_token: boxed,
2720 });
2721 }
2722
2723 Ok(FieldPat {
2724 member: Member::Named(ident),
2725 pat: Box::new(pat),
2726 attrs: Vec::new(),
2727 colon_token: None,
2728 })
Alex Crichton954046c2017-05-30 21:49:42 -07002729 }
2730
David Tolnay1501f7e2018-08-27 14:21:03 -07002731 impl Parse for Member {
2732 fn parse(input: ParseStream) -> Result<Self> {
2733 if input.peek(Ident) {
2734 input.parse().map(Member::Named)
2735 } else if input.peek(LitInt) {
2736 input.parse().map(Member::Unnamed)
2737 } else {
2738 Err(input.error("expected identifier or integer"))
2739 }
2740 }
David Tolnay85b69a42017-12-27 20:43:10 -05002741 }
2742
Bastien Oriveld29ea392018-10-16 23:50:16 +02002743 #[cfg(feature = "full")]
2744 impl Parse for Arm {
2745 fn parse(input: ParseStream) -> Result<Arm> {
2746 let requires_comma;
2747 Ok(Arm {
2748 attrs: input.call(Attribute::parse_outer)?,
2749 leading_vert: input.parse()?,
2750 pats: {
2751 let mut pats = Punctuated::new();
2752 let value: Pat = input.parse()?;
2753 pats.push_value(value);
2754 loop {
2755 if !input.peek(Token![|]) {
2756 break;
2757 }
2758 let punct = input.parse()?;
2759 pats.push_punct(punct);
2760 let value: Pat = input.parse()?;
2761 pats.push_value(value);
2762 }
2763 pats
2764 },
2765 guard: {
2766 if input.peek(Token![if]) {
2767 let if_token: Token![if] = input.parse()?;
2768 let guard: Expr = input.parse()?;
2769 Some((if_token, Box::new(guard)))
2770 } else {
2771 None
2772 }
2773 },
2774 fat_arrow_token: input.parse()?,
2775 body: {
2776 let body = input.call(expr_early)?;
2777 requires_comma = requires_terminator(&body);
2778 Box::new(body)
2779 },
2780 comma: {
2781 if requires_comma && !input.is_empty() {
2782 Some(input.parse()?)
2783 } else {
2784 input.parse()?
2785 }
2786 },
2787 })
2788 }
2789 }
2790
David Tolnay1501f7e2018-08-27 14:21:03 -07002791 impl Parse for Index {
2792 fn parse(input: ParseStream) -> Result<Self> {
2793 let lit: LitInt = input.parse()?;
2794 if let IntSuffix::None = lit.suffix() {
2795 Ok(Index {
2796 index: lit.value() as u32,
2797 span: lit.span(),
2798 })
2799 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002800 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002801 }
2802 }
David Tolnay85b69a42017-12-27 20:43:10 -05002803 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002804
Michael Layzell734adb42017-06-07 16:58:31 -04002805 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002806 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2807 Ok(PatRange {
2808 lo: Box::new(Expr::Path(ExprPath {
2809 attrs: Vec::new(),
2810 qself: qself,
2811 path: path,
2812 })),
2813 limits: input.parse()?,
2814 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002815 })
Alex Crichton954046c2017-05-30 21:49:42 -07002816 }
David Tolnay9636c052016-10-02 17:11:17 -07002817
Michael Layzell734adb42017-06-07 16:58:31 -04002818 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002819 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2820 let content;
2821 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002822
David Tolnay310b3262018-08-30 15:33:00 -07002823 let mut front = Punctuated::new();
2824 let mut dot2_token = None::<Token![..]>;
2825 let mut comma_token = None::<Token![,]>;
2826 loop {
2827 if content.is_empty() {
2828 break;
David Tolnay60291082018-08-28 09:54:49 -07002829 }
David Tolnay310b3262018-08-30 15:33:00 -07002830 if content.peek(Token![..]) {
2831 dot2_token = Some(content.parse()?);
2832 comma_token = content.parse()?;
2833 break;
David Tolnay60291082018-08-28 09:54:49 -07002834 }
David Tolnay310b3262018-08-30 15:33:00 -07002835 let value: Pat = content.parse()?;
2836 front.push_value(value);
2837 if content.is_empty() {
2838 break;
2839 }
2840 let punct = content.parse()?;
2841 front.push_punct(punct);
2842 }
2843
David Tolnayf5ebc192018-08-30 18:23:46 -07002844 let mut back = Punctuated::new();
2845 while !content.is_empty() {
2846 let value: Pat = content.parse()?;
2847 back.push_value(value);
2848 if content.is_empty() {
2849 break;
2850 }
2851 let punct = content.parse()?;
2852 back.push_punct(punct);
2853 }
David Tolnay310b3262018-08-30 15:33:00 -07002854
2855 Ok(PatTuple {
2856 paren_token: paren_token,
2857 front: front,
2858 dot2_token: dot2_token,
2859 comma_token: comma_token,
2860 back: back,
2861 })
2862 }
2863
2864 #[cfg(feature = "full")]
2865 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2866 Ok(PatRef {
2867 and_token: input.parse()?,
2868 mutability: input.parse()?,
2869 pat: input.parse()?,
2870 })
2871 }
2872
2873 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002874 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2875 let lo = input.call(pat_lit_expr)?;
2876 if input.peek(Token![..]) {
2877 Ok(Pat::Range(PatRange {
2878 lo: lo,
2879 limits: input.parse()?,
2880 hi: input.call(pat_lit_expr)?,
2881 }))
David Tolnay310b3262018-08-30 15:33:00 -07002882 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002883 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002884 }
2885 }
2886
2887 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002888 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2889 let neg: Option<Token![-]> = input.parse()?;
2890
2891 let lookahead = input.lookahead1();
2892 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002893 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002894 } else if lookahead.peek(Ident)
2895 || lookahead.peek(Token![::])
2896 || lookahead.peek(Token![<])
2897 || lookahead.peek(Token![self])
2898 || lookahead.peek(Token![Self])
2899 || lookahead.peek(Token![super])
2900 || lookahead.peek(Token![extern])
2901 || lookahead.peek(Token![crate])
2902 {
2903 Expr::Path(input.parse()?)
2904 } else {
2905 return Err(lookahead.error());
2906 };
2907
2908 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002909 Expr::Unary(ExprUnary {
2910 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002911 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002912 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002913 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002914 } else {
David Tolnay60291082018-08-28 09:54:49 -07002915 expr
2916 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002917 }
David Tolnay323279a2017-12-29 11:26:32 -05002918
2919 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002920 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2921 let content;
2922 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002923
David Tolnay310b3262018-08-30 15:33:00 -07002924 let mut front = Punctuated::new();
2925 let mut middle = None;
2926 loop {
2927 if content.is_empty() || content.peek(Token![..]) {
2928 break;
David Tolnay60291082018-08-28 09:54:49 -07002929 }
David Tolnay310b3262018-08-30 15:33:00 -07002930 let value: Pat = content.parse()?;
2931 if content.peek(Token![..]) {
2932 middle = Some(Box::new(value));
2933 break;
David Tolnay60291082018-08-28 09:54:49 -07002934 }
David Tolnay310b3262018-08-30 15:33:00 -07002935 front.push_value(value);
2936 if content.is_empty() {
2937 break;
2938 }
2939 let punct = content.parse()?;
2940 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002941 }
David Tolnay310b3262018-08-30 15:33:00 -07002942
2943 let dot2_token: Option<Token![..]> = content.parse()?;
2944 let mut comma_token = None::<Token![,]>;
2945 let mut back = Punctuated::new();
2946 if dot2_token.is_some() {
2947 comma_token = content.parse()?;
2948 if comma_token.is_some() {
2949 loop {
2950 if content.is_empty() {
2951 break;
2952 }
2953 let value: Pat = content.parse()?;
2954 back.push_value(value);
2955 if content.is_empty() {
2956 break;
2957 }
2958 let punct = content.parse()?;
2959 back.push_punct(punct);
2960 }
2961 }
2962 }
2963
2964 Ok(PatSlice {
2965 bracket_token: bracket_token,
2966 front: front,
2967 middle: middle,
2968 dot2_token: dot2_token,
2969 comma_token: comma_token,
2970 back: back,
2971 })
David Tolnay60291082018-08-28 09:54:49 -07002972 }
2973
2974 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07002975 impl Member {
2976 fn is_named(&self) -> bool {
2977 match *self {
2978 Member::Named(_) => true,
2979 Member::Unnamed(_) => false,
2980 }
2981 }
David Tolnay60291082018-08-28 09:54:49 -07002982
2983 fn is_unnamed(&self) -> bool {
2984 match *self {
2985 Member::Named(_) => false,
2986 Member::Unnamed(_) => true,
2987 }
2988 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002989 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002990}
2991
David Tolnayf4bbbd92016-09-23 14:41:55 -07002992#[cfg(feature = "printing")]
2993mod printing {
2994 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07002995
Alex Crichtona74a1c82018-05-16 10:20:44 -07002996 use proc_macro2::{Literal, TokenStream};
2997 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07002998
David Tolnay64023912018-08-31 09:51:12 -07002999 #[cfg(feature = "full")]
3000 use attr::FilterAttrs;
3001 #[cfg(feature = "full")]
3002 use print::TokensOrDefault;
3003
David Tolnaybcf26022017-12-25 22:10:52 -05003004 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003005 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003006 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003007 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003008 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003009 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003010 e.to_tokens(tokens);
3011 });
3012 } else {
3013 e.to_tokens(tokens);
3014 }
3015 }
3016
David Tolnay8c91b882017-12-28 23:04:32 -05003017 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003018 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003019 tokens.append_all(attrs.outer());
3020 }
Michael Layzell734adb42017-06-07 16:58:31 -04003021
David Tolnayd997aef2018-07-21 18:42:31 -07003022 #[cfg(feature = "full")]
3023 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3024 tokens.append_all(attrs.inner());
3025 }
3026
David Tolnay8c91b882017-12-28 23:04:32 -05003027 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003028 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3029
3030 #[cfg(not(feature = "full"))]
3031 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003032
Michael Layzell734adb42017-06-07 16:58:31 -04003033 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003034 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003035 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003036 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003037 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003038 self.expr.to_tokens(tokens);
3039 }
3040 }
3041
Michael Layzell734adb42017-06-07 16:58:31 -04003042 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003043 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003044 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003045 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003046 self.place.to_tokens(tokens);
3047 self.arrow_token.to_tokens(tokens);
3048 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003049 }
3050 }
3051
Michael Layzell734adb42017-06-07 16:58:31 -04003052 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003053 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003054 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003055 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003056 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003057 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003058 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003059 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003060 }
3061 }
3062
3063 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003064 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003065 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003066 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003067 self.paren_token.surround(tokens, |tokens| {
3068 self.args.to_tokens(tokens);
3069 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003070 }
3071 }
3072
Michael Layzell734adb42017-06-07 16:58:31 -04003073 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003074 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003075 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003076 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003077 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003078 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003079 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003080 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003081 self.paren_token.surround(tokens, |tokens| {
3082 self.args.to_tokens(tokens);
3083 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003084 }
3085 }
3086
Michael Layzell734adb42017-06-07 16:58:31 -04003087 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003088 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003089 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003090 self.colon2_token.to_tokens(tokens);
3091 self.lt_token.to_tokens(tokens);
3092 self.args.to_tokens(tokens);
3093 self.gt_token.to_tokens(tokens);
3094 }
3095 }
3096
3097 #[cfg(feature = "full")]
3098 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003099 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003100 match *self {
3101 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3102 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3103 }
3104 }
3105 }
3106
3107 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003108 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003109 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003110 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003111 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003112 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003113 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003114 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003115 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003116 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003117 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003118 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003119 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003120 }
3121 }
3122
3123 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003124 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003125 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003126 self.left.to_tokens(tokens);
3127 self.op.to_tokens(tokens);
3128 self.right.to_tokens(tokens);
3129 }
3130 }
3131
3132 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003133 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003134 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003135 self.op.to_tokens(tokens);
3136 self.expr.to_tokens(tokens);
3137 }
3138 }
3139
David Tolnay8c91b882017-12-28 23:04:32 -05003140 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003141 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003142 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003143 self.lit.to_tokens(tokens);
3144 }
3145 }
3146
Alex Crichton62a0a592017-05-22 13:58:53 -07003147 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003148 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003149 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003150 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003151 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003152 self.ty.to_tokens(tokens);
3153 }
3154 }
3155
David Tolnay0cf94f22017-12-28 23:46:26 -05003156 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003157 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003158 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003159 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003160 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003161 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003162 self.ty.to_tokens(tokens);
3163 }
3164 }
3165
Michael Layzell734adb42017-06-07 16:58:31 -04003166 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003167 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003168 if let Some((ref else_token, ref else_)) = *else_ {
3169 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003170
3171 // If we are not one of the valid expressions to exist in an else
3172 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003173 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003174 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003175 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003176 }
3177 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003178 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003179 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003180 });
3181 }
3182 }
3183 }
3184 }
3185
3186 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003187 impl ToTokens for ExprLet {
3188 fn to_tokens(&self, tokens: &mut TokenStream) {
3189 outer_attrs_to_tokens(&self.attrs, tokens);
3190 self.let_token.to_tokens(tokens);
3191 self.pats.to_tokens(tokens);
3192 self.eq_token.to_tokens(tokens);
3193 wrap_bare_struct(tokens, &self.expr);
3194 }
3195 }
3196
3197 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003199 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003200 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003201 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003202 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003203 self.then_branch.to_tokens(tokens);
3204 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003205 }
3206 }
3207
Michael Layzell734adb42017-06-07 16:58:31 -04003208 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003209 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003210 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003211 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003212 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003213 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003214 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003215 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003216 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003217 tokens.append_all(&self.body.stmts);
3218 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003219 }
3220 }
3221
Michael Layzell734adb42017-06-07 16:58:31 -04003222 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003223 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003224 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003225 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003226 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003227 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003228 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003229 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003230 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003231 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003232 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003233 tokens.append_all(&self.body.stmts);
3234 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003235 }
3236 }
3237
Michael Layzell734adb42017-06-07 16:58:31 -04003238 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003239 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003240 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003241 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003242 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003243 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003244 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003245 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003246 tokens.append_all(&self.body.stmts);
3247 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003248 }
3249 }
3250
Michael Layzell734adb42017-06-07 16:58:31 -04003251 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003252 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003253 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003254 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003255 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003256 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003257 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003258 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003259 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003260 arm.to_tokens(tokens);
3261 // Ensure that we have a comma after a non-block arm, except
3262 // for the last one.
3263 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003264 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003265 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003266 }
3267 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003268 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003269 }
3270 }
3271
Michael Layzell734adb42017-06-07 16:58:31 -04003272 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003273 impl ToTokens for ExprAsync {
3274 fn to_tokens(&self, tokens: &mut TokenStream) {
3275 outer_attrs_to_tokens(&self.attrs, tokens);
3276 self.async_token.to_tokens(tokens);
3277 self.capture.to_tokens(tokens);
3278 self.block.to_tokens(tokens);
3279 }
3280 }
3281
3282 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003283 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003284 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003285 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003286 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003287 self.block.to_tokens(tokens);
3288 }
3289 }
3290
Michael Layzell734adb42017-06-07 16:58:31 -04003291 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003292 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003293 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003294 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003295 self.yield_token.to_tokens(tokens);
3296 self.expr.to_tokens(tokens);
3297 }
3298 }
3299
3300 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003301 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003302 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003303 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003304 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003305 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003306 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003307 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003308 for input in self.inputs.pairs() {
3309 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003310 FnArg::Captured(ArgCaptured {
3311 ref pat,
3312 ty: Type::Infer(_),
3313 ..
3314 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003315 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003316 }
David Tolnay56080682018-01-06 14:01:52 -08003317 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003318 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003319 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003320 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003321 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003322 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003323 self.body.to_tokens(tokens);
3324 }
3325 }
3326
Michael Layzell734adb42017-06-07 16:58:31 -04003327 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003328 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003329 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003330 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003331 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003332 self.block.brace_token.surround(tokens, |tokens| {
3333 inner_attrs_to_tokens(&self.attrs, tokens);
3334 tokens.append_all(&self.block.stmts);
3335 });
Nika Layzell640832a2017-12-04 13:37:09 -05003336 }
3337 }
3338
3339 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003340 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003341 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003342 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003343 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003344 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003345 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003346 tokens.append_all(&self.block.stmts);
3347 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003348 }
3349 }
3350
Michael Layzell734adb42017-06-07 16:58:31 -04003351 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003352 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003353 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003354 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003355 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003356 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003357 self.right.to_tokens(tokens);
3358 }
3359 }
3360
Michael Layzell734adb42017-06-07 16:58:31 -04003361 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003362 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003363 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003364 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003365 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003366 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003367 self.right.to_tokens(tokens);
3368 }
3369 }
3370
3371 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003372 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003373 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003374 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003375 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003376 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003377 }
3378 }
3379
David Tolnay85b69a42017-12-27 20:43:10 -05003380 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003381 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003382 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003383 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003384 Member::Unnamed(ref index) => index.to_tokens(tokens),
3385 }
3386 }
3387 }
3388
David Tolnay85b69a42017-12-27 20:43:10 -05003389 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003390 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003391 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3392 lit.set_span(self.span);
3393 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003394 }
3395 }
3396
3397 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003398 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003399 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003401 self.bracket_token.surround(tokens, |tokens| {
3402 self.index.to_tokens(tokens);
3403 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003404 }
3405 }
3406
Michael Layzell734adb42017-06-07 16:58:31 -04003407 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003409 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003410 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003411 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003412 match self.limits {
3413 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3414 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3415 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003416 self.to.to_tokens(tokens);
3417 }
3418 }
3419
3420 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003421 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003422 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003423 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003424 }
3425 }
3426
Michael Layzell734adb42017-06-07 16:58:31 -04003427 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003428 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003429 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003430 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003431 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003432 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003433 self.expr.to_tokens(tokens);
3434 }
3435 }
3436
Michael Layzell734adb42017-06-07 16:58:31 -04003437 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003438 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003439 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003440 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003441 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003442 self.label.to_tokens(tokens);
3443 self.expr.to_tokens(tokens);
3444 }
3445 }
3446
Michael Layzell734adb42017-06-07 16:58:31 -04003447 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003448 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003449 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003450 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003451 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 self.label.to_tokens(tokens);
3453 }
3454 }
3455
Michael Layzell734adb42017-06-07 16:58:31 -04003456 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003457 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003458 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003459 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003460 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003461 self.expr.to_tokens(tokens);
3462 }
3463 }
3464
Michael Layzell734adb42017-06-07 16:58:31 -04003465 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003466 impl ToTokens for ExprMacro {
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);
David Tolnay8c91b882017-12-28 23:04:32 -05003469 self.mac.to_tokens(tokens);
3470 }
3471 }
3472
3473 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003474 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003475 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003476 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003477 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003478 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003479 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003480 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003481 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003482 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003483 self.rest.to_tokens(tokens);
3484 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003485 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 }
3487 }
3488
Michael Layzell734adb42017-06-07 16:58:31 -04003489 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003490 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003491 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003492 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003493 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003494 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003495 self.expr.to_tokens(tokens);
3496 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003497 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003498 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003499 }
3500 }
3501
David Tolnaye98775f2017-12-28 23:17:00 -05003502 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003503 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003504 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003505 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003506 self.group_token.surround(tokens, |tokens| {
3507 self.expr.to_tokens(tokens);
3508 });
3509 }
3510 }
3511
Alex Crichton62a0a592017-05-22 13:58:53 -07003512 impl ToTokens for ExprParen {
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 Crichtonccbb45d2017-05-23 10:58:24 -07003515 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003516 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003517 self.expr.to_tokens(tokens);
3518 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003519 }
3520 }
3521
Michael Layzell734adb42017-06-07 16:58:31 -04003522 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003523 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003524 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003525 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003526 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003527 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003528 }
3529 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003530
David Tolnay2ae520a2017-12-29 11:19:50 -05003531 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003532 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003533 self.tts.to_tokens(tokens);
3534 }
3535 }
3536
Michael Layzell734adb42017-06-07 16:58:31 -04003537 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003538 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003539 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003540 self.name.to_tokens(tokens);
3541 self.colon_token.to_tokens(tokens);
3542 }
3543 }
3544
3545 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003546 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003547 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003548 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003549 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003550 if let Some(ref colon_token) = self.colon_token {
3551 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003552 self.expr.to_tokens(tokens);
3553 }
David Tolnay055a7042016-10-02 19:23:54 -07003554 }
3555 }
3556
Michael Layzell734adb42017-06-07 16:58:31 -04003557 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003558 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003559 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003560 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003561 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003562 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003563 if let Some((ref if_token, ref guard)) = self.guard {
3564 if_token.to_tokens(tokens);
3565 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003566 }
David Tolnaydfb91432018-03-31 19:19:44 +02003567 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003568 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003569 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003570 }
3571 }
3572
Michael Layzell734adb42017-06-07 16:58:31 -04003573 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003574 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003575 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003576 self.underscore_token.to_tokens(tokens);
3577 }
3578 }
3579
Michael Layzell734adb42017-06-07 16:58:31 -04003580 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003581 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003582 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003583 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003584 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003585 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003586 if let Some((ref at_token, ref subpat)) = self.subpat {
3587 at_token.to_tokens(tokens);
3588 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003589 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003590 }
3591 }
3592
Michael Layzell734adb42017-06-07 16:58:31 -04003593 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003594 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003595 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003596 self.path.to_tokens(tokens);
3597 self.brace_token.surround(tokens, |tokens| {
3598 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003599 // NOTE: We need a comma before the dot2 token if it is present.
3600 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003601 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003602 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003603 self.dot2_token.to_tokens(tokens);
3604 });
3605 }
3606 }
3607
Michael Layzell734adb42017-06-07 16:58:31 -04003608 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003609 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003610 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003611 self.path.to_tokens(tokens);
3612 self.pat.to_tokens(tokens);
3613 }
3614 }
3615
Michael Layzell734adb42017-06-07 16:58:31 -04003616 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003618 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003619 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003620 }
3621 }
3622
Michael Layzell734adb42017-06-07 16:58:31 -04003623 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003625 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003626 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003627 self.front.to_tokens(tokens);
3628 if let Some(ref dot2_token) = self.dot2_token {
3629 if !self.front.empty_or_trailing() {
3630 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003631 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003632 }
David Tolnay41871922017-12-29 01:53:45 -05003633 dot2_token.to_tokens(tokens);
3634 self.comma_token.to_tokens(tokens);
3635 if self.comma_token.is_none() && !self.back.is_empty() {
3636 // Ensure there is a comma after the .. token.
3637 <Token![,]>::default().to_tokens(tokens);
3638 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003639 }
David Tolnay41871922017-12-29 01:53:45 -05003640 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003641 });
3642 }
3643 }
3644
Michael Layzell734adb42017-06-07 16:58:31 -04003645 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003646 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003647 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003648 self.box_token.to_tokens(tokens);
3649 self.pat.to_tokens(tokens);
3650 }
3651 }
3652
Michael Layzell734adb42017-06-07 16:58:31 -04003653 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003654 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003655 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003656 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003657 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003658 self.pat.to_tokens(tokens);
3659 }
3660 }
3661
Michael Layzell734adb42017-06-07 16:58:31 -04003662 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003663 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003664 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003665 self.expr.to_tokens(tokens);
3666 }
3667 }
3668
Michael Layzell734adb42017-06-07 16:58:31 -04003669 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003670 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003671 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003673 match self.limits {
3674 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003675 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003676 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 self.hi.to_tokens(tokens);
3678 }
3679 }
3680
Michael Layzell734adb42017-06-07 16:58:31 -04003681 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003683 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003684 self.bracket_token.surround(tokens, |tokens| {
3685 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003686
3687 // If we need a comma before the middle or standalone .. token,
3688 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003689 if !self.front.empty_or_trailing()
3690 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003691 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003692 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003693 }
3694
3695 // If we have an identifier, we always need a .. token.
3696 if self.middle.is_some() {
3697 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003698 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003699 } else if self.dot2_token.is_some() {
3700 self.dot2_token.to_tokens(tokens);
3701 }
3702
3703 // Make sure we have a comma before the back half.
3704 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003705 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003706 self.back.to_tokens(tokens);
3707 } else {
3708 self.comma_token.to_tokens(tokens);
3709 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003710 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003711 }
3712 }
3713
Michael Layzell734adb42017-06-07 16:58:31 -04003714 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003715 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003716 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003717 self.mac.to_tokens(tokens);
3718 }
3719 }
3720
3721 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003722 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003723 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003724 self.tts.to_tokens(tokens);
3725 }
3726 }
3727
3728 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003729 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003730 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003731 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003732 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003733 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003734 }
3735 self.pat.to_tokens(tokens);
3736 }
3737 }
3738
Michael Layzell734adb42017-06-07 16:58:31 -04003739 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003740 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003741 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003742 self.brace_token.surround(tokens, |tokens| {
3743 tokens.append_all(&self.stmts);
3744 });
David Tolnay42602292016-10-01 22:25:45 -07003745 }
3746 }
3747
Michael Layzell734adb42017-06-07 16:58:31 -04003748 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003749 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003750 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003751 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003752 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003753 Stmt::Item(ref item) => item.to_tokens(tokens),
3754 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003755 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003756 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003757 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003758 }
David Tolnay42602292016-10-01 22:25:45 -07003759 }
3760 }
3761 }
David Tolnay191e0582016-10-02 18:31:09 -07003762
Michael Layzell734adb42017-06-07 16:58:31 -04003763 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003764 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003765 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003766 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003767 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003768 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003769 if let Some((ref colon_token, ref ty)) = self.ty {
3770 colon_token.to_tokens(tokens);
3771 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003772 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003773 if let Some((ref eq_token, ref init)) = self.init {
3774 eq_token.to_tokens(tokens);
3775 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003776 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003777 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003778 }
3779 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003780}