blob: 196a1f4ac88e8a7c0cb5925ec55758154d3290a9 [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -07002use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -07003use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -05004#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -05005use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -07006#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -05007use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -07008#[cfg(feature = "extra-traits")]
9use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070010
Alex Crichton62a0a592017-05-22 13:58:53 -070011ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080012 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080013 ///
David Tolnay461d98e2018-01-07 11:07:19 -080014 /// *This type is available if Syn is built with the `"derive"` or `"full"`
15 /// feature.*
16 ///
David Tolnay614a0142018-01-07 10:25:43 -080017 /// # Syntax tree enums
18 ///
19 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
20 /// are designed to be traversed using the following rebinding idiom.
21 ///
David Tolnay95989db2019-01-01 15:05:57 -050022 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080023 /// # use syn::Expr;
24 /// #
25 /// # fn example(expr: Expr) {
26 /// # const IGNORE: &str = stringify! {
27 /// let expr: Expr = /* ... */;
28 /// # };
29 /// match expr {
30 /// Expr::MethodCall(expr) => {
31 /// /* ... */
32 /// }
33 /// Expr::Cast(expr) => {
34 /// /* ... */
35 /// }
David Tolnay9c119122018-09-01 18:47:02 -070036 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080037 /// /* ... */
38 /// }
David Tolnay65336072019-04-22 23:10:52 -070039 ///
David Tolnay614a0142018-01-07 10:25:43 -080040 /// /* ... */
41 /// # _ => {}
David Tolnay65336072019-04-22 23:10:52 -070042 /// # }
David Tolnay614a0142018-01-07 10:25:43 -080043 /// # }
44 /// ```
45 ///
46 /// We begin with a variable `expr` of type `Expr` that has no fields
47 /// (because it is an enum), and by matching on it and rebinding a variable
48 /// with the same name `expr` we effectively imbue our variable with all of
49 /// the data fields provided by the variant that it turned out to be. So for
50 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070051 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
52 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080053 ///
David Tolnay614a0142018-01-07 10:25:43 -080054 /// This approach avoids repeating the variant names twice on every line.
55 ///
David Tolnay95989db2019-01-01 15:05:57 -050056 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080057 /// # use syn::{Expr, ExprMethodCall};
58 /// #
59 /// # fn example(expr: Expr) {
David Tolnay65336072019-04-22 23:10:52 -070060 /// // Repetitive; recommend not doing this.
61 /// match expr {
62 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
David Tolnay614a0142018-01-07 10:25:43 -080063 /// # }
64 /// # _ => {}
65 /// # }
66 /// # }
67 /// ```
68 ///
69 /// In general, the name to which a syntax tree enum variant is bound should
70 /// be a suitable name for the complete syntax tree enum type.
71 ///
David Tolnay95989db2019-01-01 15:05:57 -050072 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080073 /// # use syn::{Expr, ExprField};
74 /// #
David Tolnay65336072019-04-22 23:10:52 -070075 /// # fn example(discriminant: ExprField) {
David Tolnay614a0142018-01-07 10:25:43 -080076 /// // Binding is called `base` which is the name I would use if I were
77 /// // assigning `*discriminant.base` without an `if let`.
David Tolnay65336072019-04-22 23:10:52 -070078 /// if let Expr::Tuple(base) = *discriminant.base {
David Tolnay614a0142018-01-07 10:25:43 -080079 /// # }
80 /// # }
81 /// ```
82 ///
83 /// A sign that you may not be choosing the right variable names is if you
84 /// see names getting repeated in your code, like accessing
85 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -050086 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -080087 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -080088 ///
89 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040090 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -050091 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080092 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -050093 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -070094 }),
Clar Charrd22b5702017-03-10 15:24:56 -050095
David Tolnaya454c8f2018-01-07 01:01:10 -080096 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -080097 ///
98 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040099 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500100 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700101 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500102 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700103 pub value: Box<Expr>,
104 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500105
David Tolnaya454c8f2018-01-07 01:01:10 -0800106 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800107 ///
108 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400109 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500110 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500111 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500112 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500114
David Tolnaya454c8f2018-01-07 01:01:10 -0800115 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800116 ///
117 /// *This type is available if Syn is built with the `"derive"` or
118 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700119 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500122 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500123 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500131 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800132 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500133 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500134 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500135 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500136 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700137 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500138
David Tolnaya454c8f2018-01-07 01:01:10 -0800139 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800140 ///
141 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500142 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500143 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500144 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500145 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700146 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500147
David Tolnaya454c8f2018-01-07 01:01:10 -0800148 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700152 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500153 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700154 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700156 pub right: Box<Expr>,
157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"derive"` or
162 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700163 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500164 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700165 pub op: UnOp,
166 pub expr: Box<Expr>,
167 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500168
David Tolnaya454c8f2018-01-07 01:01:10 -0800169 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800170 ///
171 /// *This type is available if Syn is built with the `"derive"` or
172 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub Lit(ExprLit {
174 pub attrs: Vec<Attribute>,
175 pub lit: Lit,
176 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500177
David Tolnaya454c8f2018-01-07 01:01:10 -0800178 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800179 ///
180 /// *This type is available if Syn is built with the `"derive"` or
181 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700182 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500183 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700184 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800185 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800186 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500192 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800195 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800196 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500198
David Tolnay9c119122018-09-01 18:47:02 -0700199 /// A `let` guard: `let Some(x) = opt`.
200 ///
201 /// *This type is available if Syn is built with the `"full"` feature.*
202 pub Let(ExprLet #full {
203 pub attrs: Vec<Attribute>,
204 pub let_token: Token![let],
205 pub pats: Punctuated<Pat, Token![|]>,
206 pub eq_token: Token![=],
207 pub expr: Box<Expr>,
208 }),
209
David Tolnaya454c8f2018-01-07 01:01:10 -0800210 /// An `if` expression with an optional `else` block: `if expr { ... }
211 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700212 ///
David Tolnay9c119122018-09-01 18:47:02 -0700213 /// The `else` branch expression may only be an `If` or `Block`
214 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800215 ///
216 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400217 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500218 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500219 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700220 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500221 pub then_branch: Block,
222 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700223 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500224
David Tolnaya454c8f2018-01-07 01:01:10 -0800225 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800226 ///
227 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400228 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500229 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500230 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800231 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500232 pub cond: Box<Expr>,
233 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700234 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500235
David Tolnaya454c8f2018-01-07 01:01:10 -0800236 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800237 ///
238 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400239 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500240 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500241 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500242 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500244 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700245 pub expr: Box<Expr>,
246 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700247 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500248
David Tolnaya454c8f2018-01-07 01:01:10 -0800249 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800250 ///
251 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400252 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500253 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500254 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500255 pub loop_token: Token![loop],
256 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700257 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500258
David Tolnaya454c8f2018-01-07 01:01:10 -0800259 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800260 ///
261 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400262 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500263 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800264 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500266 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 pub arms: Vec<Arm>,
268 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500269
David Tolnaya454c8f2018-01-07 01:01:10 -0800270 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800271 ///
272 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400273 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500274 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900275 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200276 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500277 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800278 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500279 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800280 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500281 pub output: ReturnType,
282 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700283 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500284
David Tolnaya454c8f2018-01-07 01:01:10 -0800285 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800286 ///
287 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500288 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500289 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500290 pub unsafe_token: Token![unsafe],
291 pub block: Block,
292 }),
293
David Tolnaya454c8f2018-01-07 01:01:10 -0800294 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800295 ///
296 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400297 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500298 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400299 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700300 pub block: Block,
301 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700302
David Tolnaya454c8f2018-01-07 01:01:10 -0800303 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800304 ///
305 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400306 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500307 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500310 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700311 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500312
David Tolnaya454c8f2018-01-07 01:01:10 -0800313 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800314 ///
315 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400316 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500317 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700318 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500319 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub right: Box<Expr>,
321 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500324 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800325 ///
326 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700327 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500328 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500329 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800330 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500331 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500333
David Tolnay05658502018-01-07 09:56:37 -0800334 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800335 ///
336 /// *This type is available if Syn is built with the `"derive"` or
337 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500341 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500342 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700343 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500344
David Tolnaya454c8f2018-01-07 01:01:10 -0800345 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800346 ///
347 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400348 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500349 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700350 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700351 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500352 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700353 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700354
David Tolnaya454c8f2018-01-07 01:01:10 -0800355 /// A path like `std::mem::replace` possibly containing generic
356 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700357 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800358 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800359 ///
360 /// *This type is available if Syn is built with the `"derive"` or
361 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700362 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500363 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700364 pub qself: Option<QSelf>,
365 pub path: Path,
366 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700367
David Tolnaya454c8f2018-01-07 01:01:10 -0800368 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800369 ///
370 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200371 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500372 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800373 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500374 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700375 pub expr: Box<Expr>,
376 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500377
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A `break`, with an optional label to break and an optional
379 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800380 ///
381 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400382 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500384 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700385 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700386 pub expr: Option<Box<Expr>>,
387 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500388
David Tolnaya454c8f2018-01-07 01:01:10 -0800389 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800390 ///
391 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400392 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500393 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800394 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500395 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500401 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500402 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800403 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700406
David Tolnaya454c8f2018-01-07 01:01:10 -0800407 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800408 ///
409 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500410 pub Macro(ExprMacro #full {
411 pub attrs: Vec<Attribute>,
412 pub mac: Macro,
413 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700414
David Tolnaya454c8f2018-01-07 01:01:10 -0800415 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800417 /// The `rest` provides the value of the remaining fields as in `S { a:
418 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400421 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700423 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500424 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500425 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500426 pub dot2_token: Option<Token![..]>,
427 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700428 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500435 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500437 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800438 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700439 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700440
David Tolnaya454c8f2018-01-07 01:01:10 -0800441 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800442 ///
443 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800444 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500445 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500446 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500447 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700449
David Tolnaya454c8f2018-01-07 01:01:10 -0800450 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400451 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800452 /// This variant is important for faithfully representing the precedence
453 /// of expressions and is related to `None`-delimited spans in a
454 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800455 ///
456 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500457 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500458 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500459 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500460 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400461 }),
462
David Tolnaya454c8f2018-01-07 01:01:10 -0800463 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800464 ///
465 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400466 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500467 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800469 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700471
David Tolnay02a9c6f2018-08-24 18:58:45 -0400472 /// An async block: `async { ... }`.
473 ///
474 /// *This type is available if Syn is built with the `"full"` feature.*
475 pub Async(ExprAsync #full {
476 pub attrs: Vec<Attribute>,
477 pub async_token: Token![async],
478 pub capture: Option<Token![move]>,
479 pub block: Block,
480 }),
481
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400482 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400485 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400487 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub block: Block,
489 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800492 ///
493 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700494 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500495 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800496 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700497 pub expr: Option<Box<Expr>>,
498 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500499
David Tolnaya454c8f2018-01-07 01:01:10 -0800500 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800501 ///
502 /// *This type is available if Syn is built with the `"derive"` or
503 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500504 pub Verbatim(ExprVerbatim #manual_extra_traits {
505 pub tts: TokenStream,
506 }),
507 }
508}
509
510#[cfg(feature = "extra-traits")]
511impl Eq for ExprVerbatim {}
512
513#[cfg(feature = "extra-traits")]
514impl PartialEq for ExprVerbatim {
515 fn eq(&self, other: &Self) -> bool {
516 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
517 }
518}
519
520#[cfg(feature = "extra-traits")]
521impl Hash for ExprVerbatim {
522 fn hash<H>(&self, state: &mut H)
523 where
524 H: Hasher,
525 {
526 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700527 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700528}
529
David Tolnay8c91b882017-12-28 23:04:32 -0500530impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700531 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700532 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500533 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800534 Expr::Box(ExprBox { ref mut attrs, .. })
535 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
536 | Expr::Array(ExprArray { ref mut attrs, .. })
537 | Expr::Call(ExprCall { ref mut attrs, .. })
538 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
539 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
540 | Expr::Binary(ExprBinary { ref mut attrs, .. })
541 | Expr::Unary(ExprUnary { ref mut attrs, .. })
542 | Expr::Lit(ExprLit { ref mut attrs, .. })
543 | Expr::Cast(ExprCast { ref mut attrs, .. })
544 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700545 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800546 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800547 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800548 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
549 | Expr::Loop(ExprLoop { ref mut attrs, .. })
550 | Expr::Match(ExprMatch { ref mut attrs, .. })
551 | Expr::Closure(ExprClosure { ref mut attrs, .. })
552 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
553 | Expr::Block(ExprBlock { ref mut attrs, .. })
554 | Expr::Assign(ExprAssign { ref mut attrs, .. })
555 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
556 | Expr::Field(ExprField { ref mut attrs, .. })
557 | Expr::Index(ExprIndex { ref mut attrs, .. })
558 | Expr::Range(ExprRange { ref mut attrs, .. })
559 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200560 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800561 | Expr::Break(ExprBreak { ref mut attrs, .. })
562 | Expr::Continue(ExprContinue { ref mut attrs, .. })
563 | Expr::Return(ExprReturn { ref mut attrs, .. })
564 | Expr::Macro(ExprMacro { ref mut attrs, .. })
565 | Expr::Struct(ExprStruct { ref mut attrs, .. })
566 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
567 | Expr::Paren(ExprParen { ref mut attrs, .. })
568 | Expr::Group(ExprGroup { ref mut attrs, .. })
569 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400570 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400571 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800572 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700573 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500574 }
575 }
576}
577
David Tolnay85b69a42017-12-27 20:43:10 -0500578ast_enum! {
579 /// A struct or tuple struct field accessed in a struct literal or field
580 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800581 ///
582 /// *This type is available if Syn is built with the `"derive"` or `"full"`
583 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500584 pub enum Member {
585 /// A named field like `self.x`.
586 Named(Ident),
587 /// An unnamed field like `self.0`.
588 Unnamed(Index),
589 }
590}
591
David Tolnay85b69a42017-12-27 20:43:10 -0500592ast_struct! {
593 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800594 ///
595 /// *This type is available if Syn is built with the `"derive"` or `"full"`
596 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500597 pub struct Index #manual_extra_traits {
598 pub index: u32,
599 pub span: Span,
600 }
601}
602
David Tolnay14982012017-12-29 00:49:51 -0500603impl From<usize> for Index {
604 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700605 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500606 Index {
607 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700608 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500609 }
610 }
611}
612
613#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500614impl Eq for Index {}
615
David Tolnay14982012017-12-29 00:49:51 -0500616#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500617impl PartialEq for Index {
618 fn eq(&self, other: &Self) -> bool {
619 self.index == other.index
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500624impl Hash for Index {
625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.index.hash(state);
627 }
628}
629
630#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700631ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800632 /// The `::<>` explicit type parameters passed to a method call:
633 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800634 ///
635 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500636 pub struct MethodTurbofish {
637 pub colon2_token: Token![::],
638 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500639 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500640 pub gt_token: Token![>],
641 }
642}
643
644#[cfg(feature = "full")]
645ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800646 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800647 ///
648 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500649 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800650 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500651 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500653 ///
654 /// NOTE: Identity expressions are represented as Type arguments, as
655 /// they are indistinguishable syntactically.
656 Const(Expr),
657 }
658}
659
660#[cfg(feature = "full")]
661ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700662 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800663 ///
664 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700665 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500666 /// Attributes tagged on the field.
667 pub attrs: Vec<Attribute>,
668
669 /// Name or index of the field.
670 pub member: Member,
671
David Tolnay5d7098a2017-12-29 01:35:24 -0500672 /// The colon in `Struct { x: x }`. If written in shorthand like
673 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500674 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500675
Alex Crichton62a0a592017-05-22 13:58:53 -0700676 /// Value of the field.
677 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700678 }
David Tolnay055a7042016-10-02 19:23:54 -0700679}
680
Michael Layzell734adb42017-06-07 16:58:31 -0400681#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700682ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800683 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800684 ///
685 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500686 pub struct Label {
687 pub name: Lifetime,
688 pub colon_token: Token![:],
689 }
690}
691
692#[cfg(feature = "full")]
693ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800695 ///
696 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700697 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500698 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700699 /// Statements in a block
700 pub stmts: Vec<Stmt>,
701 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700702}
703
Michael Layzell734adb42017-06-07 16:58:31 -0400704#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700705ast_enum! {
706 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub enum Stmt {
710 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800711 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700712
Alex Crichton62a0a592017-05-22 13:58:53 -0700713 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800714 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700715
Alex Crichton62a0a592017-05-22 13:58:53 -0700716 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800717 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700718
David Tolnaya454c8f2018-01-07 01:01:10 -0800719 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800720 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700721 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700722}
723
Michael Layzell734adb42017-06-07 16:58:31 -0400724#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700725ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800726 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700729 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500730 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800731 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200732 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500733 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500734 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500735 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700737}
738
Michael Layzell734adb42017-06-07 16:58:31 -0400739#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700740ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A pattern in a local binding, function signature, match expression, or
742 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800743 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800744 /// *This type is available if Syn is built with the `"full"` feature.*
745 ///
David Tolnay614a0142018-01-07 10:25:43 -0800746 /// # Syntax tree enum
747 ///
748 /// This type is a [syntax tree enum].
749 ///
750 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700751 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800752 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800753 ///
754 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700755 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800756 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700757 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700758
David Tolnaya454c8f2018-01-07 01:01:10 -0800759 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800760 ///
761 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700762 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500763 pub by_ref: Option<Token![ref]>,
764 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500766 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700767 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700768
David Tolnaya454c8f2018-01-07 01:01:10 -0800769 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800770 ///
771 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700772 pub Struct(PatStruct {
773 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500774 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500775 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800776 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700777 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700778
David Tolnaya454c8f2018-01-07 01:01:10 -0800779 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800780 ///
781 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700782 pub TupleStruct(PatTupleStruct {
783 pub path: Path,
784 pub pat: PatTuple,
785 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700786
David Tolnaya454c8f2018-01-07 01:01:10 -0800787 /// A path pattern like `Color::Red`, optionally qualified with a
788 /// self-type.
789 ///
Daniel Muellerd3d71a12019-01-28 06:10:46 -0800790 /// Unqualified path patterns can legally refer to variants, structs,
791 /// constants or associated constants. Qualified path patterns like
David Tolnaya454c8f2018-01-07 01:01:10 -0800792 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
793 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800794 ///
795 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700796 pub Path(PatPath {
797 pub qself: Option<QSelf>,
798 pub path: Path,
799 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700800
David Tolnaya454c8f2018-01-07 01:01:10 -0800801 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800802 ///
803 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500805 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500806 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500807 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500808 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500809 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700810 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800811
812 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800813 ///
814 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800816 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500817 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700818 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800819
820 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800821 ///
822 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700823 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800824 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500825 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500826 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800828
829 /// A literal pattern: `0`.
830 ///
831 /// This holds an `Expr` rather than a `Lit` because negative numbers
832 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800833 ///
834 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700835 pub Lit(PatLit {
836 pub expr: Box<Expr>,
837 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800838
839 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800840 ///
841 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700842 pub Range(PatRange {
843 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700844 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500845 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800847
848 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800849 ///
850 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700851 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500852 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500855 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500856 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500857 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700858 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800859
860 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800861 ///
862 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500863 pub Macro(PatMacro {
864 pub mac: Macro,
865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500870 pub Verbatim(PatVerbatim #manual_extra_traits {
871 pub tts: TokenStream,
872 }),
873 }
874}
875
David Tolnayc43b44e2017-12-30 23:55:54 -0500876#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500877impl Eq for PatVerbatim {}
878
David Tolnayc43b44e2017-12-30 23:55:54 -0500879#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500880impl PartialEq for PatVerbatim {
881 fn eq(&self, other: &Self) -> bool {
882 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
883 }
884}
885
David Tolnayc43b44e2017-12-30 23:55:54 -0500886#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500887impl Hash for PatVerbatim {
888 fn hash<H>(&self, state: &mut H)
889 where
890 H: Hasher,
891 {
892 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700893 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700894}
895
Michael Layzell734adb42017-06-07 16:58:31 -0400896#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700897ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800898 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700899 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800900 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700901 ///
David Tolnay95989db2019-01-01 15:05:57 -0500902 /// ```edition2018
David Tolnaya454c8f2018-01-07 01:01:10 -0800903 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500904 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700905 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800906 /// 0...10 => {
907 /// return true;
908 /// }
909 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500910 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700911 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800912 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500913 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700914 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700917 pub struct Arm {
918 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200919 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500920 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500921 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200922 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700923 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800924 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700925 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700926}
927
Michael Layzell734adb42017-06-07 16:58:31 -0400928#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700929ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800930 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800931 ///
932 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700933 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700934 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800935 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800936 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800937 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800938 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700939 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700940}
941
Michael Layzell734adb42017-06-07 16:58:31 -0400942#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700943ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800944 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700945 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800946 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
947 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
David Tolnay461d98e2018-01-07 11:07:19 -0800948 ///
949 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700950 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500951 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500952 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500953 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700954 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700956}
957
Michael Layzell3936ceb2017-07-08 00:28:36 -0400958#[cfg(any(feature = "parsing", feature = "printing"))]
959#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700960fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700961 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500962 match *expr {
963 Expr::Unsafe(..)
964 | Expr::Block(..)
965 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500966 | Expr::Match(..)
967 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500968 | Expr::Loop(..)
969 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400970 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400971 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700972 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400973 }
974}
975
David Tolnayb9c8e322016-09-23 20:48:37 -0700976#[cfg(feature = "parsing")]
977pub mod parsing {
978 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700979
Michael Layzell734adb42017-06-07 16:58:31 -0400980 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -0700981 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -0700982 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -0700983 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700984
David Tolnaybcf26022017-12-25 22:10:52 -0500985 // When we're parsing expressions which occur before blocks, like in an if
986 // statement's condition, we cannot parse a struct literal.
987 //
988 // Struct literals are ambiguous in certain positions
989 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -0700990 #[derive(Copy, Clone)]
991 pub struct AllowStruct(bool);
992
David Tolnay01218d12018-08-29 18:13:07 -0700993 #[derive(Copy, Clone, PartialEq, PartialOrd)]
994 enum Precedence {
995 Any,
996 Assign,
997 Placement,
998 Range,
999 Or,
1000 And,
1001 Compare,
1002 BitOr,
1003 BitXor,
1004 BitAnd,
1005 Shift,
1006 Arithmetic,
1007 Term,
1008 Cast,
1009 }
1010
1011 impl Precedence {
1012 fn of(op: &BinOp) -> Self {
1013 match *op {
1014 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1015 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1016 BinOp::And(_) => Precedence::And,
1017 BinOp::Or(_) => Precedence::Or,
1018 BinOp::BitXor(_) => Precedence::BitXor,
1019 BinOp::BitAnd(_) => Precedence::BitAnd,
1020 BinOp::BitOr(_) => Precedence::BitOr,
1021 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001022 BinOp::Eq(_)
1023 | BinOp::Lt(_)
1024 | BinOp::Le(_)
1025 | BinOp::Ne(_)
1026 | BinOp::Ge(_)
1027 | BinOp::Gt(_) => Precedence::Compare,
1028 BinOp::AddEq(_)
1029 | BinOp::SubEq(_)
1030 | BinOp::MulEq(_)
1031 | BinOp::DivEq(_)
1032 | BinOp::RemEq(_)
1033 | BinOp::BitXorEq(_)
1034 | BinOp::BitAndEq(_)
1035 | BinOp::BitOrEq(_)
1036 | BinOp::ShlEq(_)
1037 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001038 }
1039 }
1040 }
1041
David Tolnay9389c382018-08-27 09:13:37 -07001042 impl Parse for Expr {
1043 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001044 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001045 }
1046 }
1047
Michael Layzell734adb42017-06-07 16:58:31 -04001048 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001049 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001050 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001051 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001052
David Tolnay01218d12018-08-29 18:13:07 -07001053 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001054 fn parse_expr(
1055 input: ParseStream,
1056 mut lhs: Expr,
1057 allow_struct: AllowStruct,
1058 base: Precedence,
1059 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001060 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001061 if input
1062 .fork()
1063 .parse::<BinOp>()
1064 .ok()
1065 .map_or(false, |op| Precedence::of(&op) >= base)
1066 {
David Tolnay01218d12018-08-29 18:13:07 -07001067 let op: BinOp = input.parse()?;
1068 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001069 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001070 loop {
1071 let next = peek_precedence(input);
1072 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001073 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001074 } else {
1075 break;
1076 }
1077 }
David Tolnay90276252018-08-31 10:50:08 -07001078 lhs = if precedence == Precedence::Assign {
1079 Expr::AssignOp(ExprAssignOp {
1080 attrs: Vec::new(),
1081 left: Box::new(lhs),
1082 op: op,
1083 right: Box::new(rhs),
1084 })
1085 } else {
1086 Expr::Binary(ExprBinary {
1087 attrs: Vec::new(),
1088 left: Box::new(lhs),
1089 op: op,
1090 right: Box::new(rhs),
1091 })
1092 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001093 } else if Precedence::Assign >= base
1094 && input.peek(Token![=])
1095 && !input.peek(Token![==])
1096 && !input.peek(Token![=>])
1097 {
David Tolnay01218d12018-08-29 18:13:07 -07001098 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001099 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001100 loop {
1101 let next = peek_precedence(input);
1102 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001103 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001104 } else {
1105 break;
1106 }
1107 }
1108 lhs = Expr::Assign(ExprAssign {
1109 attrs: Vec::new(),
1110 left: Box::new(lhs),
1111 eq_token: eq_token,
1112 right: Box::new(rhs),
1113 });
1114 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1115 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001116 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001117 loop {
1118 let next = peek_precedence(input);
1119 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001120 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001121 } else {
1122 break;
1123 }
1124 }
1125 lhs = Expr::InPlace(ExprInPlace {
1126 attrs: Vec::new(),
1127 place: Box::new(lhs),
1128 arrow_token: arrow_token,
1129 value: Box::new(rhs),
1130 });
1131 } else if Precedence::Range >= base && input.peek(Token![..]) {
1132 let limits: RangeLimits = input.parse()?;
1133 let rhs = if input.is_empty()
1134 || input.peek(Token![,])
1135 || input.peek(Token![;])
1136 || !allow_struct.0 && input.peek(token::Brace)
1137 {
1138 None
1139 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001140 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001141 loop {
1142 let next = peek_precedence(input);
1143 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001144 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001145 } else {
1146 break;
1147 }
1148 }
1149 Some(rhs)
1150 };
1151 lhs = Expr::Range(ExprRange {
1152 attrs: Vec::new(),
1153 from: Some(Box::new(lhs)),
1154 limits: limits,
1155 to: rhs.map(Box::new),
1156 });
1157 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1158 let as_token: Token![as] = input.parse()?;
1159 let ty = input.call(Type::without_plus)?;
1160 lhs = Expr::Cast(ExprCast {
1161 attrs: Vec::new(),
1162 expr: Box::new(lhs),
1163 as_token: as_token,
1164 ty: Box::new(ty),
1165 });
1166 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1167 let colon_token: Token![:] = input.parse()?;
1168 let ty = input.call(Type::without_plus)?;
1169 lhs = Expr::Type(ExprType {
1170 attrs: Vec::new(),
1171 expr: Box::new(lhs),
1172 colon_token: colon_token,
1173 ty: Box::new(ty),
1174 });
1175 } else {
1176 break;
1177 }
1178 }
1179 Ok(lhs)
1180 }
1181
David Tolnay3e541292018-08-30 11:42:15 -07001182 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001183 fn parse_expr(
1184 input: ParseStream,
1185 mut lhs: Expr,
1186 allow_struct: AllowStruct,
1187 base: Precedence,
1188 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001189 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001190 if input
1191 .fork()
1192 .parse::<BinOp>()
1193 .ok()
1194 .map_or(false, |op| Precedence::of(&op) >= base)
1195 {
David Tolnay3e541292018-08-30 11:42:15 -07001196 let op: BinOp = input.parse()?;
1197 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001198 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001199 loop {
1200 let next = peek_precedence(input);
1201 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001202 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001203 } else {
1204 break;
1205 }
1206 }
1207 lhs = Expr::Binary(ExprBinary {
1208 attrs: Vec::new(),
1209 left: Box::new(lhs),
1210 op: op,
1211 right: Box::new(rhs),
1212 });
1213 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1214 let as_token: Token![as] = input.parse()?;
1215 let ty = input.call(Type::without_plus)?;
1216 lhs = Expr::Cast(ExprCast {
1217 attrs: Vec::new(),
1218 expr: Box::new(lhs),
1219 as_token: as_token,
1220 ty: Box::new(ty),
1221 });
1222 } else {
1223 break;
1224 }
1225 }
1226 Ok(lhs)
1227 }
1228
David Tolnay01218d12018-08-29 18:13:07 -07001229 fn peek_precedence(input: ParseStream) -> Precedence {
1230 if let Ok(op) = input.fork().parse() {
1231 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001232 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001233 Precedence::Assign
1234 } else if input.peek(Token![<-]) {
1235 Precedence::Placement
1236 } else if input.peek(Token![..]) {
1237 Precedence::Range
1238 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1239 Precedence::Cast
1240 } else {
1241 Precedence::Any
1242 }
1243 }
1244
David Tolnaybcf26022017-12-25 22:10:52 -05001245 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001246 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001247 let lhs = unary_expr(input, allow_struct)?;
1248 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001249 }
1250
David Tolnaybcf26022017-12-25 22:10:52 -05001251 // <UnOp> <trailer>
1252 // & <trailer>
1253 // &mut <trailer>
1254 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001255 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001256 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001257 let ahead = input.fork();
1258 ahead.call(Attribute::parse_outer)?;
1259 if ahead.peek(Token![&])
1260 || ahead.peek(Token![box])
1261 || ahead.peek(Token![*])
1262 || ahead.peek(Token![!])
1263 || ahead.peek(Token![-])
1264 {
1265 let attrs = input.call(Attribute::parse_outer)?;
1266 if input.peek(Token![&]) {
1267 Ok(Expr::Reference(ExprReference {
1268 attrs: attrs,
1269 and_token: input.parse()?,
1270 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001271 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001272 }))
1273 } else if input.peek(Token![box]) {
1274 Ok(Expr::Box(ExprBox {
1275 attrs: attrs,
1276 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001277 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001278 }))
1279 } else {
1280 Ok(Expr::Unary(ExprUnary {
1281 attrs: attrs,
1282 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001283 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001284 }))
1285 }
1286 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001287 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001288 }
1289 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001290
Michael Layzell734adb42017-06-07 16:58:31 -04001291 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001292 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001293 let ahead = input.fork();
1294 ahead.call(Attribute::parse_outer)?;
1295 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1296 Ok(Expr::Unary(ExprUnary {
1297 attrs: input.call(Attribute::parse_outer)?,
1298 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001299 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001300 }))
1301 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001302 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001303 }
1304 }
Michael Layzell734adb42017-06-07 16:58:31 -04001305
David Tolnaybcf26022017-12-25 22:10:52 -05001306 // <atom> (..<args>) ...
1307 // <atom> . <ident> (..<args>) ...
1308 // <atom> . <ident> ...
1309 // <atom> . <lit> ...
1310 // <atom> [ <expr> ] ...
1311 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001312 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001313 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001314 if input.peek(token::Group) {
1315 return input.call(expr_group).map(Expr::Group);
1316 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001317
David Tolnay577fd312018-09-01 02:26:40 -07001318 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001319
David Tolnay577fd312018-09-01 02:26:40 -07001320 let atom = atom_expr(input, allow_struct)?;
1321 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001322
David Tolnay577fd312018-09-01 02:26:40 -07001323 let inner_attrs = e.replace_attrs(Vec::new());
1324 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001325 e.replace_attrs(attrs);
1326 Ok(e)
1327 }
1328
1329 #[cfg(feature = "full")]
1330 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001331 loop {
1332 if input.peek(token::Paren) {
1333 let content;
1334 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001335 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001336 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001337 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001338 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001339 });
1340 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1341 let dot_token: Token![.] = input.parse()?;
1342 let member: Member = input.parse()?;
1343 let turbofish = if member.is_named() && input.peek(Token![::]) {
1344 Some(MethodTurbofish {
1345 colon2_token: input.parse()?,
1346 lt_token: input.parse()?,
1347 args: {
1348 let mut args = Punctuated::new();
1349 loop {
1350 if input.peek(Token![>]) {
1351 break;
1352 }
David Tolnay310b3262018-08-30 15:33:00 -07001353 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001354 args.push_value(value);
1355 if input.peek(Token![>]) {
1356 break;
1357 }
1358 let punct = input.parse()?;
1359 args.push_punct(punct);
1360 }
1361 args
1362 },
1363 gt_token: input.parse()?,
1364 })
1365 } else {
1366 None
1367 };
1368
1369 if turbofish.is_some() || input.peek(token::Paren) {
1370 if let Member::Named(method) = member {
1371 let content;
1372 e = Expr::MethodCall(ExprMethodCall {
1373 attrs: Vec::new(),
1374 receiver: Box::new(e),
1375 dot_token: dot_token,
1376 method: method,
1377 turbofish: turbofish,
1378 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001379 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001380 });
1381 continue;
1382 }
1383 }
1384
1385 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001386 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001387 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001388 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001389 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001390 });
1391 } else if input.peek(token::Bracket) {
1392 let content;
1393 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001394 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001395 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001396 bracket_token: bracketed!(content in input),
1397 index: content.parse()?,
1398 });
1399 } else if input.peek(Token![?]) {
1400 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001401 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001402 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001403 question_token: input.parse()?,
1404 });
1405 } else {
1406 break;
1407 }
1408 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001409 Ok(e)
1410 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001411
Michael Layzell734adb42017-06-07 16:58:31 -04001412 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001413 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001414 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001415
1416 loop {
1417 if input.peek(token::Paren) {
1418 let content;
1419 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001420 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001421 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001422 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001423 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001424 });
1425 } else if input.peek(Token![.]) {
1426 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001427 attrs: Vec::new(),
1428 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001429 dot_token: input.parse()?,
1430 member: input.parse()?,
1431 });
1432 } else if input.peek(token::Bracket) {
1433 let content;
1434 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001435 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001436 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001437 bracket_token: bracketed!(content in input),
1438 index: content.parse()?,
1439 });
1440 } else {
1441 break;
1442 }
1443 }
1444
1445 Ok(e)
1446 }
Michael Layzell734adb42017-06-07 16:58:31 -04001447
David Tolnaya454c8f2018-01-07 01:01:10 -08001448 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001449 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001450 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001451 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001452 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001453 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001454 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001455 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001456 } else if input.peek(Token![async])
1457 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1458 {
David Tolnay577fd312018-09-01 02:26:40 -07001459 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001460 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001461 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001462 } else if input.peek(Token![|])
1463 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1464 || input.peek(Token![static])
1465 || input.peek(Token![move])
1466 {
David Tolnay577fd312018-09-01 02:26:40 -07001467 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001468 } else if input.peek(Ident)
1469 || input.peek(Token![::])
1470 || input.peek(Token![<])
1471 || input.peek(Token![self])
1472 || input.peek(Token![Self])
1473 || input.peek(Token![super])
1474 || input.peek(Token![extern])
1475 || input.peek(Token![crate])
1476 {
David Tolnay577fd312018-09-01 02:26:40 -07001477 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001478 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001479 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001481 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001482 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001483 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001484 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001485 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001486 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001487 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001488 } else if input.peek(Token![let]) {
1489 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001490 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001491 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001493 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001495 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001496 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001497 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001499 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001501 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001502 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001503 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001504 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001505 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001506 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001507 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001508 } else if input.peek(Lifetime) {
1509 let the_label: Label = input.parse()?;
1510 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001511 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001512 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001513 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001515 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001516 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001517 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 } else {
1519 return Err(input.error("expected loop or block expression"));
1520 };
1521 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001522 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001523 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1524 | Expr::Loop(ExprLoop { ref mut label, .. })
1525 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001526 _ => unreachable!(),
1527 }
David Tolnay577fd312018-09-01 02:26:40 -07001528 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001530 Err(input.error("expected expression"))
1531 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001532 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001533
Michael Layzell734adb42017-06-07 16:58:31 -04001534 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001535 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001536 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001537 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001539 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 } else if input.peek(Ident)
1541 || input.peek(Token![::])
1542 || input.peek(Token![<])
1543 || input.peek(Token![self])
1544 || input.peek(Token![Self])
1545 || input.peek(Token![super])
1546 || input.peek(Token![extern])
1547 || input.peek(Token![crate])
1548 {
1549 input.parse().map(Expr::Path)
1550 } else {
1551 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1552 }
1553 }
1554
1555 #[cfg(feature = "full")]
1556 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1557 let expr: ExprPath = input.parse()?;
1558 if expr.qself.is_some() {
1559 return Ok(Expr::Path(expr));
1560 }
1561
1562 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1563 let mut contains_arguments = false;
1564 for segment in &expr.path.segments {
1565 match segment.arguments {
1566 PathArguments::None => {}
1567 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1568 contains_arguments = true;
1569 }
1570 }
1571 }
1572
1573 if !contains_arguments {
1574 let bang_token: Token![!] = input.parse()?;
1575 let (delimiter, tts) = mac::parse_delimiter(input)?;
1576 return Ok(Expr::Macro(ExprMacro {
1577 attrs: Vec::new(),
1578 mac: Macro {
1579 path: expr.path,
1580 bang_token: bang_token,
1581 delimiter: delimiter,
1582 tts: tts,
1583 },
1584 }));
1585 }
1586 }
1587
1588 if allow_struct.0 && input.peek(token::Brace) {
1589 let outer_attrs = Vec::new();
1590 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1591 } else {
1592 Ok(Expr::Path(expr))
1593 }
1594 }
1595
1596 #[cfg(feature = "full")]
1597 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1598 let content;
1599 let paren_token = parenthesized!(content in input);
1600 let inner_attrs = content.call(Attribute::parse_inner)?;
1601 if content.is_empty() {
1602 return Ok(Expr::Tuple(ExprTuple {
1603 attrs: inner_attrs,
1604 paren_token: paren_token,
1605 elems: Punctuated::new(),
1606 }));
1607 }
1608
1609 let first: Expr = content.parse()?;
1610 if content.is_empty() {
1611 return Ok(Expr::Paren(ExprParen {
1612 attrs: inner_attrs,
1613 paren_token: paren_token,
1614 expr: Box::new(first),
1615 }));
1616 }
1617
1618 let mut elems = Punctuated::new();
1619 elems.push_value(first);
1620 while !content.is_empty() {
1621 let punct = content.parse()?;
1622 elems.push_punct(punct);
1623 if content.is_empty() {
1624 break;
1625 }
1626 let value = content.parse()?;
1627 elems.push_value(value);
1628 }
1629 Ok(Expr::Tuple(ExprTuple {
1630 attrs: inner_attrs,
1631 paren_token: paren_token,
1632 elems: elems,
1633 }))
1634 }
1635
1636 #[cfg(feature = "full")]
1637 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1638 let content;
1639 let bracket_token = bracketed!(content in input);
1640 let inner_attrs = content.call(Attribute::parse_inner)?;
1641 if content.is_empty() {
1642 return Ok(Expr::Array(ExprArray {
1643 attrs: inner_attrs,
1644 bracket_token: bracket_token,
1645 elems: Punctuated::new(),
1646 }));
1647 }
1648
1649 let first: Expr = content.parse()?;
1650 if content.is_empty() || content.peek(Token![,]) {
1651 let mut elems = Punctuated::new();
1652 elems.push_value(first);
1653 while !content.is_empty() {
1654 let punct = content.parse()?;
1655 elems.push_punct(punct);
1656 if content.is_empty() {
1657 break;
1658 }
1659 let value = content.parse()?;
1660 elems.push_value(value);
1661 }
1662 Ok(Expr::Array(ExprArray {
1663 attrs: inner_attrs,
1664 bracket_token: bracket_token,
1665 elems: elems,
1666 }))
1667 } else if content.peek(Token![;]) {
1668 let semi_token: Token![;] = content.parse()?;
1669 let len: Expr = content.parse()?;
1670 Ok(Expr::Repeat(ExprRepeat {
1671 attrs: inner_attrs,
1672 bracket_token: bracket_token,
1673 expr: Box::new(first),
1674 semi_token: semi_token,
1675 len: Box::new(len),
1676 }))
1677 } else {
1678 Err(content.error("expected `,` or `;`"))
1679 }
1680 }
Michael Layzell734adb42017-06-07 16:58:31 -04001681
Michael Layzell734adb42017-06-07 16:58:31 -04001682 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001683 fn expr_early(input: ParseStream) -> Result<Expr> {
1684 let mut attrs = input.call(Attribute::parse_outer)?;
1685 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001686 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001687 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001688 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001689 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001690 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001691 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001692 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001693 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001694 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001695 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001696 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001697 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001698 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001699 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001700 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001701 } else {
1702 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001703 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001704
1705 attrs.extend(expr.replace_attrs(Vec::new()));
1706 expr.replace_attrs(attrs);
1707
David Tolnay7d2e1db2018-08-30 11:49:04 -07001708 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001709 };
1710
1711 if input.peek(Token![.]) || input.peek(Token![?]) {
1712 expr = trailer_helper(input, expr)?;
1713
1714 attrs.extend(expr.replace_attrs(Vec::new()));
1715 expr.replace_attrs(attrs);
1716
1717 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001718 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001719 }
1720
1721 attrs.extend(expr.replace_attrs(Vec::new()));
1722 expr.replace_attrs(attrs);
1723 Ok(expr)
1724 }
Michael Layzell35418782017-06-07 09:20:25 -04001725
Peter Hall04f42792019-04-02 16:58:45 +02001726 impl Parse for ExprLit {
1727 fn parse(input: ParseStream) -> Result<Self> {
1728 Ok(ExprLit {
1729 attrs: Vec::new(),
1730 lit: input.parse()?,
1731 })
1732 }
David Tolnay8c91b882017-12-28 23:04:32 -05001733 }
1734
1735 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001736 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001737 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001738 Ok(ExprGroup {
1739 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001740 group_token: group.token,
1741 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001742 })
1743 }
1744
1745 #[cfg(not(feature = "full"))]
1746 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1747 let content;
1748 Ok(ExprParen {
1749 attrs: Vec::new(),
1750 paren_token: parenthesized!(content in input),
1751 expr: content.parse()?,
1752 })
David Tolnay8c91b882017-12-28 23:04:32 -05001753 }
1754
David Tolnaye98775f2017-12-28 23:17:00 -05001755 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001756 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001757 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001758 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001759 }
1760
1761 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001762 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1763 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001764 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001765 let_token: input.parse()?,
1766 pats: {
1767 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001768 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001769 let value: Pat = input.parse()?;
1770 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001771 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001772 let punct = input.parse()?;
1773 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001774 let value: Pat = input.parse()?;
1775 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001776 }
1777 pats
1778 },
1779 eq_token: input.parse()?,
1780 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001781 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001782 }
1783
Michael Layzell734adb42017-06-07 16:58:31 -04001784 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001785 impl Parse for ExprIf {
1786 fn parse(input: ParseStream) -> Result<Self> {
1787 Ok(ExprIf {
1788 attrs: Vec::new(),
1789 if_token: input.parse()?,
1790 cond: Box::new(input.call(expr_no_struct)?),
1791 then_branch: input.parse()?,
1792 else_branch: {
1793 if input.peek(Token![else]) {
1794 Some(input.call(else_block)?)
1795 } else {
1796 None
1797 }
1798 },
1799 })
1800 }
Alex Crichton954046c2017-05-30 21:49:42 -07001801 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001802
Michael Layzell734adb42017-06-07 16:58:31 -04001803 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001804 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1805 let else_token: Token![else] = input.parse()?;
1806
1807 let lookahead = input.lookahead1();
1808 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001809 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001810 } else if input.peek(token::Brace) {
1811 Expr::Block(ExprBlock {
1812 attrs: Vec::new(),
1813 label: None,
1814 block: input.parse()?,
1815 })
1816 } else {
1817 return Err(lookahead.error());
1818 };
1819
1820 Ok((else_token, Box::new(else_branch)))
1821 }
David Tolnay939766a2016-09-23 23:48:12 -07001822
Michael Layzell734adb42017-06-07 16:58:31 -04001823 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001824 impl Parse for ExprForLoop {
1825 fn parse(input: ParseStream) -> Result<Self> {
1826 let label: Option<Label> = input.parse()?;
1827 let for_token: Token![for] = input.parse()?;
1828 let pat: Pat = input.parse()?;
1829 let in_token: Token![in] = input.parse()?;
1830 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001831
Peter Hall04f42792019-04-02 16:58:45 +02001832 let content;
1833 let brace_token = braced!(content in input);
1834 let inner_attrs = content.call(Attribute::parse_inner)?;
1835 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001836
Peter Hall04f42792019-04-02 16:58:45 +02001837 Ok(ExprForLoop {
1838 attrs: inner_attrs,
1839 label: label,
1840 for_token: for_token,
1841 pat: Box::new(pat),
1842 in_token: in_token,
1843 expr: Box::new(expr),
1844 body: Block {
1845 brace_token: brace_token,
1846 stmts: stmts,
1847 },
1848 })
1849 }
Alex Crichton954046c2017-05-30 21:49:42 -07001850 }
David Tolnay1978c672016-10-27 22:05:52 -07001851
Michael Layzell734adb42017-06-07 16:58:31 -04001852 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001853 impl Parse for ExprLoop {
1854 fn parse(input: ParseStream) -> Result<Self> {
1855 let label: Option<Label> = input.parse()?;
1856 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001857
Peter Hall04f42792019-04-02 16:58:45 +02001858 let content;
1859 let brace_token = braced!(content in input);
1860 let inner_attrs = content.call(Attribute::parse_inner)?;
1861 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001862
Peter Hall04f42792019-04-02 16:58:45 +02001863 Ok(ExprLoop {
1864 attrs: inner_attrs,
1865 label: label,
1866 loop_token: loop_token,
1867 body: Block {
1868 brace_token: brace_token,
1869 stmts: stmts,
1870 },
1871 })
1872 }
Alex Crichton954046c2017-05-30 21:49:42 -07001873 }
Arnavion02ef13f2017-04-25 00:54:31 -07001874
Michael Layzell734adb42017-06-07 16:58:31 -04001875 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001876 impl Parse for ExprMatch {
1877 fn parse(input: ParseStream) -> Result<Self> {
1878 let match_token: Token![match] = input.parse()?;
1879 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001880
Peter Hall55f00f72019-04-02 16:50:57 +02001881 let content;
1882 let brace_token = braced!(content in input);
1883 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001884
Peter Hall55f00f72019-04-02 16:50:57 +02001885 let mut arms = Vec::new();
1886 while !content.is_empty() {
1887 arms.push(content.call(Arm::parse)?);
1888 }
1889
1890 Ok(ExprMatch {
1891 attrs: inner_attrs,
1892 match_token: match_token,
1893 expr: Box::new(expr),
1894 brace_token: brace_token,
1895 arms: arms,
1896 })
David Tolnay310b3262018-08-30 15:33:00 -07001897 }
David Tolnay310b3262018-08-30 15:33:00 -07001898 }
1899
bstriecde20e62019-05-05 13:29:15 -04001900 macro_rules! impl_by_parsing_expr {
David Tolnaye957eb62019-05-07 22:02:51 -07001901 (
1902 $(
1903 $expr_type:ty, $variant:ident, $msg:expr,
1904 )*
1905 ) => {
1906 $(
1907 #[cfg(all(feature = "full", feature = "printing"))]
1908 impl Parse for $expr_type {
1909 fn parse(input: ParseStream) -> Result<Self> {
1910 let mut expr: Expr = input.parse()?;
1911 loop {
1912 match expr {
1913 Expr::$variant(inner) => return Ok(inner),
1914 Expr::Group(next) => expr = *next.expr,
1915 _ => return Err(Error::new_spanned(expr, $msg)),
1916 }
bstrie1626c372019-05-05 13:44:57 -04001917 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001918 }
1919 }
David Tolnaye957eb62019-05-07 22:02:51 -07001920 )*
David Tolnaya58223d2019-05-07 21:58:15 -07001921 };
bstrie7b4f52d2019-04-30 18:44:21 -04001922 }
1923
David Tolnaye957eb62019-05-07 22:02:51 -07001924 impl_by_parsing_expr! {
1925 ExprBox, Box, "expected box expression",
1926 ExprInPlace, InPlace, "expected placement expression",
1927 ExprArray, Array, "expected slice literal expression",
1928 ExprCall, Call, "expected function call expression",
1929 ExprMethodCall, MethodCall, "expected method call expression",
1930 ExprTuple, Tuple, "expected tuple expression",
1931 ExprBinary, Binary, "expected binary operation",
1932 ExprUnary, Unary, "expected unary operation",
1933 ExprCast, Cast, "expected cast expression",
1934 ExprType, Type, "expected type ascription expression",
1935 ExprLet, Let, "expected let guard",
1936 ExprClosure, Closure, "expected closure expression",
1937 ExprUnsafe, Unsafe, "expected unsafe block",
1938 ExprBlock, Block, "expected blocked scope",
1939 ExprAssign, Assign, "expected assignment expression",
1940 ExprAssignOp, AssignOp, "expected compound assignment expression",
1941 ExprField, Field, "expected struct field access",
1942 ExprIndex, Index, "expected indexing expression",
1943 ExprRange, Range, "expected range expression",
1944 ExprReference, Reference, "expected referencing operation",
1945 ExprBreak, Break, "expected break expression",
1946 ExprContinue, Continue, "expected continue expression",
1947 ExprReturn, Return, "expected return expression",
1948 ExprMacro, Macro, "expected macro invocation expression",
1949 ExprStruct, Struct, "expected struct literal expression",
1950 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
1951 ExprParen, Paren, "expected parenthesized expression",
1952 ExprTry, Try, "expected try expression",
1953 ExprAsync, Async, "expected async block",
1954 ExprTryBlock, TryBlock, "expected try block",
1955 ExprYield, Yield, "expected yield expression",
1956 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001957
David Tolnay310b3262018-08-30 15:33:00 -07001958 #[cfg(feature = "full")]
1959 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1960 Ok(ExprTryBlock {
1961 attrs: Vec::new(),
1962 try_token: input.parse()?,
1963 block: input.parse()?,
1964 })
1965 }
1966
1967 #[cfg(feature = "full")]
1968 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1969 Ok(ExprYield {
1970 attrs: Vec::new(),
1971 yield_token: input.parse()?,
1972 expr: {
1973 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1974 Some(input.parse()?)
1975 } else {
1976 None
1977 }
1978 },
1979 })
1980 }
1981
1982 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001983 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001984 let asyncness: Option<Token![async]> = input.parse()?;
1985 let movability: Option<Token![static]> = if asyncness.is_none() {
1986 input.parse()?
1987 } else {
1988 None
1989 };
1990 let capture: Option<Token![move]> = input.parse()?;
1991 let or1_token: Token![|] = input.parse()?;
1992
1993 let mut inputs = Punctuated::new();
1994 loop {
1995 if input.peek(Token![|]) {
1996 break;
1997 }
1998 let value = fn_arg(input)?;
1999 inputs.push_value(value);
2000 if input.peek(Token![|]) {
2001 break;
2002 }
2003 let punct: Token![,] = input.parse()?;
2004 inputs.push_punct(punct);
2005 }
2006
2007 let or2_token: Token![|] = input.parse()?;
2008
2009 let (output, body) = if input.peek(Token![->]) {
2010 let arrow_token: Token![->] = input.parse()?;
2011 let ty: Type = input.parse()?;
2012 let body: Block = input.parse()?;
2013 let output = ReturnType::Type(arrow_token, Box::new(ty));
2014 let block = Expr::Block(ExprBlock {
2015 attrs: Vec::new(),
2016 label: None,
2017 block: body,
2018 });
2019 (output, block)
2020 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002021 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002022 (ReturnType::Default, body)
2023 };
2024
2025 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002026 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002027 asyncness: asyncness,
2028 movability: movability,
2029 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002030 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002031 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002032 or2_token: or2_token,
2033 output: output,
2034 body: Box::new(body),
2035 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002036 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002037
2038 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002039 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2040 Ok(ExprAsync {
2041 attrs: Vec::new(),
2042 async_token: input.parse()?,
2043 capture: input.parse()?,
2044 block: input.parse()?,
2045 })
David Tolnay60291082018-08-28 09:54:49 -07002046 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002047
Michael Layzell734adb42017-06-07 16:58:31 -04002048 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002049 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2050 let pat: Pat = input.parse()?;
2051
2052 if input.peek(Token![:]) {
2053 Ok(FnArg::Captured(ArgCaptured {
2054 pat: pat,
2055 colon_token: input.parse()?,
2056 ty: input.parse()?,
2057 }))
2058 } else {
2059 Ok(FnArg::Inferred(pat))
2060 }
2061 }
2062
2063 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002064 impl Parse for ExprWhile {
2065 fn parse(input: ParseStream) -> Result<Self> {
2066 let label: Option<Label> = input.parse()?;
2067 let while_token: Token![while] = input.parse()?;
2068 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002069
Peter Hall04f42792019-04-02 16:58:45 +02002070 let content;
2071 let brace_token = braced!(content in input);
2072 let inner_attrs = content.call(Attribute::parse_inner)?;
2073 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002074
Peter Hall04f42792019-04-02 16:58:45 +02002075 Ok(ExprWhile {
2076 attrs: inner_attrs,
2077 label: label,
2078 while_token: while_token,
2079 cond: Box::new(cond),
2080 body: Block {
2081 brace_token: brace_token,
2082 stmts: stmts,
2083 },
2084 })
2085 }
Alex Crichton954046c2017-05-30 21:49:42 -07002086 }
2087
Michael Layzell734adb42017-06-07 16:58:31 -04002088 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002089 impl Parse for Label {
2090 fn parse(input: ParseStream) -> Result<Self> {
2091 Ok(Label {
2092 name: input.parse()?,
2093 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002094 })
David Tolnay60291082018-08-28 09:54:49 -07002095 }
Alex Crichton954046c2017-05-30 21:49:42 -07002096 }
2097
Michael Layzell734adb42017-06-07 16:58:31 -04002098 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002099 impl Parse for Option<Label> {
2100 fn parse(input: ParseStream) -> Result<Self> {
2101 if input.peek(Lifetime) {
2102 input.parse().map(Some)
2103 } else {
2104 Ok(None)
2105 }
2106 }
2107 }
2108
2109 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002110 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2111 Ok(ExprContinue {
2112 attrs: Vec::new(),
2113 continue_token: input.parse()?,
2114 label: input.parse()?,
2115 })
Alex Crichton954046c2017-05-30 21:49:42 -07002116 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002117
Michael Layzell734adb42017-06-07 16:58:31 -04002118 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002119 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2120 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002121 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002122 break_token: input.parse()?,
2123 label: input.parse()?,
2124 expr: {
2125 if input.is_empty()
2126 || input.peek(Token![,])
2127 || input.peek(Token![;])
2128 || !allow_struct.0 && input.peek(token::Brace)
2129 {
2130 None
2131 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002132 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002133 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002134 }
David Tolnay60291082018-08-28 09:54:49 -07002135 },
2136 })
Alex Crichton954046c2017-05-30 21:49:42 -07002137 }
2138
Michael Layzell734adb42017-06-07 16:58:31 -04002139 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002140 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2141 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002142 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002143 return_token: input.parse()?,
2144 expr: {
2145 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2146 None
2147 } else {
2148 // NOTE: return is greedy and eats blocks after it even when in a
2149 // position where structs are not allowed, such as in if statement
2150 // conditions. For example:
2151 //
2152 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002153 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002154 Some(Box::new(expr))
2155 }
2156 },
2157 })
2158 }
2159
2160 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002161 impl Parse for FieldValue {
2162 fn parse(input: ParseStream) -> Result<Self> {
2163 let member: Member = input.parse()?;
2164 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2165 let colon_token: Token![:] = input.parse()?;
2166 let value: Expr = input.parse()?;
2167 (Some(colon_token), value)
2168 } else if let Member::Named(ref ident) = member {
2169 let value = Expr::Path(ExprPath {
2170 attrs: Vec::new(),
2171 qself: None,
2172 path: Path::from(ident.clone()),
2173 });
2174 (None, value)
2175 } else {
2176 unreachable!()
2177 };
2178
2179 Ok(FieldValue {
2180 attrs: Vec::new(),
2181 member: member,
2182 colon_token: colon_token,
2183 expr: value,
2184 })
2185 }
2186 }
2187
2188 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002189 fn expr_struct_helper(
2190 input: ParseStream,
2191 outer_attrs: Vec<Attribute>,
2192 path: Path,
2193 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002194 let content;
2195 let brace_token = braced!(content in input);
2196 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002197
David Tolnay6e1e5052018-08-30 10:21:48 -07002198 let mut fields = Punctuated::new();
2199 loop {
2200 let attrs = content.call(Attribute::parse_outer)?;
2201 if content.fork().parse::<Member>().is_err() {
2202 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002203 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002204 } else {
2205 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002206 }
David Tolnay60291082018-08-28 09:54:49 -07002207 }
2208
David Tolnay6e1e5052018-08-30 10:21:48 -07002209 fields.push(FieldValue {
2210 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002211 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002212 });
2213
2214 if !content.peek(Token![,]) {
2215 break;
2216 }
2217 let punct: Token![,] = content.parse()?;
2218 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002219 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002220
2221 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2222 let dot2_token: Token![..] = content.parse()?;
2223 let rest: Expr = content.parse()?;
2224 (Some(dot2_token), Some(Box::new(rest)))
2225 } else {
2226 (None, None)
2227 };
2228
2229 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002230 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002231 brace_token: brace_token,
2232 path: path,
2233 fields: fields,
2234 dot2_token: dot2_token,
2235 rest: rest,
2236 })
Alex Crichton954046c2017-05-30 21:49:42 -07002237 }
David Tolnay055a7042016-10-02 19:23:54 -07002238
Michael Layzell734adb42017-06-07 16:58:31 -04002239 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002240 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2241 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002242
David Tolnay310b3262018-08-30 15:33:00 -07002243 let content;
2244 let brace_token = braced!(content in input);
2245 let inner_attrs = content.call(Attribute::parse_inner)?;
2246 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002247
David Tolnay310b3262018-08-30 15:33:00 -07002248 Ok(ExprUnsafe {
2249 attrs: inner_attrs,
2250 unsafe_token: unsafe_token,
2251 block: Block {
2252 brace_token: brace_token,
2253 stmts: stmts,
2254 },
2255 })
Alex Crichton954046c2017-05-30 21:49:42 -07002256 }
David Tolnay055a7042016-10-02 19:23:54 -07002257
Michael Layzell734adb42017-06-07 16:58:31 -04002258 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002259 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2260 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002261
David Tolnay310b3262018-08-30 15:33:00 -07002262 let content;
2263 let brace_token = braced!(content in input);
2264 let inner_attrs = content.call(Attribute::parse_inner)?;
2265 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002266
David Tolnay310b3262018-08-30 15:33:00 -07002267 Ok(ExprBlock {
2268 attrs: inner_attrs,
2269 label: label,
2270 block: Block {
2271 brace_token: brace_token,
2272 stmts: stmts,
2273 },
2274 })
Alex Crichton954046c2017-05-30 21:49:42 -07002275 }
David Tolnay89e05672016-10-02 14:39:42 -07002276
Michael Layzell734adb42017-06-07 16:58:31 -04002277 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002278 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2279 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002280 attrs: Vec::new(),
2281 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002282 limits: input.parse()?,
2283 to: {
2284 if input.is_empty()
2285 || input.peek(Token![,])
2286 || input.peek(Token![;])
2287 || !allow_struct.0 && input.peek(token::Brace)
2288 {
2289 None
2290 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002291 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002292 Some(Box::new(to))
2293 }
2294 },
2295 })
2296 }
David Tolnay438c9052016-10-07 23:24:48 -07002297
Michael Layzell734adb42017-06-07 16:58:31 -04002298 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002299 impl Parse for RangeLimits {
2300 fn parse(input: ParseStream) -> Result<Self> {
2301 let lookahead = input.lookahead1();
2302 if lookahead.peek(Token![..=]) {
2303 input.parse().map(RangeLimits::Closed)
2304 } else if lookahead.peek(Token![...]) {
2305 let dot3: Token![...] = input.parse()?;
2306 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2307 } else if lookahead.peek(Token![..]) {
2308 input.parse().map(RangeLimits::HalfOpen)
2309 } else {
2310 Err(lookahead.error())
2311 }
2312 }
Alex Crichton954046c2017-05-30 21:49:42 -07002313 }
David Tolnay438c9052016-10-07 23:24:48 -07002314
David Tolnay60291082018-08-28 09:54:49 -07002315 impl Parse for ExprPath {
2316 fn parse(input: ParseStream) -> Result<Self> {
2317 #[cfg(not(feature = "full"))]
2318 let attrs = Vec::new();
2319 #[cfg(feature = "full")]
2320 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002321
David Tolnay60291082018-08-28 09:54:49 -07002322 let (qself, path) = path::parsing::qpath(input, true)?;
2323
2324 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002325 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002326 qself: qself,
2327 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002328 })
David Tolnay60291082018-08-28 09:54:49 -07002329 }
Alex Crichton954046c2017-05-30 21:49:42 -07002330 }
David Tolnay42602292016-10-01 22:25:45 -07002331
Michael Layzell734adb42017-06-07 16:58:31 -04002332 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002333 impl Parse for Block {
2334 fn parse(input: ParseStream) -> Result<Self> {
2335 let content;
2336 Ok(Block {
2337 brace_token: braced!(content in input),
2338 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002339 })
David Tolnay60291082018-08-28 09:54:49 -07002340 }
Alex Crichton954046c2017-05-30 21:49:42 -07002341 }
David Tolnay939766a2016-09-23 23:48:12 -07002342
Michael Layzell734adb42017-06-07 16:58:31 -04002343 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002344 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002345 /// Parse the body of a block as zero or more statements, possibly
2346 /// including one trailing expression.
2347 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002348 /// *This function is available if Syn is built with the `"parsing"`
2349 /// feature.*
2350 ///
David Tolnay6b457252018-09-01 15:55:47 -07002351 /// # Example
2352 ///
David Tolnay95989db2019-01-01 15:05:57 -05002353 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002354 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002355 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002356 ///
2357 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002358 /// //
2359 /// // fn playground {
2360 /// // let mut x = 1;
2361 /// // x += 1;
2362 /// // println!("{}", x);
2363 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002364 /// struct MiniFunction {
2365 /// attrs: Vec<Attribute>,
2366 /// fn_token: Token![fn],
2367 /// name: Ident,
2368 /// brace_token: token::Brace,
2369 /// stmts: Vec<Stmt>,
2370 /// }
2371 ///
2372 /// impl Parse for MiniFunction {
2373 /// fn parse(input: ParseStream) -> Result<Self> {
2374 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2375 /// let fn_token: Token![fn] = input.parse()?;
2376 /// let name: Ident = input.parse()?;
2377 ///
2378 /// let content;
2379 /// let brace_token = braced!(content in input);
2380 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2381 /// let stmts = content.call(Block::parse_within)?;
2382 ///
2383 /// Ok(MiniFunction {
2384 /// attrs: {
2385 /// let mut attrs = outer_attrs;
2386 /// attrs.extend(inner_attrs);
2387 /// attrs
2388 /// },
2389 /// fn_token: fn_token,
2390 /// name: name,
2391 /// brace_token: brace_token,
2392 /// stmts: stmts,
2393 /// })
2394 /// }
2395 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002396 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002397 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002398 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002399 loop {
2400 while input.peek(Token![;]) {
2401 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002402 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002403 if input.is_empty() {
2404 break;
2405 }
2406 let s = parse_stmt(input, true)?;
2407 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2408 requires_terminator(s)
2409 } else {
2410 false
2411 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002412 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002413 if input.is_empty() {
2414 break;
2415 } else if requires_semicolon {
2416 return Err(input.error("unexpected token"));
2417 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002418 }
2419 Ok(stmts)
2420 }
Alex Crichton954046c2017-05-30 21:49:42 -07002421 }
2422
Michael Layzell734adb42017-06-07 16:58:31 -04002423 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002424 impl Parse for Stmt {
2425 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002426 parse_stmt(input, false)
2427 }
2428 }
David Tolnay939766a2016-09-23 23:48:12 -07002429
David Tolnaye532d6b2018-08-30 16:55:01 -07002430 #[cfg(feature = "full")]
2431 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2432 let ahead = input.fork();
2433 ahead.call(Attribute::parse_outer)?;
2434
David Tolnaye532d6b2018-08-30 16:55:01 -07002435 if {
2436 let ahead = ahead.fork();
2437 // Only parse braces here; paren and bracket will get parsed as
2438 // expression statements
2439 ahead.call(Path::parse_mod_style).is_ok()
2440 && ahead.parse::<Token![!]>().is_ok()
2441 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2442 } {
2443 stmt_mac(input)
2444 } else if ahead.peek(Token![let]) {
2445 stmt_local(input).map(Stmt::Local)
2446 } else if ahead.peek(Token![pub])
2447 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2448 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2449 || ahead.peek(Token![use])
2450 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2451 || ahead.peek(Token![const])
2452 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2453 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2454 || ahead.peek(Token![fn])
2455 || ahead.peek(Token![mod])
2456 || ahead.peek(Token![type])
2457 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2458 || ahead.peek(Token![struct])
2459 || ahead.peek(Token![enum])
2460 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2461 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2462 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002463 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002464 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2465 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002466 || ahead.peek(Token![macro])
2467 {
2468 input.parse().map(Stmt::Item)
2469 } else {
2470 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002471 }
Alex Crichton954046c2017-05-30 21:49:42 -07002472 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002473
Michael Layzell734adb42017-06-07 16:58:31 -04002474 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002475 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2476 let attrs = input.call(Attribute::parse_outer)?;
2477 let path = input.call(Path::parse_mod_style)?;
2478 let bang_token: Token![!] = input.parse()?;
2479 let ident: Option<Ident> = input.parse()?;
2480 let (delimiter, tts) = mac::parse_delimiter(input)?;
2481 let semi_token: Option<Token![;]> = input.parse()?;
2482
2483 Ok(Stmt::Item(Item::Macro(ItemMacro {
2484 attrs: attrs,
2485 ident: ident,
2486 mac: Macro {
2487 path: path,
2488 bang_token: bang_token,
2489 delimiter: delimiter,
2490 tts: tts,
2491 },
2492 semi_token: semi_token,
2493 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002494 }
David Tolnay84aa0752016-10-02 23:01:13 -07002495
Michael Layzell734adb42017-06-07 16:58:31 -04002496 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002497 fn stmt_local(input: ParseStream) -> Result<Local> {
2498 Ok(Local {
2499 attrs: input.call(Attribute::parse_outer)?,
2500 let_token: input.parse()?,
2501 pats: {
2502 let mut pats = Punctuated::new();
2503 let value: Pat = input.parse()?;
2504 pats.push_value(value);
2505 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2506 let punct = input.parse()?;
2507 pats.push_punct(punct);
2508 let value: Pat = input.parse()?;
2509 pats.push_value(value);
2510 }
2511 pats
2512 },
2513 ty: {
2514 if input.peek(Token![:]) {
2515 let colon_token: Token![:] = input.parse()?;
2516 let ty: Type = input.parse()?;
2517 Some((colon_token, Box::new(ty)))
2518 } else {
2519 None
2520 }
2521 },
2522 init: {
2523 if input.peek(Token![=]) {
2524 let eq_token: Token![=] = input.parse()?;
2525 let init: Expr = input.parse()?;
2526 Some((eq_token, Box::new(init)))
2527 } else {
2528 None
2529 }
2530 },
2531 semi_token: input.parse()?,
2532 })
2533 }
2534
2535 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002536 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002537 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002538 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002539
2540 attrs.extend(e.replace_attrs(Vec::new()));
2541 e.replace_attrs(attrs);
2542
2543 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002544 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002545 }
David Tolnay60291082018-08-28 09:54:49 -07002546
David Tolnayf00a2762018-08-30 17:22:22 -07002547 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002548 Ok(Stmt::Expr(e))
2549 } else {
2550 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002551 }
David Tolnay60291082018-08-28 09:54:49 -07002552 }
2553
2554 #[cfg(feature = "full")]
2555 impl Parse for Pat {
2556 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002557 let lookahead = input.lookahead1();
2558 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002559 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002560 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002561 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002562 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2563 pat_lit_or_range(input)
2564 } else if input.peek(Ident)
2565 && ({
2566 input.peek2(Token![::])
2567 || input.peek2(Token![!])
2568 || input.peek2(token::Brace)
2569 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002570 || input.peek2(Token![..])
2571 && !{
2572 let ahead = input.fork();
2573 ahead.parse::<Ident>()?;
2574 ahead.parse::<RangeLimits>()?;
2575 ahead.is_empty() || ahead.peek(Token![,])
2576 }
David Tolnay8d534b02018-09-02 09:46:05 -07002577 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002578 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002579 || input.peek(Token![::])
2580 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002581 || input.peek(Token![Self])
2582 || input.peek(Token![super])
2583 || input.peek(Token![extern])
2584 || input.peek(Token![crate])
2585 {
2586 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002587 } else if input.peek(Token![ref])
2588 || input.peek(Token![mut])
2589 || input.peek(Token![self])
2590 || input.peek(Ident)
2591 {
David Tolnay310b3262018-08-30 15:33:00 -07002592 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002593 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002594 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002595 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002596 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002597 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002598 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002599 } else {
2600 Err(lookahead.error())
2601 }
2602 }
2603 }
2604
2605 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002606 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2607 let (qself, path) = path::parsing::qpath(input, true)?;
2608
2609 if input.peek(Token![..]) {
2610 return pat_range(input, qself, path).map(Pat::Range);
2611 }
2612
2613 if qself.is_some() {
2614 return Ok(Pat::Path(PatPath {
2615 qself: qself,
2616 path: path,
2617 }));
2618 }
2619
2620 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2621 let mut contains_arguments = false;
2622 for segment in &path.segments {
2623 match segment.arguments {
2624 PathArguments::None => {}
2625 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2626 contains_arguments = true;
2627 }
2628 }
2629 }
2630
2631 if !contains_arguments {
2632 let bang_token: Token![!] = input.parse()?;
2633 let (delimiter, tts) = mac::parse_delimiter(input)?;
2634 return Ok(Pat::Macro(PatMacro {
2635 mac: Macro {
2636 path: path,
2637 bang_token: bang_token,
2638 delimiter: delimiter,
2639 tts: tts,
2640 },
2641 }));
2642 }
2643 }
2644
2645 if input.peek(token::Brace) {
2646 pat_struct(input, path).map(Pat::Struct)
2647 } else if input.peek(token::Paren) {
2648 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2649 } else if input.peek(Token![..]) {
2650 pat_range(input, qself, path).map(Pat::Range)
2651 } else {
2652 Ok(Pat::Path(PatPath {
2653 qself: qself,
2654 path: path,
2655 }))
2656 }
2657 }
2658
2659 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002660 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2661 Ok(PatWild {
2662 underscore_token: input.parse()?,
2663 })
Alex Crichton954046c2017-05-30 21:49:42 -07002664 }
2665
Michael Layzell734adb42017-06-07 16:58:31 -04002666 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002667 fn pat_box(input: ParseStream) -> Result<PatBox> {
2668 Ok(PatBox {
2669 box_token: input.parse()?,
2670 pat: input.parse()?,
2671 })
David Tolnay60291082018-08-28 09:54:49 -07002672 }
2673
2674 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002675 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2676 Ok(PatIdent {
2677 by_ref: input.parse()?,
2678 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002679 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002680 subpat: {
2681 if input.peek(Token![@]) {
2682 let at_token: Token![@] = input.parse()?;
2683 let subpat: Pat = input.parse()?;
2684 Some((at_token, Box::new(subpat)))
2685 } else {
2686 None
2687 }
2688 },
2689 })
David Tolnay60291082018-08-28 09:54:49 -07002690 }
2691
2692 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002693 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002694 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002695 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002696 pat: input.call(pat_tuple)?,
2697 })
2698 }
David Tolnay60291082018-08-28 09:54:49 -07002699
David Tolnay310b3262018-08-30 15:33:00 -07002700 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002701 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002702 let content;
2703 let brace_token = braced!(content in input);
2704
2705 let mut fields = Punctuated::new();
2706 while !content.is_empty() && !content.peek(Token![..]) {
2707 let value = content.call(field_pat)?;
2708 fields.push_value(value);
2709 if !content.peek(Token![,]) {
2710 break;
David Tolnay60291082018-08-28 09:54:49 -07002711 }
David Tolnay310b3262018-08-30 15:33:00 -07002712 let punct: Token![,] = content.parse()?;
2713 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002714 }
David Tolnay310b3262018-08-30 15:33:00 -07002715
2716 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2717 Some(content.parse()?)
2718 } else {
2719 None
2720 };
2721
2722 Ok(PatStruct {
2723 path: path,
2724 brace_token: brace_token,
2725 fields: fields,
2726 dot2_token: dot2_token,
2727 })
2728 }
2729
2730 #[cfg(feature = "full")]
2731 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2732 let boxed: Option<Token![box]> = input.parse()?;
2733 let by_ref: Option<Token![ref]> = input.parse()?;
2734 let mutability: Option<Token![mut]> = input.parse()?;
2735 let member: Member = input.parse()?;
2736
2737 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2738 || member.is_unnamed()
2739 {
2740 return Ok(FieldPat {
2741 attrs: Vec::new(),
2742 member: member,
2743 colon_token: input.parse()?,
2744 pat: input.parse()?,
2745 });
2746 }
2747
2748 let ident = match member {
2749 Member::Named(ident) => ident,
2750 Member::Unnamed(_) => unreachable!(),
2751 };
2752
2753 let mut pat = Pat::Ident(PatIdent {
2754 by_ref: by_ref,
2755 mutability: mutability,
2756 ident: ident.clone(),
2757 subpat: None,
2758 });
2759
2760 if let Some(boxed) = boxed {
2761 pat = Pat::Box(PatBox {
2762 pat: Box::new(pat),
2763 box_token: boxed,
2764 });
2765 }
2766
2767 Ok(FieldPat {
2768 member: Member::Named(ident),
2769 pat: Box::new(pat),
2770 attrs: Vec::new(),
2771 colon_token: None,
2772 })
Alex Crichton954046c2017-05-30 21:49:42 -07002773 }
2774
David Tolnay1501f7e2018-08-27 14:21:03 -07002775 impl Parse for Member {
2776 fn parse(input: ParseStream) -> Result<Self> {
2777 if input.peek(Ident) {
2778 input.parse().map(Member::Named)
2779 } else if input.peek(LitInt) {
2780 input.parse().map(Member::Unnamed)
2781 } else {
2782 Err(input.error("expected identifier or integer"))
2783 }
2784 }
David Tolnay85b69a42017-12-27 20:43:10 -05002785 }
2786
Bastien Oriveld29ea392018-10-16 23:50:16 +02002787 #[cfg(feature = "full")]
2788 impl Parse for Arm {
2789 fn parse(input: ParseStream) -> Result<Arm> {
2790 let requires_comma;
2791 Ok(Arm {
2792 attrs: input.call(Attribute::parse_outer)?,
2793 leading_vert: input.parse()?,
2794 pats: {
2795 let mut pats = Punctuated::new();
2796 let value: Pat = input.parse()?;
2797 pats.push_value(value);
2798 loop {
2799 if !input.peek(Token![|]) {
2800 break;
2801 }
2802 let punct = input.parse()?;
2803 pats.push_punct(punct);
2804 let value: Pat = input.parse()?;
2805 pats.push_value(value);
2806 }
2807 pats
2808 },
2809 guard: {
2810 if input.peek(Token![if]) {
2811 let if_token: Token![if] = input.parse()?;
2812 let guard: Expr = input.parse()?;
2813 Some((if_token, Box::new(guard)))
2814 } else {
2815 None
2816 }
2817 },
2818 fat_arrow_token: input.parse()?,
2819 body: {
2820 let body = input.call(expr_early)?;
2821 requires_comma = requires_terminator(&body);
2822 Box::new(body)
2823 },
2824 comma: {
2825 if requires_comma && !input.is_empty() {
2826 Some(input.parse()?)
2827 } else {
2828 input.parse()?
2829 }
2830 },
2831 })
2832 }
2833 }
2834
David Tolnay1501f7e2018-08-27 14:21:03 -07002835 impl Parse for Index {
2836 fn parse(input: ParseStream) -> Result<Self> {
2837 let lit: LitInt = input.parse()?;
2838 if let IntSuffix::None = lit.suffix() {
2839 Ok(Index {
2840 index: lit.value() as u32,
2841 span: lit.span(),
2842 })
2843 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002844 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002845 }
2846 }
David Tolnay85b69a42017-12-27 20:43:10 -05002847 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002848
Michael Layzell734adb42017-06-07 16:58:31 -04002849 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002850 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2851 Ok(PatRange {
2852 lo: Box::new(Expr::Path(ExprPath {
2853 attrs: Vec::new(),
2854 qself: qself,
2855 path: path,
2856 })),
2857 limits: input.parse()?,
2858 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002859 })
Alex Crichton954046c2017-05-30 21:49:42 -07002860 }
David Tolnay9636c052016-10-02 17:11:17 -07002861
Michael Layzell734adb42017-06-07 16:58:31 -04002862 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002863 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2864 let content;
2865 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002866
David Tolnay310b3262018-08-30 15:33:00 -07002867 let mut front = Punctuated::new();
2868 let mut dot2_token = None::<Token![..]>;
2869 let mut comma_token = None::<Token![,]>;
2870 loop {
2871 if content.is_empty() {
2872 break;
David Tolnay60291082018-08-28 09:54:49 -07002873 }
David Tolnay310b3262018-08-30 15:33:00 -07002874 if content.peek(Token![..]) {
2875 dot2_token = Some(content.parse()?);
2876 comma_token = content.parse()?;
2877 break;
David Tolnay60291082018-08-28 09:54:49 -07002878 }
David Tolnay310b3262018-08-30 15:33:00 -07002879 let value: Pat = content.parse()?;
2880 front.push_value(value);
2881 if content.is_empty() {
2882 break;
2883 }
2884 let punct = content.parse()?;
2885 front.push_punct(punct);
2886 }
2887
David Tolnayf5ebc192018-08-30 18:23:46 -07002888 let mut back = Punctuated::new();
2889 while !content.is_empty() {
2890 let value: Pat = content.parse()?;
2891 back.push_value(value);
2892 if content.is_empty() {
2893 break;
2894 }
2895 let punct = content.parse()?;
2896 back.push_punct(punct);
2897 }
David Tolnay310b3262018-08-30 15:33:00 -07002898
2899 Ok(PatTuple {
2900 paren_token: paren_token,
2901 front: front,
2902 dot2_token: dot2_token,
2903 comma_token: comma_token,
2904 back: back,
2905 })
2906 }
2907
2908 #[cfg(feature = "full")]
2909 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2910 Ok(PatRef {
2911 and_token: input.parse()?,
2912 mutability: input.parse()?,
2913 pat: input.parse()?,
2914 })
2915 }
2916
2917 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002918 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2919 let lo = input.call(pat_lit_expr)?;
2920 if input.peek(Token![..]) {
2921 Ok(Pat::Range(PatRange {
2922 lo: lo,
2923 limits: input.parse()?,
2924 hi: input.call(pat_lit_expr)?,
2925 }))
David Tolnay310b3262018-08-30 15:33:00 -07002926 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002927 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002928 }
2929 }
2930
2931 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002932 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2933 let neg: Option<Token![-]> = input.parse()?;
2934
2935 let lookahead = input.lookahead1();
2936 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002937 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002938 } else if lookahead.peek(Ident)
2939 || lookahead.peek(Token![::])
2940 || lookahead.peek(Token![<])
2941 || lookahead.peek(Token![self])
2942 || lookahead.peek(Token![Self])
2943 || lookahead.peek(Token![super])
2944 || lookahead.peek(Token![extern])
2945 || lookahead.peek(Token![crate])
2946 {
2947 Expr::Path(input.parse()?)
2948 } else {
2949 return Err(lookahead.error());
2950 };
2951
2952 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002953 Expr::Unary(ExprUnary {
2954 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002955 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002956 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002957 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002958 } else {
David Tolnay60291082018-08-28 09:54:49 -07002959 expr
2960 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002961 }
David Tolnay323279a2017-12-29 11:26:32 -05002962
2963 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002964 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2965 let content;
2966 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002967
David Tolnay310b3262018-08-30 15:33:00 -07002968 let mut front = Punctuated::new();
2969 let mut middle = None;
2970 loop {
2971 if content.is_empty() || content.peek(Token![..]) {
2972 break;
David Tolnay60291082018-08-28 09:54:49 -07002973 }
David Tolnay310b3262018-08-30 15:33:00 -07002974 let value: Pat = content.parse()?;
2975 if content.peek(Token![..]) {
2976 middle = Some(Box::new(value));
2977 break;
David Tolnay60291082018-08-28 09:54:49 -07002978 }
David Tolnay310b3262018-08-30 15:33:00 -07002979 front.push_value(value);
2980 if content.is_empty() {
2981 break;
2982 }
2983 let punct = content.parse()?;
2984 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002985 }
David Tolnay310b3262018-08-30 15:33:00 -07002986
2987 let dot2_token: Option<Token![..]> = content.parse()?;
2988 let mut comma_token = None::<Token![,]>;
2989 let mut back = Punctuated::new();
2990 if dot2_token.is_some() {
2991 comma_token = content.parse()?;
2992 if comma_token.is_some() {
2993 loop {
2994 if content.is_empty() {
2995 break;
2996 }
2997 let value: Pat = content.parse()?;
2998 back.push_value(value);
2999 if content.is_empty() {
3000 break;
3001 }
3002 let punct = content.parse()?;
3003 back.push_punct(punct);
3004 }
3005 }
3006 }
3007
3008 Ok(PatSlice {
3009 bracket_token: bracket_token,
3010 front: front,
3011 middle: middle,
3012 dot2_token: dot2_token,
3013 comma_token: comma_token,
3014 back: back,
3015 })
David Tolnay60291082018-08-28 09:54:49 -07003016 }
3017
3018 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003019 impl Member {
3020 fn is_named(&self) -> bool {
3021 match *self {
3022 Member::Named(_) => true,
3023 Member::Unnamed(_) => false,
3024 }
3025 }
David Tolnay60291082018-08-28 09:54:49 -07003026
3027 fn is_unnamed(&self) -> bool {
3028 match *self {
3029 Member::Named(_) => false,
3030 Member::Unnamed(_) => true,
3031 }
3032 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003033 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003034}
3035
David Tolnayf4bbbd92016-09-23 14:41:55 -07003036#[cfg(feature = "printing")]
3037mod printing {
3038 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003039
Alex Crichtona74a1c82018-05-16 10:20:44 -07003040 use proc_macro2::{Literal, TokenStream};
3041 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003042
David Tolnay64023912018-08-31 09:51:12 -07003043 #[cfg(feature = "full")]
3044 use attr::FilterAttrs;
3045 #[cfg(feature = "full")]
3046 use print::TokensOrDefault;
3047
David Tolnaybcf26022017-12-25 22:10:52 -05003048 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003049 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003050 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003051 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003052 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003053 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003054 e.to_tokens(tokens);
3055 });
3056 } else {
3057 e.to_tokens(tokens);
3058 }
3059 }
3060
David Tolnay8c91b882017-12-28 23:04:32 -05003061 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003062 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003063 tokens.append_all(attrs.outer());
3064 }
Michael Layzell734adb42017-06-07 16:58:31 -04003065
David Tolnayd997aef2018-07-21 18:42:31 -07003066 #[cfg(feature = "full")]
3067 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3068 tokens.append_all(attrs.inner());
3069 }
3070
David Tolnay8c91b882017-12-28 23:04:32 -05003071 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003072 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3073
3074 #[cfg(not(feature = "full"))]
3075 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003076
Michael Layzell734adb42017-06-07 16:58:31 -04003077 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003078 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003079 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003080 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003081 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003082 self.expr.to_tokens(tokens);
3083 }
3084 }
3085
Michael Layzell734adb42017-06-07 16:58:31 -04003086 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003087 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003088 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003089 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003090 self.place.to_tokens(tokens);
3091 self.arrow_token.to_tokens(tokens);
3092 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003093 }
3094 }
3095
Michael Layzell734adb42017-06-07 16:58:31 -04003096 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003097 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003098 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003099 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003100 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003101 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003102 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003103 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003104 }
3105 }
3106
3107 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003108 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003109 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003110 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003111 self.paren_token.surround(tokens, |tokens| {
3112 self.args.to_tokens(tokens);
3113 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003114 }
3115 }
3116
Michael Layzell734adb42017-06-07 16:58:31 -04003117 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003118 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003119 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003120 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003121 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003122 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003123 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003124 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003125 self.paren_token.surround(tokens, |tokens| {
3126 self.args.to_tokens(tokens);
3127 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003128 }
3129 }
3130
Michael Layzell734adb42017-06-07 16:58:31 -04003131 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003132 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003133 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003134 self.colon2_token.to_tokens(tokens);
3135 self.lt_token.to_tokens(tokens);
3136 self.args.to_tokens(tokens);
3137 self.gt_token.to_tokens(tokens);
3138 }
3139 }
3140
3141 #[cfg(feature = "full")]
3142 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003143 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003144 match *self {
3145 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3146 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3147 }
3148 }
3149 }
3150
3151 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003152 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003153 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003154 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003155 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003156 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003157 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003158 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003159 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003160 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003161 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003162 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003163 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003164 }
3165 }
3166
3167 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003168 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003169 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003170 self.left.to_tokens(tokens);
3171 self.op.to_tokens(tokens);
3172 self.right.to_tokens(tokens);
3173 }
3174 }
3175
3176 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003177 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003178 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003179 self.op.to_tokens(tokens);
3180 self.expr.to_tokens(tokens);
3181 }
3182 }
3183
David Tolnay8c91b882017-12-28 23:04:32 -05003184 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003185 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003186 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003187 self.lit.to_tokens(tokens);
3188 }
3189 }
3190
Alex Crichton62a0a592017-05-22 13:58:53 -07003191 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003192 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003193 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003194 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003195 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003196 self.ty.to_tokens(tokens);
3197 }
3198 }
3199
David Tolnay0cf94f22017-12-28 23:46:26 -05003200 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003201 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003202 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003203 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003204 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003205 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003206 self.ty.to_tokens(tokens);
3207 }
3208 }
3209
Michael Layzell734adb42017-06-07 16:58:31 -04003210 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003211 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003212 if let Some((ref else_token, ref else_)) = *else_ {
3213 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003214
3215 // If we are not one of the valid expressions to exist in an else
3216 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003217 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003218 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003219 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003220 }
3221 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003222 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003223 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003224 });
3225 }
3226 }
3227 }
3228 }
3229
3230 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003231 impl ToTokens for ExprLet {
3232 fn to_tokens(&self, tokens: &mut TokenStream) {
3233 outer_attrs_to_tokens(&self.attrs, tokens);
3234 self.let_token.to_tokens(tokens);
3235 self.pats.to_tokens(tokens);
3236 self.eq_token.to_tokens(tokens);
3237 wrap_bare_struct(tokens, &self.expr);
3238 }
3239 }
3240
3241 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003242 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003243 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003244 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003245 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003246 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003247 self.then_branch.to_tokens(tokens);
3248 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003249 }
3250 }
3251
Michael Layzell734adb42017-06-07 16:58:31 -04003252 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003253 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003254 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003255 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003256 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003257 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003258 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003259 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003260 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003261 tokens.append_all(&self.body.stmts);
3262 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003263 }
3264 }
3265
Michael Layzell734adb42017-06-07 16:58:31 -04003266 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003267 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003268 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003269 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003270 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003271 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003272 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003273 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003274 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003275 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003276 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003277 tokens.append_all(&self.body.stmts);
3278 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003279 }
3280 }
3281
Michael Layzell734adb42017-06-07 16:58:31 -04003282 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003283 impl ToTokens for ExprLoop {
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 Tolnaybcd498f2017-12-29 12:02:33 -05003286 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003287 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003288 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003289 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003290 tokens.append_all(&self.body.stmts);
3291 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003292 }
3293 }
3294
Michael Layzell734adb42017-06-07 16:58:31 -04003295 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003296 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003297 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003298 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003299 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003300 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003301 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003302 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003303 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003304 arm.to_tokens(tokens);
3305 // Ensure that we have a comma after a non-block arm, except
3306 // for the last one.
3307 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003308 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003309 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003310 }
3311 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003312 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003313 }
3314 }
3315
Michael Layzell734adb42017-06-07 16:58:31 -04003316 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003317 impl ToTokens for ExprAsync {
3318 fn to_tokens(&self, tokens: &mut TokenStream) {
3319 outer_attrs_to_tokens(&self.attrs, tokens);
3320 self.async_token.to_tokens(tokens);
3321 self.capture.to_tokens(tokens);
3322 self.block.to_tokens(tokens);
3323 }
3324 }
3325
3326 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003327 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003328 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003329 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003330 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003331 self.block.to_tokens(tokens);
3332 }
3333 }
3334
Michael Layzell734adb42017-06-07 16:58:31 -04003335 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003336 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003337 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003338 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003339 self.yield_token.to_tokens(tokens);
3340 self.expr.to_tokens(tokens);
3341 }
3342 }
3343
3344 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003345 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003346 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003347 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003348 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003349 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003350 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003351 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003352 for input in self.inputs.pairs() {
3353 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003354 FnArg::Captured(ArgCaptured {
3355 ref pat,
3356 ty: Type::Infer(_),
3357 ..
3358 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003359 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003360 }
David Tolnay56080682018-01-06 14:01:52 -08003361 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003362 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003363 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003364 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003365 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003366 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003367 self.body.to_tokens(tokens);
3368 }
3369 }
3370
Michael Layzell734adb42017-06-07 16:58:31 -04003371 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003372 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003373 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003374 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003375 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003376 self.block.brace_token.surround(tokens, |tokens| {
3377 inner_attrs_to_tokens(&self.attrs, tokens);
3378 tokens.append_all(&self.block.stmts);
3379 });
Nika Layzell640832a2017-12-04 13:37:09 -05003380 }
3381 }
3382
3383 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003384 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003385 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003386 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003387 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003388 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003389 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003390 tokens.append_all(&self.block.stmts);
3391 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003392 }
3393 }
3394
Michael Layzell734adb42017-06-07 16:58:31 -04003395 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003396 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003397 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003398 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003399 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003400 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003401 self.right.to_tokens(tokens);
3402 }
3403 }
3404
Michael Layzell734adb42017-06-07 16:58:31 -04003405 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003406 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003407 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003408 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003409 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003410 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003411 self.right.to_tokens(tokens);
3412 }
3413 }
3414
3415 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003416 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003417 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003418 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003419 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003420 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003421 }
3422 }
3423
David Tolnay85b69a42017-12-27 20:43:10 -05003424 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003425 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003426 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003427 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003428 Member::Unnamed(ref index) => index.to_tokens(tokens),
3429 }
3430 }
3431 }
3432
David Tolnay85b69a42017-12-27 20:43:10 -05003433 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003434 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003435 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3436 lit.set_span(self.span);
3437 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003438 }
3439 }
3440
3441 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003442 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003443 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003444 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003445 self.bracket_token.surround(tokens, |tokens| {
3446 self.index.to_tokens(tokens);
3447 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003448 }
3449 }
3450
Michael Layzell734adb42017-06-07 16:58:31 -04003451 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003453 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003454 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003455 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003456 match self.limits {
3457 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3458 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3459 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003460 self.to.to_tokens(tokens);
3461 }
3462 }
3463
3464 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003465 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003466 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003467 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003468 }
3469 }
3470
Michael Layzell734adb42017-06-07 16:58:31 -04003471 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003472 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003473 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003474 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003475 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003476 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003477 self.expr.to_tokens(tokens);
3478 }
3479 }
3480
Michael Layzell734adb42017-06-07 16:58:31 -04003481 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003482 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003483 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003484 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003485 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 self.label.to_tokens(tokens);
3487 self.expr.to_tokens(tokens);
3488 }
3489 }
3490
Michael Layzell734adb42017-06-07 16:58:31 -04003491 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003492 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003493 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003494 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003495 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003496 self.label.to_tokens(tokens);
3497 }
3498 }
3499
Michael Layzell734adb42017-06-07 16:58:31 -04003500 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003501 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003502 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003503 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003504 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003505 self.expr.to_tokens(tokens);
3506 }
3507 }
3508
Michael Layzell734adb42017-06-07 16:58:31 -04003509 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003510 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003511 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003512 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003513 self.mac.to_tokens(tokens);
3514 }
3515 }
3516
3517 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003518 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003519 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003520 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003521 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003522 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003523 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003524 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003525 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003526 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003527 self.rest.to_tokens(tokens);
3528 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003529 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003530 }
3531 }
3532
Michael Layzell734adb42017-06-07 16:58:31 -04003533 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003534 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003535 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003536 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003537 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003538 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003539 self.expr.to_tokens(tokens);
3540 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003541 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003542 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003543 }
3544 }
3545
David Tolnaye98775f2017-12-28 23:17:00 -05003546 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003547 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003548 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003549 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003550 self.group_token.surround(tokens, |tokens| {
3551 self.expr.to_tokens(tokens);
3552 });
3553 }
3554 }
3555
Alex Crichton62a0a592017-05-22 13:58:53 -07003556 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003557 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003558 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003559 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003560 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003561 self.expr.to_tokens(tokens);
3562 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003563 }
3564 }
3565
Michael Layzell734adb42017-06-07 16:58:31 -04003566 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003567 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003568 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003569 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003570 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003571 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003572 }
3573 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003574
David Tolnay2ae520a2017-12-29 11:19:50 -05003575 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003576 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003577 self.tts.to_tokens(tokens);
3578 }
3579 }
3580
Michael Layzell734adb42017-06-07 16:58:31 -04003581 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003582 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003583 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003584 self.name.to_tokens(tokens);
3585 self.colon_token.to_tokens(tokens);
3586 }
3587 }
3588
3589 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003590 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003591 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003592 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003593 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003594 if let Some(ref colon_token) = self.colon_token {
3595 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003596 self.expr.to_tokens(tokens);
3597 }
David Tolnay055a7042016-10-02 19:23:54 -07003598 }
3599 }
3600
Michael Layzell734adb42017-06-07 16:58:31 -04003601 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003602 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003603 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003604 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003605 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003606 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003607 if let Some((ref if_token, ref guard)) = self.guard {
3608 if_token.to_tokens(tokens);
3609 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003610 }
David Tolnaydfb91432018-03-31 19:19:44 +02003611 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003612 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003613 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003614 }
3615 }
3616
Michael Layzell734adb42017-06-07 16:58:31 -04003617 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003618 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003619 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003620 self.underscore_token.to_tokens(tokens);
3621 }
3622 }
3623
Michael Layzell734adb42017-06-07 16:58:31 -04003624 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003625 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003626 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003627 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003628 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003629 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003630 if let Some((ref at_token, ref subpat)) = self.subpat {
3631 at_token.to_tokens(tokens);
3632 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003633 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003634 }
3635 }
3636
Michael Layzell734adb42017-06-07 16:58:31 -04003637 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003639 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003640 self.path.to_tokens(tokens);
3641 self.brace_token.surround(tokens, |tokens| {
3642 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003643 // NOTE: We need a comma before the dot2 token if it is present.
3644 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003645 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003646 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003647 self.dot2_token.to_tokens(tokens);
3648 });
3649 }
3650 }
3651
Michael Layzell734adb42017-06-07 16:58:31 -04003652 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003653 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003654 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003655 self.path.to_tokens(tokens);
3656 self.pat.to_tokens(tokens);
3657 }
3658 }
3659
Michael Layzell734adb42017-06-07 16:58:31 -04003660 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003661 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003662 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003663 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003664 }
3665 }
3666
Michael Layzell734adb42017-06-07 16:58:31 -04003667 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003668 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003669 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003670 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003671 self.front.to_tokens(tokens);
3672 if let Some(ref dot2_token) = self.dot2_token {
3673 if !self.front.empty_or_trailing() {
3674 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003675 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003676 }
David Tolnay41871922017-12-29 01:53:45 -05003677 dot2_token.to_tokens(tokens);
3678 self.comma_token.to_tokens(tokens);
3679 if self.comma_token.is_none() && !self.back.is_empty() {
3680 // Ensure there is a comma after the .. token.
3681 <Token![,]>::default().to_tokens(tokens);
3682 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003683 }
David Tolnay41871922017-12-29 01:53:45 -05003684 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003685 });
3686 }
3687 }
3688
Michael Layzell734adb42017-06-07 16:58:31 -04003689 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003690 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003691 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003692 self.box_token.to_tokens(tokens);
3693 self.pat.to_tokens(tokens);
3694 }
3695 }
3696
Michael Layzell734adb42017-06-07 16:58:31 -04003697 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003698 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003699 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003700 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003701 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003702 self.pat.to_tokens(tokens);
3703 }
3704 }
3705
Michael Layzell734adb42017-06-07 16:58:31 -04003706 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003707 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003708 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003709 self.expr.to_tokens(tokens);
3710 }
3711 }
3712
Michael Layzell734adb42017-06-07 16:58:31 -04003713 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003714 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003715 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003716 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003717 match self.limits {
3718 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003719 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003720 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003721 self.hi.to_tokens(tokens);
3722 }
3723 }
3724
Michael Layzell734adb42017-06-07 16:58:31 -04003725 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003726 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003727 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003728 self.bracket_token.surround(tokens, |tokens| {
3729 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003730
3731 // If we need a comma before the middle or standalone .. token,
3732 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003733 if !self.front.empty_or_trailing()
3734 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003735 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003736 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003737 }
3738
3739 // If we have an identifier, we always need a .. token.
3740 if self.middle.is_some() {
3741 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003742 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003743 } else if self.dot2_token.is_some() {
3744 self.dot2_token.to_tokens(tokens);
3745 }
3746
3747 // Make sure we have a comma before the back half.
3748 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003749 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003750 self.back.to_tokens(tokens);
3751 } else {
3752 self.comma_token.to_tokens(tokens);
3753 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003754 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003755 }
3756 }
3757
Michael Layzell734adb42017-06-07 16:58:31 -04003758 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003759 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003760 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003761 self.mac.to_tokens(tokens);
3762 }
3763 }
3764
3765 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003766 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003767 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003768 self.tts.to_tokens(tokens);
3769 }
3770 }
3771
3772 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003773 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003774 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003775 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003776 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003777 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003778 }
3779 self.pat.to_tokens(tokens);
3780 }
3781 }
3782
Michael Layzell734adb42017-06-07 16:58:31 -04003783 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003784 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003785 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003786 self.brace_token.surround(tokens, |tokens| {
3787 tokens.append_all(&self.stmts);
3788 });
David Tolnay42602292016-10-01 22:25:45 -07003789 }
3790 }
3791
Michael Layzell734adb42017-06-07 16:58:31 -04003792 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003793 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003794 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003795 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003796 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003797 Stmt::Item(ref item) => item.to_tokens(tokens),
3798 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003799 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003800 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003801 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003802 }
David Tolnay42602292016-10-01 22:25:45 -07003803 }
3804 }
3805 }
David Tolnay191e0582016-10-02 18:31:09 -07003806
Michael Layzell734adb42017-06-07 16:58:31 -04003807 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003808 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003809 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003810 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003811 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003812 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003813 if let Some((ref colon_token, ref ty)) = self.ty {
3814 colon_token.to_tokens(tokens);
3815 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003816 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003817 if let Some((ref eq_token, ref init)) = self.init {
3818 eq_token.to_tokens(tokens);
3819 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003820 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003821 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003822 }
3823 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003824}