1 use super::*;
2 use proc_macro2::{Span, TokenStream};
3 use punctuated::Punctuated;
4 #[cfg(feature = "extra-traits")]
5 use std::hash::{Hash, Hasher};
6 #[cfg(all(feature = "parsing", feature = "full"))]
7 use std::mem;
8 #[cfg(feature = "extra-traits")]
9 use tt::TokenStreamHelper;
10
11 ast_enum_of_structs! {
12 /// A Rust expression.
13 ///
14 /// *This type is available if Syn is built with the `"derive"` or `"full"`
15 /// feature.*
16 ///
17 /// # 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 ///
22 /// ```edition2018
23 /// # 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 /// }
36 /// Expr::If(expr) => {
37 /// /* ... */
38 /// }
39 ///
40 /// /* ... */
41 /// # _ => {}
42 /// # }
43 /// # }
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
51 /// `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`.
53 ///
54 /// This approach avoids repeating the variant names twice on every line.
55 ///
56 /// ```edition2018
57 /// # use syn::{Expr, ExprMethodCall};
58 /// #
59 /// # fn example(expr: Expr) {
60 /// // Repetitive; recommend not doing this.
61 /// match expr {
62 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
63 /// # }
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 ///
72 /// ```edition2018
73 /// # use syn::{Expr, ExprField};
74 /// #
75 /// # fn example(discriminant: ExprField) {
76 /// // Binding is called `base` which is the name I would use if I were
77 /// // assigning `*discriminant.base` without an `if let`.
78 /// if let Expr::Tuple(base) = *discriminant.base {
79 /// # }
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`.
86 pub enum Expr {
87 /// A box expression: `box f`.
88 ///
89 /// *This type is available if Syn is built with the `"full"` feature.*
90 pub Box(ExprBox #full {
91 pub attrs: Vec<Attribute>,
92 pub box_token: Token![box],
93 pub expr: Box<Expr>,
94 }),
95
96 /// A placement expression: `place <- value`.
97 ///
98 /// *This type is available if Syn is built with the `"full"` feature.*
99 pub InPlace(ExprInPlace #full {
100 pub attrs: Vec<Attribute>,
101 pub place: Box<Expr>,
102 pub arrow_token: Token![<-],
103 pub value: Box<Expr>,
104 }),
105
106 /// A slice literal expression: `[a, b, c, d]`.
107 ///
108 /// *This type is available if Syn is built with the `"full"` feature.*
109 pub Array(ExprArray #full {
110 pub attrs: Vec<Attribute>,
111 pub bracket_token: token::Bracket,
112 pub elems: Punctuated<Expr, Token![,]>,
113 }),
114
115 /// A function call expression: `invoke(a, b)`.
116 ///
117 /// *This type is available if Syn is built with the `"derive"` or
118 /// `"full"` feature.*
119 pub Call(ExprCall {
120 pub attrs: Vec<Attribute>,
121 pub func: Box<Expr>,
122 pub paren_token: token::Paren,
123 pub args: Punctuated<Expr, Token![,]>,
124 }),
125
126 /// A method call expression: `x.foo::<T>(a, b)`.
127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
129 pub MethodCall(ExprMethodCall #full {
130 pub attrs: Vec<Attribute>,
131 pub receiver: Box<Expr>,
132 pub dot_token: Token![.],
133 pub method: Ident,
134 pub turbofish: Option<MethodTurbofish>,
135 pub paren_token: token::Paren,
136 pub args: Punctuated<Expr, Token![,]>,
137 }),
138
139 /// A tuple expression: `(a, b, c, d)`.
140 ///
141 /// *This type is available if Syn is built with the `"full"` feature.*
142 pub Tuple(ExprTuple #full {
143 pub attrs: Vec<Attribute>,
144 pub paren_token: token::Paren,
145 pub elems: Punctuated<Expr, Token![,]>,
146 }),
147
148 /// A binary operation: `a + b`, `a * b`.
149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
152 pub Binary(ExprBinary {
153 pub attrs: Vec<Attribute>,
154 pub left: Box<Expr>,
155 pub op: BinOp,
156 pub right: Box<Expr>,
157 }),
158
159 /// A unary operation: `!x`, `*x`.
160 ///
161 /// *This type is available if Syn is built with the `"derive"` or
162 /// `"full"` feature.*
163 pub Unary(ExprUnary {
164 pub attrs: Vec<Attribute>,
165 pub op: UnOp,
166 pub expr: Box<Expr>,
167 }),
168
169 /// A literal in place of an expression: `1`, `"foo"`.
170 ///
171 /// *This type is available if Syn is built with the `"derive"` or
172 /// `"full"` feature.*
173 pub Lit(ExprLit {
174 pub attrs: Vec<Attribute>,
175 pub lit: Lit,
176 }),
177
178 /// A cast expression: `foo as f64`.
179 ///
180 /// *This type is available if Syn is built with the `"derive"` or
181 /// `"full"` feature.*
182 pub Cast(ExprCast {
183 pub attrs: Vec<Attribute>,
184 pub expr: Box<Expr>,
185 pub as_token: Token![as],
186 pub ty: Box<Type>,
187 }),
188
189 /// A type ascription expression: `foo: f64`.
190 ///
191 /// *This type is available if Syn is built with the `"full"` feature.*
192 pub Type(ExprType #full {
193 pub attrs: Vec<Attribute>,
194 pub expr: Box<Expr>,
195 pub colon_token: Token![:],
196 pub ty: Box<Type>,
197 }),
198
199 /// 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
210 /// An `if` expression with an optional `else` block: `if expr { ... }
211 /// else { ... }`.
212 ///
213 /// The `else` branch expression may only be an `If` or `Block`
214 /// expression, not any of the other types of expression.
215 ///
216 /// *This type is available if Syn is built with the `"full"` feature.*
217 pub If(ExprIf #full {
218 pub attrs: Vec<Attribute>,
219 pub if_token: Token![if],
220 pub cond: Box<Expr>,
221 pub then_branch: Block,
222 pub else_branch: Option<(Token![else], Box<Expr>)>,
223 }),
224
225 /// A while loop: `while expr { ... }`.
226 ///
227 /// *This type is available if Syn is built with the `"full"` feature.*
228 pub While(ExprWhile #full {
229 pub attrs: Vec<Attribute>,
230 pub label: Option<Label>,
231 pub while_token: Token![while],
232 pub cond: Box<Expr>,
233 pub body: Block,
234 }),
235
236 /// A for loop: `for pat in expr { ... }`.
237 ///
238 /// *This type is available if Syn is built with the `"full"` feature.*
239 pub ForLoop(ExprForLoop #full {
240 pub attrs: Vec<Attribute>,
241 pub label: Option<Label>,
242 pub for_token: Token![for],
243 pub pat: Box<Pat>,
244 pub in_token: Token![in],
245 pub expr: Box<Expr>,
246 pub body: Block,
247 }),
248
249 /// Conditionless loop: `loop { ... }`.
250 ///
251 /// *This type is available if Syn is built with the `"full"` feature.*
252 pub Loop(ExprLoop #full {
253 pub attrs: Vec<Attribute>,
254 pub label: Option<Label>,
255 pub loop_token: Token![loop],
256 pub body: Block,
257 }),
258
259 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
260 ///
261 /// *This type is available if Syn is built with the `"full"` feature.*
262 pub Match(ExprMatch #full {
263 pub attrs: Vec<Attribute>,
264 pub match_token: Token![match],
265 pub expr: Box<Expr>,
266 pub brace_token: token::Brace,
267 pub arms: Vec<Arm>,
268 }),
269
270 /// A closure expression: `|a, b| a + b`.
271 ///
272 /// *This type is available if Syn is built with the `"full"` feature.*
273 pub Closure(ExprClosure #full {
274 pub attrs: Vec<Attribute>,
275 pub asyncness: Option<Token![async]>,
276 pub movability: Option<Token![static]>,
277 pub capture: Option<Token![move]>,
278 pub or1_token: Token![|],
279 pub inputs: Punctuated<FnArg, Token![,]>,
280 pub or2_token: Token![|],
281 pub output: ReturnType,
282 pub body: Box<Expr>,
283 }),
284
285 /// An unsafe block: `unsafe { ... }`.
286 ///
287 /// *This type is available if Syn is built with the `"full"` feature.*
288 pub Unsafe(ExprUnsafe #full {
289 pub attrs: Vec<Attribute>,
290 pub unsafe_token: Token![unsafe],
291 pub block: Block,
292 }),
293
294 /// A blocked scope: `{ ... }`.
295 ///
296 /// *This type is available if Syn is built with the `"full"` feature.*
297 pub Block(ExprBlock #full {
298 pub attrs: Vec<Attribute>,
299 pub label: Option<Label>,
300 pub block: Block,
301 }),
302
303 /// An assignment expression: `a = compute()`.
304 ///
305 /// *This type is available if Syn is built with the `"full"` feature.*
306 pub Assign(ExprAssign #full {
307 pub attrs: Vec<Attribute>,
308 pub left: Box<Expr>,
309 pub eq_token: Token![=],
310 pub right: Box<Expr>,
311 }),
312
313 /// A compound assignment expression: `counter += 1`.
314 ///
315 /// *This type is available if Syn is built with the `"full"` feature.*
316 pub AssignOp(ExprAssignOp #full {
317 pub attrs: Vec<Attribute>,
318 pub left: Box<Expr>,
319 pub op: BinOp,
320 pub right: Box<Expr>,
321 }),
322
323 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
324 /// field (`obj.0`).
325 ///
326 /// *This type is available if Syn is built with the `"full"` feature.*
327 pub Field(ExprField {
328 pub attrs: Vec<Attribute>,
329 pub base: Box<Expr>,
330 pub dot_token: Token![.],
331 pub member: Member,
332 }),
333
334 /// A square bracketed indexing expression: `vector[2]`.
335 ///
336 /// *This type is available if Syn is built with the `"derive"` or
337 /// `"full"` feature.*
338 pub Index(ExprIndex {
339 pub attrs: Vec<Attribute>,
340 pub expr: Box<Expr>,
341 pub bracket_token: token::Bracket,
342 pub index: Box<Expr>,
343 }),
344
345 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
346 ///
347 /// *This type is available if Syn is built with the `"full"` feature.*
348 pub Range(ExprRange #full {
349 pub attrs: Vec<Attribute>,
350 pub from: Option<Box<Expr>>,
351 pub limits: RangeLimits,
352 pub to: Option<Box<Expr>>,
353 }),
354
355 /// A path like `std::mem::replace` possibly containing generic
356 /// parameters and a qualified self-type.
357 ///
358 /// A plain identifier like `x` is a path of length 1.
359 ///
360 /// *This type is available if Syn is built with the `"derive"` or
361 /// `"full"` feature.*
362 pub Path(ExprPath {
363 pub attrs: Vec<Attribute>,
364 pub qself: Option<QSelf>,
365 pub path: Path,
366 }),
367
368 /// A referencing operation: `&a` or `&mut a`.
369 ///
370 /// *This type is available if Syn is built with the `"full"` feature.*
371 pub Reference(ExprReference #full {
372 pub attrs: Vec<Attribute>,
373 pub and_token: Token![&],
374 pub mutability: Option<Token![mut]>,
375 pub expr: Box<Expr>,
376 }),
377
378 /// A `break`, with an optional label to break and an optional
379 /// expression.
380 ///
381 /// *This type is available if Syn is built with the `"full"` feature.*
382 pub Break(ExprBreak #full {
383 pub attrs: Vec<Attribute>,
384 pub break_token: Token![break],
385 pub label: Option<Lifetime>,
386 pub expr: Option<Box<Expr>>,
387 }),
388
389 /// A `continue`, with an optional label.
390 ///
391 /// *This type is available if Syn is built with the `"full"` feature.*
392 pub Continue(ExprContinue #full {
393 pub attrs: Vec<Attribute>,
394 pub continue_token: Token![continue],
395 pub label: Option<Lifetime>,
396 }),
397
398 /// A `return`, with an optional value to be returned.
399 ///
400 /// *This type is available if Syn is built with the `"full"` feature.*
401 pub Return(ExprReturn #full {
402 pub attrs: Vec<Attribute>,
403 pub return_token: Token![return],
404 pub expr: Option<Box<Expr>>,
405 }),
406
407 /// A macro invocation expression: `format!("{}", q)`.
408 ///
409 /// *This type is available if Syn is built with the `"full"` feature.*
410 pub Macro(ExprMacro #full {
411 pub attrs: Vec<Attribute>,
412 pub mac: Macro,
413 }),
414
415 /// A struct literal expression: `Point { x: 1, y: 1 }`.
416 ///
417 /// The `rest` provides the value of the remaining fields as in `S { a:
418 /// 1, b: 1, ..rest }`.
419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
421 pub Struct(ExprStruct #full {
422 pub attrs: Vec<Attribute>,
423 pub path: Path,
424 pub brace_token: token::Brace,
425 pub fields: Punctuated<FieldValue, Token![,]>,
426 pub dot2_token: Option<Token![..]>,
427 pub rest: Option<Box<Expr>>,
428 }),
429
430 /// An array literal constructed from one repeated element: `[0u8; N]`.
431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
433 pub Repeat(ExprRepeat #full {
434 pub attrs: Vec<Attribute>,
435 pub bracket_token: token::Bracket,
436 pub expr: Box<Expr>,
437 pub semi_token: Token![;],
438 pub len: Box<Expr>,
439 }),
440
441 /// A parenthesized expression: `(a + b)`.
442 ///
443 /// *This type is available if Syn is built with the `"full"` feature.*
444 pub Paren(ExprParen {
445 pub attrs: Vec<Attribute>,
446 pub paren_token: token::Paren,
447 pub expr: Box<Expr>,
448 }),
449
450 /// An expression contained within invisible delimiters.
451 ///
452 /// This variant is important for faithfully representing the precedence
453 /// of expressions and is related to `None`-delimited spans in a
454 /// `TokenStream`.
455 ///
456 /// *This type is available if Syn is built with the `"full"` feature.*
457 pub Group(ExprGroup #full {
458 pub attrs: Vec<Attribute>,
459 pub group_token: token::Group,
460 pub expr: Box<Expr>,
461 }),
462
463 /// A try-expression: `expr?`.
464 ///
465 /// *This type is available if Syn is built with the `"full"` feature.*
466 pub Try(ExprTry #full {
467 pub attrs: Vec<Attribute>,
468 pub expr: Box<Expr>,
469 pub question_token: Token![?],
470 }),
471
472 /// 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
482 /// A try block: `try { ... }`.
483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
485 pub TryBlock(ExprTryBlock #full {
486 pub attrs: Vec<Attribute>,
487 pub try_token: Token![try],
488 pub block: Block,
489 }),
490
491 /// A yield expression: `yield expr`.
492 ///
493 /// *This type is available if Syn is built with the `"full"` feature.*
494 pub Yield(ExprYield #full {
495 pub attrs: Vec<Attribute>,
496 pub yield_token: Token![yield],
497 pub expr: Option<Box<Expr>>,
498 }),
499
500 /// Tokens in expression position not interpreted by Syn.
501 ///
502 /// *This type is available if Syn is built with the `"derive"` or
503 /// `"full"` feature.*
504 pub Verbatim(ExprVerbatim #manual_extra_traits {
505 pub tts: TokenStream,
506 }),
507 }
508 }
509
510 #[cfg(feature = "extra-traits")]
511 impl Eq for ExprVerbatim {}
512
513 #[cfg(feature = "extra-traits")]
514 impl PartialEq for ExprVerbatim {
eq(&self, other: &Self) -> bool515 fn eq(&self, other: &Self) -> bool {
516 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
517 }
518 }
519
520 #[cfg(feature = "extra-traits")]
521 impl Hash for ExprVerbatim {
hash<H>(&self, state: &mut H) where H: Hasher,522 fn hash<H>(&self, state: &mut H)
523 where
524 H: Hasher,
525 {
526 TokenStreamHelper(&self.tts).hash(state);
527 }
528 }
529
530 impl Expr {
531 #[cfg(all(feature = "parsing", feature = "full"))]
replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute>532 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
533 match *self {
534 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, .. })
545 | Expr::Let(ExprLet { ref mut attrs, .. })
546 | Expr::If(ExprIf { ref mut attrs, .. })
547 | Expr::While(ExprWhile { ref mut attrs, .. })
548 | 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, .. })
560 | Expr::Reference(ExprReference { ref mut attrs, .. })
561 | 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, .. })
570 | Expr::Async(ExprAsync { ref mut attrs, .. })
571 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
572 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
573 Expr::Verbatim(_) => Vec::new(),
574 }
575 }
576 }
577
578 ast_enum! {
579 /// A struct or tuple struct field accessed in a struct literal or field
580 /// expression.
581 ///
582 /// *This type is available if Syn is built with the `"derive"` or `"full"`
583 /// feature.*
584 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
592 ast_struct! {
593 /// The index of an unnamed tuple struct field.
594 ///
595 /// *This type is available if Syn is built with the `"derive"` or `"full"`
596 /// feature.*
597 pub struct Index #manual_extra_traits {
598 pub index: u32,
599 pub span: Span,
600 }
601 }
602
603 impl From<usize> for Index {
from(index: usize) -> Index604 fn from(index: usize) -> Index {
605 assert!(index < u32::max_value() as usize);
606 Index {
607 index: index as u32,
608 span: Span::call_site(),
609 }
610 }
611 }
612
613 #[cfg(feature = "extra-traits")]
614 impl Eq for Index {}
615
616 #[cfg(feature = "extra-traits")]
617 impl PartialEq for Index {
eq(&self, other: &Self) -> bool618 fn eq(&self, other: &Self) -> bool {
619 self.index == other.index
620 }
621 }
622
623 #[cfg(feature = "extra-traits")]
624 impl Hash for Index {
hash<H: Hasher>(&self, state: &mut H)625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.index.hash(state);
627 }
628 }
629
630 #[cfg(feature = "full")]
631 ast_struct! {
632 /// The `::<>` explicit type parameters passed to a method call:
633 /// `parse::<u64>()`.
634 ///
635 /// *This type is available if Syn is built with the `"full"` feature.*
636 pub struct MethodTurbofish {
637 pub colon2_token: Token![::],
638 pub lt_token: Token![<],
639 pub args: Punctuated<GenericMethodArgument, Token![,]>,
640 pub gt_token: Token![>],
641 }
642 }
643
644 #[cfg(feature = "full")]
645 ast_enum! {
646 /// An individual generic argument to a method, like `T`.
647 ///
648 /// *This type is available if Syn is built with the `"full"` feature.*
649 pub enum GenericMethodArgument {
650 /// A type argument.
651 Type(Type),
652 /// A const expression. Must be inside of a block.
653 ///
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")]
661 ast_struct! {
662 /// A field-value pair in a struct literal.
663 ///
664 /// *This type is available if Syn is built with the `"full"` feature.*
665 pub struct FieldValue {
666 /// Attributes tagged on the field.
667 pub attrs: Vec<Attribute>,
668
669 /// Name or index of the field.
670 pub member: Member,
671
672 /// The colon in `Struct { x: x }`. If written in shorthand like
673 /// `Struct { x }`, there is no colon.
674 pub colon_token: Option<Token![:]>,
675
676 /// Value of the field.
677 pub expr: Expr,
678 }
679 }
680
681 #[cfg(feature = "full")]
682 ast_struct! {
683 /// A lifetime labeling a `for`, `while`, or `loop`.
684 ///
685 /// *This type is available if Syn is built with the `"full"` feature.*
686 pub struct Label {
687 pub name: Lifetime,
688 pub colon_token: Token![:],
689 }
690 }
691
692 #[cfg(feature = "full")]
693 ast_struct! {
694 /// A braced block containing Rust statements.
695 ///
696 /// *This type is available if Syn is built with the `"full"` feature.*
697 pub struct Block {
698 pub brace_token: token::Brace,
699 /// Statements in a block
700 pub stmts: Vec<Stmt>,
701 }
702 }
703
704 #[cfg(feature = "full")]
705 ast_enum! {
706 /// A statement, usually ending in a semicolon.
707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
709 pub enum Stmt {
710 /// A local (let) binding.
711 Local(Local),
712
713 /// An item definition.
714 Item(Item),
715
716 /// Expr without trailing semicolon.
717 Expr(Expr),
718
719 /// Expression with trailing semicolon.
720 Semi(Expr, Token![;]),
721 }
722 }
723
724 #[cfg(feature = "full")]
725 ast_struct! {
726 /// A local `let` binding: `let x: u64 = s.parse()?`.
727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
729 pub struct Local {
730 pub attrs: Vec<Attribute>,
731 pub let_token: Token![let],
732 pub pats: Punctuated<Pat, Token![|]>,
733 pub ty: Option<(Token![:], Box<Type>)>,
734 pub init: Option<(Token![=], Box<Expr>)>,
735 pub semi_token: Token![;],
736 }
737 }
738
739 #[cfg(feature = "full")]
740 ast_enum_of_structs! {
741 /// A pattern in a local binding, function signature, match expression, or
742 /// various other places.
743 ///
744 /// *This type is available if Syn is built with the `"full"` feature.*
745 ///
746 /// # Syntax tree enum
747 ///
748 /// This type is a [syntax tree enum].
749 ///
750 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
751 //
752 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
753 // blocked on https://github.com/rust-lang/rust/issues/62833
754 pub enum Pat {
755 /// A pattern that matches any value: `_`.
756 ///
757 /// *This type is available if Syn is built with the `"full"` feature.*
758 pub Wild(PatWild {
759 pub underscore_token: Token![_],
760 }),
761
762 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
763 ///
764 /// *This type is available if Syn is built with the `"full"` feature.*
765 pub Ident(PatIdent {
766 pub by_ref: Option<Token![ref]>,
767 pub mutability: Option<Token![mut]>,
768 pub ident: Ident,
769 pub subpat: Option<(Token![@], Box<Pat>)>,
770 }),
771
772 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
773 ///
774 /// *This type is available if Syn is built with the `"full"` feature.*
775 pub Struct(PatStruct {
776 pub path: Path,
777 pub brace_token: token::Brace,
778 pub fields: Punctuated<FieldPat, Token![,]>,
779 pub dot2_token: Option<Token![..]>,
780 }),
781
782 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
783 ///
784 /// *This type is available if Syn is built with the `"full"` feature.*
785 pub TupleStruct(PatTupleStruct {
786 pub path: Path,
787 pub pat: PatTuple,
788 }),
789
790 /// A path pattern like `Color::Red`, optionally qualified with a
791 /// self-type.
792 ///
793 /// Unqualified path patterns can legally refer to variants, structs,
794 /// constants or associated constants. Qualified path patterns like
795 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
796 /// associated constants.
797 ///
798 /// *This type is available if Syn is built with the `"full"` feature.*
799 pub Path(PatPath {
800 pub qself: Option<QSelf>,
801 pub path: Path,
802 }),
803
804 /// A tuple pattern: `(a, b)`.
805 ///
806 /// *This type is available if Syn is built with the `"full"` feature.*
807 pub Tuple(PatTuple {
808 pub paren_token: token::Paren,
809 pub front: Punctuated<Pat, Token![,]>,
810 pub dot2_token: Option<Token![..]>,
811 pub comma_token: Option<Token![,]>,
812 pub back: Punctuated<Pat, Token![,]>,
813 }),
814
815 /// A box pattern: `box v`.
816 ///
817 /// *This type is available if Syn is built with the `"full"` feature.*
818 pub Box(PatBox {
819 pub box_token: Token![box],
820 pub pat: Box<Pat>,
821 }),
822
823 /// A reference pattern: `&mut (first, second)`.
824 ///
825 /// *This type is available if Syn is built with the `"full"` feature.*
826 pub Ref(PatRef {
827 pub and_token: Token![&],
828 pub mutability: Option<Token![mut]>,
829 pub pat: Box<Pat>,
830 }),
831
832 /// A literal pattern: `0`.
833 ///
834 /// This holds an `Expr` rather than a `Lit` because negative numbers
835 /// are represented as an `Expr::Unary`.
836 ///
837 /// *This type is available if Syn is built with the `"full"` feature.*
838 pub Lit(PatLit {
839 pub expr: Box<Expr>,
840 }),
841
842 /// A range pattern: `1..=2`.
843 ///
844 /// *This type is available if Syn is built with the `"full"` feature.*
845 pub Range(PatRange {
846 pub lo: Box<Expr>,
847 pub limits: RangeLimits,
848 pub hi: Box<Expr>,
849 }),
850
851 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
852 ///
853 /// *This type is available if Syn is built with the `"full"` feature.*
854 pub Slice(PatSlice {
855 pub bracket_token: token::Bracket,
856 pub front: Punctuated<Pat, Token![,]>,
857 pub middle: Option<Box<Pat>>,
858 pub dot2_token: Option<Token![..]>,
859 pub comma_token: Option<Token![,]>,
860 pub back: Punctuated<Pat, Token![,]>,
861 }),
862
863 /// A macro in expression position.
864 ///
865 /// *This type is available if Syn is built with the `"full"` feature.*
866 pub Macro(PatMacro {
867 pub mac: Macro,
868 }),
869
870 /// Tokens in pattern position not interpreted by Syn.
871 ///
872 /// *This type is available if Syn is built with the `"full"` feature.*
873 pub Verbatim(PatVerbatim #manual_extra_traits {
874 pub tts: TokenStream,
875 }),
876 }
877 }
878
879 #[cfg(all(feature = "full", feature = "extra-traits"))]
880 impl Eq for PatVerbatim {}
881
882 #[cfg(all(feature = "full", feature = "extra-traits"))]
883 impl PartialEq for PatVerbatim {
eq(&self, other: &Self) -> bool884 fn eq(&self, other: &Self) -> bool {
885 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
886 }
887 }
888
889 #[cfg(all(feature = "full", feature = "extra-traits"))]
890 impl Hash for PatVerbatim {
hash<H>(&self, state: &mut H) where H: Hasher,891 fn hash<H>(&self, state: &mut H)
892 where
893 H: Hasher,
894 {
895 TokenStreamHelper(&self.tts).hash(state);
896 }
897 }
898
899 #[cfg(feature = "full")]
900 ast_struct! {
901 /// One arm of a `match` expression: `0...10 => { return true; }`.
902 ///
903 /// As in:
904 ///
905 /// ```edition2018
906 /// # fn f() -> bool {
907 /// # let n = 0;
908 /// match n {
909 /// 0...10 => {
910 /// return true;
911 /// }
912 /// // ...
913 /// # _ => {}
914 /// }
915 /// # false
916 /// # }
917 /// ```
918 ///
919 /// *This type is available if Syn is built with the `"full"` feature.*
920 pub struct Arm {
921 pub attrs: Vec<Attribute>,
922 pub leading_vert: Option<Token![|]>,
923 pub pats: Punctuated<Pat, Token![|]>,
924 pub guard: Option<(Token![if], Box<Expr>)>,
925 pub fat_arrow_token: Token![=>],
926 pub body: Box<Expr>,
927 pub comma: Option<Token![,]>,
928 }
929 }
930
931 #[cfg(feature = "full")]
932 ast_enum! {
933 /// Limit types of a range, inclusive or exclusive.
934 ///
935 /// *This type is available if Syn is built with the `"full"` feature.*
936 #[cfg_attr(feature = "clone-impls", derive(Copy))]
937 pub enum RangeLimits {
938 /// Inclusive at the beginning, exclusive at the end.
939 HalfOpen(Token![..]),
940 /// Inclusive at the beginning and end.
941 Closed(Token![..=]),
942 }
943 }
944
945 #[cfg(feature = "full")]
946 ast_struct! {
947 /// A single field in a struct pattern.
948 ///
949 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
950 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
951 ///
952 /// *This type is available if Syn is built with the `"full"` feature.*
953 pub struct FieldPat {
954 pub attrs: Vec<Attribute>,
955 pub member: Member,
956 pub colon_token: Option<Token![:]>,
957 pub pat: Box<Pat>,
958 }
959 }
960
961 #[cfg(any(feature = "parsing", feature = "printing"))]
962 #[cfg(feature = "full")]
requires_terminator(expr: &Expr) -> bool963 fn requires_terminator(expr: &Expr) -> bool {
964 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
965 match *expr {
966 Expr::Unsafe(..)
967 | Expr::Block(..)
968 | Expr::If(..)
969 | Expr::Match(..)
970 | Expr::While(..)
971 | Expr::Loop(..)
972 | Expr::ForLoop(..)
973 | Expr::Async(..)
974 | Expr::TryBlock(..) => false,
975 _ => true,
976 }
977 }
978
979 #[cfg(feature = "parsing")]
980 pub mod parsing {
981 use super::*;
982
983 #[cfg(feature = "full")]
984 use ext::IdentExt;
985 use parse::{Parse, ParseStream, Result};
986 use path;
987
988 // When we're parsing expressions which occur before blocks, like in an if
989 // statement's condition, we cannot parse a struct literal.
990 //
991 // Struct literals are ambiguous in certain positions
992 // https://github.com/rust-lang/rfcs/pull/92
993 #[derive(Copy, Clone)]
994 pub struct AllowStruct(bool);
995
996 #[derive(Copy, Clone, PartialEq, PartialOrd)]
997 enum Precedence {
998 Any,
999 Assign,
1000 Range,
1001 Or,
1002 And,
1003 Compare,
1004 BitOr,
1005 BitXor,
1006 BitAnd,
1007 Shift,
1008 Arithmetic,
1009 Term,
1010 Cast,
1011 }
1012
1013 impl Precedence {
of(op: &BinOp) -> Self1014 fn of(op: &BinOp) -> Self {
1015 match *op {
1016 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1017 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1018 BinOp::And(_) => Precedence::And,
1019 BinOp::Or(_) => Precedence::Or,
1020 BinOp::BitXor(_) => Precedence::BitXor,
1021 BinOp::BitAnd(_) => Precedence::BitAnd,
1022 BinOp::BitOr(_) => Precedence::BitOr,
1023 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1024 BinOp::Eq(_)
1025 | BinOp::Lt(_)
1026 | BinOp::Le(_)
1027 | BinOp::Ne(_)
1028 | BinOp::Ge(_)
1029 | BinOp::Gt(_) => Precedence::Compare,
1030 BinOp::AddEq(_)
1031 | BinOp::SubEq(_)
1032 | BinOp::MulEq(_)
1033 | BinOp::DivEq(_)
1034 | BinOp::RemEq(_)
1035 | BinOp::BitXorEq(_)
1036 | BinOp::BitAndEq(_)
1037 | BinOp::BitOrEq(_)
1038 | BinOp::ShlEq(_)
1039 | BinOp::ShrEq(_) => Precedence::Assign,
1040 }
1041 }
1042 }
1043
1044 impl Parse for Expr {
parse(input: ParseStream) -> Result<Self>1045 fn parse(input: ParseStream) -> Result<Self> {
1046 ambiguous_expr(input, AllowStruct(true))
1047 }
1048 }
1049
1050 #[cfg(feature = "full")]
expr_no_struct(input: ParseStream) -> Result<Expr>1051 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
1052 ambiguous_expr(input, AllowStruct(false))
1053 }
1054
1055 #[cfg(feature = "full")]
parse_expr( input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence, ) -> Result<Expr>1056 fn parse_expr(
1057 input: ParseStream,
1058 mut lhs: Expr,
1059 allow_struct: AllowStruct,
1060 base: Precedence,
1061 ) -> Result<Expr> {
1062 loop {
1063 if input
1064 .fork()
1065 .parse::<BinOp>()
1066 .ok()
1067 .map_or(false, |op| Precedence::of(&op) >= base)
1068 {
1069 let op: BinOp = input.parse()?;
1070 let precedence = Precedence::of(&op);
1071 let mut rhs = unary_expr(input, allow_struct)?;
1072 loop {
1073 let next = peek_precedence(input);
1074 if next > precedence || next == precedence && precedence == Precedence::Assign {
1075 rhs = parse_expr(input, rhs, allow_struct, next)?;
1076 } else {
1077 break;
1078 }
1079 }
1080 lhs = if precedence == Precedence::Assign {
1081 Expr::AssignOp(ExprAssignOp {
1082 attrs: Vec::new(),
1083 left: Box::new(lhs),
1084 op: op,
1085 right: Box::new(rhs),
1086 })
1087 } else {
1088 Expr::Binary(ExprBinary {
1089 attrs: Vec::new(),
1090 left: Box::new(lhs),
1091 op: op,
1092 right: Box::new(rhs),
1093 })
1094 };
1095 } else if Precedence::Assign >= base
1096 && input.peek(Token![=])
1097 && !input.peek(Token![==])
1098 && !input.peek(Token![=>])
1099 {
1100 let eq_token: Token![=] = input.parse()?;
1101 let mut rhs = unary_expr(input, allow_struct)?;
1102 loop {
1103 let next = peek_precedence(input);
1104 if next >= Precedence::Assign {
1105 rhs = parse_expr(input, rhs, allow_struct, next)?;
1106 } else {
1107 break;
1108 }
1109 }
1110 lhs = Expr::Assign(ExprAssign {
1111 attrs: Vec::new(),
1112 left: Box::new(lhs),
1113 eq_token: eq_token,
1114 right: Box::new(rhs),
1115 });
1116 } else if Precedence::Range >= base && input.peek(Token![..]) {
1117 let limits: RangeLimits = input.parse()?;
1118 let rhs = if input.is_empty()
1119 || input.peek(Token![,])
1120 || input.peek(Token![;])
1121 || !allow_struct.0 && input.peek(token::Brace)
1122 {
1123 None
1124 } else {
1125 let mut rhs = unary_expr(input, allow_struct)?;
1126 loop {
1127 let next = peek_precedence(input);
1128 if next > Precedence::Range {
1129 rhs = parse_expr(input, rhs, allow_struct, next)?;
1130 } else {
1131 break;
1132 }
1133 }
1134 Some(rhs)
1135 };
1136 lhs = Expr::Range(ExprRange {
1137 attrs: Vec::new(),
1138 from: Some(Box::new(lhs)),
1139 limits: limits,
1140 to: rhs.map(Box::new),
1141 });
1142 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1143 let as_token: Token![as] = input.parse()?;
1144 let ty = input.call(Type::without_plus)?;
1145 lhs = Expr::Cast(ExprCast {
1146 attrs: Vec::new(),
1147 expr: Box::new(lhs),
1148 as_token: as_token,
1149 ty: Box::new(ty),
1150 });
1151 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1152 let colon_token: Token![:] = input.parse()?;
1153 let ty = input.call(Type::without_plus)?;
1154 lhs = Expr::Type(ExprType {
1155 attrs: Vec::new(),
1156 expr: Box::new(lhs),
1157 colon_token: colon_token,
1158 ty: Box::new(ty),
1159 });
1160 } else {
1161 break;
1162 }
1163 }
1164 Ok(lhs)
1165 }
1166
1167 #[cfg(not(feature = "full"))]
parse_expr( input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence, ) -> Result<Expr>1168 fn parse_expr(
1169 input: ParseStream,
1170 mut lhs: Expr,
1171 allow_struct: AllowStruct,
1172 base: Precedence,
1173 ) -> Result<Expr> {
1174 loop {
1175 if input
1176 .fork()
1177 .parse::<BinOp>()
1178 .ok()
1179 .map_or(false, |op| Precedence::of(&op) >= base)
1180 {
1181 let op: BinOp = input.parse()?;
1182 let precedence = Precedence::of(&op);
1183 let mut rhs = unary_expr(input, allow_struct)?;
1184 loop {
1185 let next = peek_precedence(input);
1186 if next > precedence || next == precedence && precedence == Precedence::Assign {
1187 rhs = parse_expr(input, rhs, allow_struct, next)?;
1188 } else {
1189 break;
1190 }
1191 }
1192 lhs = Expr::Binary(ExprBinary {
1193 attrs: Vec::new(),
1194 left: Box::new(lhs),
1195 op: op,
1196 right: Box::new(rhs),
1197 });
1198 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1199 let as_token: Token![as] = input.parse()?;
1200 let ty = input.call(Type::without_plus)?;
1201 lhs = Expr::Cast(ExprCast {
1202 attrs: Vec::new(),
1203 expr: Box::new(lhs),
1204 as_token: as_token,
1205 ty: Box::new(ty),
1206 });
1207 } else {
1208 break;
1209 }
1210 }
1211 Ok(lhs)
1212 }
1213
peek_precedence(input: ParseStream) -> Precedence1214 fn peek_precedence(input: ParseStream) -> Precedence {
1215 if let Ok(op) = input.fork().parse() {
1216 Precedence::of(&op)
1217 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1218 Precedence::Assign
1219 } else if input.peek(Token![..]) {
1220 Precedence::Range
1221 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1222 Precedence::Cast
1223 } else {
1224 Precedence::Any
1225 }
1226 }
1227
1228 // Parse an arbitrary expression.
ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1229 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1230 let lhs = unary_expr(input, allow_struct)?;
1231 parse_expr(input, lhs, allow_struct, Precedence::Any)
1232 }
1233
1234 // <UnOp> <trailer>
1235 // & <trailer>
1236 // &mut <trailer>
1237 // box <trailer>
1238 #[cfg(feature = "full")]
unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1239 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1240 // TODO: optimize using advance_to
1241 let ahead = input.fork();
1242 ahead.call(Attribute::parse_outer)?;
1243 if ahead.peek(Token![&])
1244 || ahead.peek(Token![box])
1245 || ahead.peek(Token![*])
1246 || ahead.peek(Token![!])
1247 || ahead.peek(Token![-])
1248 {
1249 let attrs = input.call(Attribute::parse_outer)?;
1250 if input.peek(Token![&]) {
1251 Ok(Expr::Reference(ExprReference {
1252 attrs: attrs,
1253 and_token: input.parse()?,
1254 mutability: input.parse()?,
1255 expr: Box::new(unary_expr(input, allow_struct)?),
1256 }))
1257 } else if input.peek(Token![box]) {
1258 Ok(Expr::Box(ExprBox {
1259 attrs: attrs,
1260 box_token: input.parse()?,
1261 expr: Box::new(unary_expr(input, allow_struct)?),
1262 }))
1263 } else {
1264 Ok(Expr::Unary(ExprUnary {
1265 attrs: attrs,
1266 op: input.parse()?,
1267 expr: Box::new(unary_expr(input, allow_struct)?),
1268 }))
1269 }
1270 } else {
1271 trailer_expr(input, allow_struct)
1272 }
1273 }
1274
1275 #[cfg(not(feature = "full"))]
unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1276 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1277 // TODO: optimize using advance_to
1278 let ahead = input.fork();
1279 ahead.call(Attribute::parse_outer)?;
1280 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1281 Ok(Expr::Unary(ExprUnary {
1282 attrs: input.call(Attribute::parse_outer)?,
1283 op: input.parse()?,
1284 expr: Box::new(unary_expr(input, allow_struct)?),
1285 }))
1286 } else {
1287 trailer_expr(input, allow_struct)
1288 }
1289 }
1290
1291 // <atom> (..<args>) ...
1292 // <atom> . <ident> (..<args>) ...
1293 // <atom> . <ident> ...
1294 // <atom> . <lit> ...
1295 // <atom> [ <expr> ] ...
1296 // <atom> ? ...
1297 #[cfg(feature = "full")]
trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1298 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1299 if input.peek(token::Group) {
1300 return input.call(expr_group).map(Expr::Group);
1301 }
1302
1303 let outer_attrs = input.call(Attribute::parse_outer)?;
1304
1305 let atom = atom_expr(input, allow_struct)?;
1306 let mut e = trailer_helper(input, atom)?;
1307
1308 let inner_attrs = e.replace_attrs(Vec::new());
1309 let attrs = private::attrs(outer_attrs, inner_attrs);
1310 e.replace_attrs(attrs);
1311 Ok(e)
1312 }
1313
1314 #[cfg(feature = "full")]
trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr>1315 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1316 loop {
1317 if input.peek(token::Paren) {
1318 let content;
1319 e = Expr::Call(ExprCall {
1320 attrs: Vec::new(),
1321 func: Box::new(e),
1322 paren_token: parenthesized!(content in input),
1323 args: content.parse_terminated(Expr::parse)?,
1324 });
1325 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1326 let dot_token: Token![.] = input.parse()?;
1327 let member: Member = input.parse()?;
1328 let turbofish = if member.is_named() && input.peek(Token![::]) {
1329 Some(MethodTurbofish {
1330 colon2_token: input.parse()?,
1331 lt_token: input.parse()?,
1332 args: {
1333 let mut args = Punctuated::new();
1334 loop {
1335 if input.peek(Token![>]) {
1336 break;
1337 }
1338 let value = input.call(generic_method_argument)?;
1339 args.push_value(value);
1340 if input.peek(Token![>]) {
1341 break;
1342 }
1343 let punct = input.parse()?;
1344 args.push_punct(punct);
1345 }
1346 args
1347 },
1348 gt_token: input.parse()?,
1349 })
1350 } else {
1351 None
1352 };
1353
1354 if turbofish.is_some() || input.peek(token::Paren) {
1355 if let Member::Named(method) = member {
1356 let content;
1357 e = Expr::MethodCall(ExprMethodCall {
1358 attrs: Vec::new(),
1359 receiver: Box::new(e),
1360 dot_token: dot_token,
1361 method: method,
1362 turbofish: turbofish,
1363 paren_token: parenthesized!(content in input),
1364 args: content.parse_terminated(Expr::parse)?,
1365 });
1366 continue;
1367 }
1368 }
1369
1370 e = Expr::Field(ExprField {
1371 attrs: Vec::new(),
1372 base: Box::new(e),
1373 dot_token: dot_token,
1374 member: member,
1375 });
1376 } else if input.peek(token::Bracket) {
1377 let content;
1378 e = Expr::Index(ExprIndex {
1379 attrs: Vec::new(),
1380 expr: Box::new(e),
1381 bracket_token: bracketed!(content in input),
1382 index: content.parse()?,
1383 });
1384 } else if input.peek(Token![?]) {
1385 e = Expr::Try(ExprTry {
1386 attrs: Vec::new(),
1387 expr: Box::new(e),
1388 question_token: input.parse()?,
1389 });
1390 } else {
1391 break;
1392 }
1393 }
1394 Ok(e)
1395 }
1396
1397 #[cfg(not(feature = "full"))]
trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1398 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1399 let mut e = atom_expr(input, allow_struct)?;
1400
1401 loop {
1402 if input.peek(token::Paren) {
1403 let content;
1404 e = Expr::Call(ExprCall {
1405 attrs: Vec::new(),
1406 func: Box::new(e),
1407 paren_token: parenthesized!(content in input),
1408 args: content.parse_terminated(Expr::parse)?,
1409 });
1410 } else if input.peek(Token![.]) {
1411 e = Expr::Field(ExprField {
1412 attrs: Vec::new(),
1413 base: Box::new(e),
1414 dot_token: input.parse()?,
1415 member: input.parse()?,
1416 });
1417 } else if input.peek(token::Bracket) {
1418 let content;
1419 e = Expr::Index(ExprIndex {
1420 attrs: Vec::new(),
1421 expr: Box::new(e),
1422 bracket_token: bracketed!(content in input),
1423 index: content.parse()?,
1424 });
1425 } else {
1426 break;
1427 }
1428 }
1429
1430 Ok(e)
1431 }
1432
1433 // Parse all atomic expressions which don't have to worry about precedence
1434 // interactions, as they are fully contained.
1435 #[cfg(feature = "full")]
atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1436 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1437 if input.peek(token::Group) {
1438 input.call(expr_group).map(Expr::Group)
1439 } else if input.peek(Lit) {
1440 input.parse().map(Expr::Lit)
1441 } else if input.peek(Token![async])
1442 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1443 {
1444 input.call(expr_async).map(Expr::Async)
1445 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1446 input.call(expr_try_block).map(Expr::TryBlock)
1447 } else if input.peek(Token![|])
1448 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1449 || input.peek(Token![static])
1450 || input.peek(Token![move])
1451 {
1452 expr_closure(input, allow_struct).map(Expr::Closure)
1453 } else if input.peek(Ident)
1454 || input.peek(Token![::])
1455 || input.peek(Token![<])
1456 || input.peek(Token![self])
1457 || input.peek(Token![Self])
1458 || input.peek(Token![super])
1459 || input.peek(Token![extern])
1460 || input.peek(Token![crate])
1461 {
1462 path_or_macro_or_struct(input, allow_struct)
1463 } else if input.peek(token::Paren) {
1464 paren_or_tuple(input)
1465 } else if input.peek(Token![break]) {
1466 expr_break(input, allow_struct).map(Expr::Break)
1467 } else if input.peek(Token![continue]) {
1468 input.call(expr_continue).map(Expr::Continue)
1469 } else if input.peek(Token![return]) {
1470 expr_ret(input, allow_struct).map(Expr::Return)
1471 } else if input.peek(token::Bracket) {
1472 array_or_repeat(input)
1473 } else if input.peek(Token![let]) {
1474 input.call(expr_let).map(Expr::Let)
1475 } else if input.peek(Token![if]) {
1476 input.parse().map(Expr::If)
1477 } else if input.peek(Token![while]) {
1478 input.parse().map(Expr::While)
1479 } else if input.peek(Token![for]) {
1480 input.parse().map(Expr::ForLoop)
1481 } else if input.peek(Token![loop]) {
1482 input.parse().map(Expr::Loop)
1483 } else if input.peek(Token![match]) {
1484 input.parse().map(Expr::Match)
1485 } else if input.peek(Token![yield]) {
1486 input.call(expr_yield).map(Expr::Yield)
1487 } else if input.peek(Token![unsafe]) {
1488 input.call(expr_unsafe).map(Expr::Unsafe)
1489 } else if input.peek(token::Brace) {
1490 input.call(expr_block).map(Expr::Block)
1491 } else if input.peek(Token![..]) {
1492 expr_range(input, allow_struct).map(Expr::Range)
1493 } else if input.peek(Lifetime) {
1494 let the_label: Label = input.parse()?;
1495 let mut expr = if input.peek(Token![while]) {
1496 Expr::While(input.parse()?)
1497 } else if input.peek(Token![for]) {
1498 Expr::ForLoop(input.parse()?)
1499 } else if input.peek(Token![loop]) {
1500 Expr::Loop(input.parse()?)
1501 } else if input.peek(token::Brace) {
1502 Expr::Block(input.call(expr_block)?)
1503 } else {
1504 return Err(input.error("expected loop or block expression"));
1505 };
1506 match expr {
1507 Expr::While(ExprWhile { ref mut label, .. })
1508 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1509 | Expr::Loop(ExprLoop { ref mut label, .. })
1510 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
1511 _ => unreachable!(),
1512 }
1513 Ok(expr)
1514 } else {
1515 Err(input.error("expected expression"))
1516 }
1517 }
1518
1519 #[cfg(not(feature = "full"))]
atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr>1520 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
1521 if input.peek(Lit) {
1522 input.parse().map(Expr::Lit)
1523 } else if input.peek(token::Paren) {
1524 input.call(expr_paren).map(Expr::Paren)
1525 } else if input.peek(Ident)
1526 || input.peek(Token![::])
1527 || input.peek(Token![<])
1528 || input.peek(Token![self])
1529 || input.peek(Token![Self])
1530 || input.peek(Token![super])
1531 || input.peek(Token![extern])
1532 || input.peek(Token![crate])
1533 {
1534 input.parse().map(Expr::Path)
1535 } else {
1536 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1537 }
1538 }
1539
1540 #[cfg(feature = "full")]
path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1541 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1542 let expr: ExprPath = input.parse()?;
1543 if expr.qself.is_some() {
1544 return Ok(Expr::Path(expr));
1545 }
1546
1547 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1548 let mut contains_arguments = false;
1549 for segment in &expr.path.segments {
1550 match segment.arguments {
1551 PathArguments::None => {}
1552 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1553 contains_arguments = true;
1554 }
1555 }
1556 }
1557
1558 if !contains_arguments {
1559 let bang_token: Token![!] = input.parse()?;
1560 let (delimiter, tts) = mac::parse_delimiter(input)?;
1561 return Ok(Expr::Macro(ExprMacro {
1562 attrs: Vec::new(),
1563 mac: Macro {
1564 path: expr.path,
1565 bang_token: bang_token,
1566 delimiter: delimiter,
1567 tts: tts,
1568 },
1569 }));
1570 }
1571 }
1572
1573 if allow_struct.0 && input.peek(token::Brace) {
1574 let outer_attrs = Vec::new();
1575 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1576 } else {
1577 Ok(Expr::Path(expr))
1578 }
1579 }
1580
1581 #[cfg(feature = "full")]
paren_or_tuple(input: ParseStream) -> Result<Expr>1582 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1583 let content;
1584 let paren_token = parenthesized!(content in input);
1585 let inner_attrs = content.call(Attribute::parse_inner)?;
1586 if content.is_empty() {
1587 return Ok(Expr::Tuple(ExprTuple {
1588 attrs: inner_attrs,
1589 paren_token: paren_token,
1590 elems: Punctuated::new(),
1591 }));
1592 }
1593
1594 let first: Expr = content.parse()?;
1595 if content.is_empty() {
1596 return Ok(Expr::Paren(ExprParen {
1597 attrs: inner_attrs,
1598 paren_token: paren_token,
1599 expr: Box::new(first),
1600 }));
1601 }
1602
1603 let mut elems = Punctuated::new();
1604 elems.push_value(first);
1605 while !content.is_empty() {
1606 let punct = content.parse()?;
1607 elems.push_punct(punct);
1608 if content.is_empty() {
1609 break;
1610 }
1611 let value = content.parse()?;
1612 elems.push_value(value);
1613 }
1614 Ok(Expr::Tuple(ExprTuple {
1615 attrs: inner_attrs,
1616 paren_token: paren_token,
1617 elems: elems,
1618 }))
1619 }
1620
1621 #[cfg(feature = "full")]
array_or_repeat(input: ParseStream) -> Result<Expr>1622 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1623 let content;
1624 let bracket_token = bracketed!(content in input);
1625 let inner_attrs = content.call(Attribute::parse_inner)?;
1626 if content.is_empty() {
1627 return Ok(Expr::Array(ExprArray {
1628 attrs: inner_attrs,
1629 bracket_token: bracket_token,
1630 elems: Punctuated::new(),
1631 }));
1632 }
1633
1634 let first: Expr = content.parse()?;
1635 if content.is_empty() || content.peek(Token![,]) {
1636 let mut elems = Punctuated::new();
1637 elems.push_value(first);
1638 while !content.is_empty() {
1639 let punct = content.parse()?;
1640 elems.push_punct(punct);
1641 if content.is_empty() {
1642 break;
1643 }
1644 let value = content.parse()?;
1645 elems.push_value(value);
1646 }
1647 Ok(Expr::Array(ExprArray {
1648 attrs: inner_attrs,
1649 bracket_token: bracket_token,
1650 elems: elems,
1651 }))
1652 } else if content.peek(Token![;]) {
1653 let semi_token: Token![;] = content.parse()?;
1654 let len: Expr = content.parse()?;
1655 Ok(Expr::Repeat(ExprRepeat {
1656 attrs: inner_attrs,
1657 bracket_token: bracket_token,
1658 expr: Box::new(first),
1659 semi_token: semi_token,
1660 len: Box::new(len),
1661 }))
1662 } else {
1663 Err(content.error("expected `,` or `;`"))
1664 }
1665 }
1666
1667 #[cfg(feature = "full")]
expr_early(input: ParseStream) -> Result<Expr>1668 fn expr_early(input: ParseStream) -> Result<Expr> {
1669 let mut attrs = input.call(Attribute::parse_outer)?;
1670 let mut expr = if input.peek(Token![if]) {
1671 Expr::If(input.parse()?)
1672 } else if input.peek(Token![while]) {
1673 Expr::While(input.parse()?)
1674 } else if input.peek(Token![for]) {
1675 Expr::ForLoop(input.parse()?)
1676 } else if input.peek(Token![loop]) {
1677 Expr::Loop(input.parse()?)
1678 } else if input.peek(Token![match]) {
1679 Expr::Match(input.parse()?)
1680 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1681 Expr::TryBlock(input.call(expr_try_block)?)
1682 } else if input.peek(Token![unsafe]) {
1683 Expr::Unsafe(input.call(expr_unsafe)?)
1684 } else if input.peek(token::Brace) {
1685 Expr::Block(input.call(expr_block)?)
1686 } else {
1687 let allow_struct = AllowStruct(true);
1688 let mut expr = unary_expr(input, allow_struct)?;
1689
1690 attrs.extend(expr.replace_attrs(Vec::new()));
1691 expr.replace_attrs(attrs);
1692
1693 return parse_expr(input, expr, allow_struct, Precedence::Any);
1694 };
1695
1696 if input.peek(Token![.]) || input.peek(Token![?]) {
1697 expr = trailer_helper(input, expr)?;
1698
1699 attrs.extend(expr.replace_attrs(Vec::new()));
1700 expr.replace_attrs(attrs);
1701
1702 let allow_struct = AllowStruct(true);
1703 return parse_expr(input, expr, allow_struct, Precedence::Any);
1704 }
1705
1706 attrs.extend(expr.replace_attrs(Vec::new()));
1707 expr.replace_attrs(attrs);
1708 Ok(expr)
1709 }
1710
1711 impl Parse for ExprLit {
parse(input: ParseStream) -> Result<Self>1712 fn parse(input: ParseStream) -> Result<Self> {
1713 Ok(ExprLit {
1714 attrs: Vec::new(),
1715 lit: input.parse()?,
1716 })
1717 }
1718 }
1719
1720 #[cfg(feature = "full")]
expr_group(input: ParseStream) -> Result<ExprGroup>1721 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1722 let group = private::parse_group(input)?;
1723 Ok(ExprGroup {
1724 attrs: Vec::new(),
1725 group_token: group.token,
1726 expr: group.content.parse()?,
1727 })
1728 }
1729
1730 #[cfg(not(feature = "full"))]
expr_paren(input: ParseStream) -> Result<ExprParen>1731 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1732 let content;
1733 Ok(ExprParen {
1734 attrs: Vec::new(),
1735 paren_token: parenthesized!(content in input),
1736 expr: content.parse()?,
1737 })
1738 }
1739
1740 #[cfg(feature = "full")]
generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument>1741 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
1742 // TODO parse const generics as well
1743 input.parse().map(GenericMethodArgument::Type)
1744 }
1745
1746 #[cfg(feature = "full")]
expr_let(input: ParseStream) -> Result<ExprLet>1747 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1748 Ok(ExprLet {
1749 attrs: Vec::new(),
1750 let_token: input.parse()?,
1751 pats: {
1752 let mut pats = Punctuated::new();
1753 input.parse::<Option<Token![|]>>()?;
1754 let value: Pat = input.parse()?;
1755 pats.push_value(value);
1756 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
1757 let punct = input.parse()?;
1758 pats.push_punct(punct);
1759 let value: Pat = input.parse()?;
1760 pats.push_value(value);
1761 }
1762 pats
1763 },
1764 eq_token: input.parse()?,
1765 expr: Box::new(input.call(expr_no_struct)?),
1766 })
1767 }
1768
1769 #[cfg(feature = "full")]
1770 impl Parse for ExprIf {
parse(input: ParseStream) -> Result<Self>1771 fn parse(input: ParseStream) -> Result<Self> {
1772 Ok(ExprIf {
1773 attrs: Vec::new(),
1774 if_token: input.parse()?,
1775 cond: Box::new(input.call(expr_no_struct)?),
1776 then_branch: input.parse()?,
1777 else_branch: {
1778 if input.peek(Token![else]) {
1779 Some(input.call(else_block)?)
1780 } else {
1781 None
1782 }
1783 },
1784 })
1785 }
1786 }
1787
1788 #[cfg(feature = "full")]
else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)>1789 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1790 let else_token: Token![else] = input.parse()?;
1791
1792 let lookahead = input.lookahead1();
1793 let else_branch = if input.peek(Token![if]) {
1794 input.parse().map(Expr::If)?
1795 } else if input.peek(token::Brace) {
1796 Expr::Block(ExprBlock {
1797 attrs: Vec::new(),
1798 label: None,
1799 block: input.parse()?,
1800 })
1801 } else {
1802 return Err(lookahead.error());
1803 };
1804
1805 Ok((else_token, Box::new(else_branch)))
1806 }
1807
1808 #[cfg(feature = "full")]
1809 impl Parse for ExprForLoop {
parse(input: ParseStream) -> Result<Self>1810 fn parse(input: ParseStream) -> Result<Self> {
1811 let label: Option<Label> = input.parse()?;
1812 let for_token: Token![for] = input.parse()?;
1813 let pat: Pat = input.parse()?;
1814 let in_token: Token![in] = input.parse()?;
1815 let expr: Expr = input.call(expr_no_struct)?;
1816
1817 let content;
1818 let brace_token = braced!(content in input);
1819 let inner_attrs = content.call(Attribute::parse_inner)?;
1820 let stmts = content.call(Block::parse_within)?;
1821
1822 Ok(ExprForLoop {
1823 attrs: inner_attrs,
1824 label: label,
1825 for_token: for_token,
1826 pat: Box::new(pat),
1827 in_token: in_token,
1828 expr: Box::new(expr),
1829 body: Block {
1830 brace_token: brace_token,
1831 stmts: stmts,
1832 },
1833 })
1834 }
1835 }
1836
1837 #[cfg(feature = "full")]
1838 impl Parse for ExprLoop {
parse(input: ParseStream) -> Result<Self>1839 fn parse(input: ParseStream) -> Result<Self> {
1840 let label: Option<Label> = input.parse()?;
1841 let loop_token: Token![loop] = input.parse()?;
1842
1843 let content;
1844 let brace_token = braced!(content in input);
1845 let inner_attrs = content.call(Attribute::parse_inner)?;
1846 let stmts = content.call(Block::parse_within)?;
1847
1848 Ok(ExprLoop {
1849 attrs: inner_attrs,
1850 label: label,
1851 loop_token: loop_token,
1852 body: Block {
1853 brace_token: brace_token,
1854 stmts: stmts,
1855 },
1856 })
1857 }
1858 }
1859
1860 #[cfg(feature = "full")]
1861 impl Parse for ExprMatch {
parse(input: ParseStream) -> Result<Self>1862 fn parse(input: ParseStream) -> Result<Self> {
1863 let match_token: Token![match] = input.parse()?;
1864 let expr = expr_no_struct(input)?;
1865
1866 let content;
1867 let brace_token = braced!(content in input);
1868 let inner_attrs = content.call(Attribute::parse_inner)?;
1869
1870 let mut arms = Vec::new();
1871 while !content.is_empty() {
1872 arms.push(content.call(Arm::parse)?);
1873 }
1874
1875 Ok(ExprMatch {
1876 attrs: inner_attrs,
1877 match_token: match_token,
1878 expr: Box::new(expr),
1879 brace_token: brace_token,
1880 arms: arms,
1881 })
1882 }
1883 }
1884
1885 #[cfg(all(feature = "full", feature = "printing"))]
1886 impl Parse for ExprInPlace {
parse(input: ParseStream) -> Result<Self>1887 fn parse(input: ParseStream) -> Result<Self> {
1888 let msg = "placement expression has been removed from Rust and is no longer parsed";
1889 Err(input.error(msg))
1890 }
1891 }
1892
1893 macro_rules! impl_by_parsing_expr {
1894 (
1895 $(
1896 $expr_type:ty, $variant:ident, $msg:expr,
1897 )*
1898 ) => {
1899 $(
1900 #[cfg(all(feature = "full", feature = "printing"))]
1901 impl Parse for $expr_type {
1902 fn parse(input: ParseStream) -> Result<Self> {
1903 let mut expr: Expr = input.parse()?;
1904 loop {
1905 match expr {
1906 Expr::$variant(inner) => return Ok(inner),
1907 Expr::Group(next) => expr = *next.expr,
1908 _ => return Err(Error::new_spanned(expr, $msg)),
1909 }
1910 }
1911 }
1912 }
1913 )*
1914 };
1915 }
1916
1917 impl_by_parsing_expr! {
1918 ExprBox, Box, "expected box expression",
1919 ExprArray, Array, "expected slice literal expression",
1920 ExprCall, Call, "expected function call expression",
1921 ExprMethodCall, MethodCall, "expected method call expression",
1922 ExprTuple, Tuple, "expected tuple expression",
1923 ExprBinary, Binary, "expected binary operation",
1924 ExprUnary, Unary, "expected unary operation",
1925 ExprCast, Cast, "expected cast expression",
1926 ExprType, Type, "expected type ascription expression",
1927 ExprLet, Let, "expected let guard",
1928 ExprClosure, Closure, "expected closure expression",
1929 ExprUnsafe, Unsafe, "expected unsafe block",
1930 ExprBlock, Block, "expected blocked scope",
1931 ExprAssign, Assign, "expected assignment expression",
1932 ExprAssignOp, AssignOp, "expected compound assignment expression",
1933 ExprField, Field, "expected struct field access",
1934 ExprIndex, Index, "expected indexing expression",
1935 ExprRange, Range, "expected range expression",
1936 ExprReference, Reference, "expected referencing operation",
1937 ExprBreak, Break, "expected break expression",
1938 ExprContinue, Continue, "expected continue expression",
1939 ExprReturn, Return, "expected return expression",
1940 ExprMacro, Macro, "expected macro invocation expression",
1941 ExprStruct, Struct, "expected struct literal expression",
1942 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
1943 ExprParen, Paren, "expected parenthesized expression",
1944 ExprTry, Try, "expected try expression",
1945 ExprAsync, Async, "expected async block",
1946 ExprTryBlock, TryBlock, "expected try block",
1947 ExprYield, Yield, "expected yield expression",
1948 }
1949
1950 #[cfg(feature = "full")]
expr_try_block(input: ParseStream) -> Result<ExprTryBlock>1951 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1952 Ok(ExprTryBlock {
1953 attrs: Vec::new(),
1954 try_token: input.parse()?,
1955 block: input.parse()?,
1956 })
1957 }
1958
1959 #[cfg(feature = "full")]
expr_yield(input: ParseStream) -> Result<ExprYield>1960 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1961 Ok(ExprYield {
1962 attrs: Vec::new(),
1963 yield_token: input.parse()?,
1964 expr: {
1965 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1966 Some(input.parse()?)
1967 } else {
1968 None
1969 }
1970 },
1971 })
1972 }
1973
1974 #[cfg(feature = "full")]
expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure>1975 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
1976 let asyncness: Option<Token![async]> = input.parse()?;
1977 let movability: Option<Token![static]> = if asyncness.is_none() {
1978 input.parse()?
1979 } else {
1980 None
1981 };
1982 let capture: Option<Token![move]> = input.parse()?;
1983 let or1_token: Token![|] = input.parse()?;
1984
1985 let mut inputs = Punctuated::new();
1986 loop {
1987 if input.peek(Token![|]) {
1988 break;
1989 }
1990 let value = fn_arg(input)?;
1991 inputs.push_value(value);
1992 if input.peek(Token![|]) {
1993 break;
1994 }
1995 let punct: Token![,] = input.parse()?;
1996 inputs.push_punct(punct);
1997 }
1998
1999 let or2_token: Token![|] = input.parse()?;
2000
2001 let (output, body) = if input.peek(Token![->]) {
2002 let arrow_token: Token![->] = input.parse()?;
2003 let ty: Type = input.parse()?;
2004 let body: Block = input.parse()?;
2005 let output = ReturnType::Type(arrow_token, Box::new(ty));
2006 let block = Expr::Block(ExprBlock {
2007 attrs: Vec::new(),
2008 label: None,
2009 block: body,
2010 });
2011 (output, block)
2012 } else {
2013 let body = ambiguous_expr(input, allow_struct)?;
2014 (ReturnType::Default, body)
2015 };
2016
2017 Ok(ExprClosure {
2018 attrs: Vec::new(),
2019 asyncness: asyncness,
2020 movability: movability,
2021 capture: capture,
2022 or1_token: or1_token,
2023 inputs: inputs,
2024 or2_token: or2_token,
2025 output: output,
2026 body: Box::new(body),
2027 })
2028 }
2029
2030 #[cfg(feature = "full")]
expr_async(input: ParseStream) -> Result<ExprAsync>2031 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2032 Ok(ExprAsync {
2033 attrs: Vec::new(),
2034 async_token: input.parse()?,
2035 capture: input.parse()?,
2036 block: input.parse()?,
2037 })
2038 }
2039
2040 #[cfg(feature = "full")]
fn_arg(input: ParseStream) -> Result<FnArg>2041 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2042 let pat: Pat = input.parse()?;
2043
2044 if input.peek(Token![:]) {
2045 Ok(FnArg::Captured(ArgCaptured {
2046 pat: pat,
2047 colon_token: input.parse()?,
2048 ty: input.parse()?,
2049 }))
2050 } else {
2051 Ok(FnArg::Inferred(pat))
2052 }
2053 }
2054
2055 #[cfg(feature = "full")]
2056 impl Parse for ExprWhile {
parse(input: ParseStream) -> Result<Self>2057 fn parse(input: ParseStream) -> Result<Self> {
2058 let label: Option<Label> = input.parse()?;
2059 let while_token: Token![while] = input.parse()?;
2060 let cond = expr_no_struct(input)?;
2061
2062 let content;
2063 let brace_token = braced!(content in input);
2064 let inner_attrs = content.call(Attribute::parse_inner)?;
2065 let stmts = content.call(Block::parse_within)?;
2066
2067 Ok(ExprWhile {
2068 attrs: inner_attrs,
2069 label: label,
2070 while_token: while_token,
2071 cond: Box::new(cond),
2072 body: Block {
2073 brace_token: brace_token,
2074 stmts: stmts,
2075 },
2076 })
2077 }
2078 }
2079
2080 #[cfg(feature = "full")]
2081 impl Parse for Label {
parse(input: ParseStream) -> Result<Self>2082 fn parse(input: ParseStream) -> Result<Self> {
2083 Ok(Label {
2084 name: input.parse()?,
2085 colon_token: input.parse()?,
2086 })
2087 }
2088 }
2089
2090 #[cfg(feature = "full")]
2091 impl Parse for Option<Label> {
parse(input: ParseStream) -> Result<Self>2092 fn parse(input: ParseStream) -> Result<Self> {
2093 if input.peek(Lifetime) {
2094 input.parse().map(Some)
2095 } else {
2096 Ok(None)
2097 }
2098 }
2099 }
2100
2101 #[cfg(feature = "full")]
expr_continue(input: ParseStream) -> Result<ExprContinue>2102 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2103 Ok(ExprContinue {
2104 attrs: Vec::new(),
2105 continue_token: input.parse()?,
2106 label: input.parse()?,
2107 })
2108 }
2109
2110 #[cfg(feature = "full")]
expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak>2111 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2112 Ok(ExprBreak {
2113 attrs: Vec::new(),
2114 break_token: input.parse()?,
2115 label: input.parse()?,
2116 expr: {
2117 if input.is_empty()
2118 || input.peek(Token![,])
2119 || input.peek(Token![;])
2120 || !allow_struct.0 && input.peek(token::Brace)
2121 {
2122 None
2123 } else {
2124 let expr = ambiguous_expr(input, allow_struct)?;
2125 Some(Box::new(expr))
2126 }
2127 },
2128 })
2129 }
2130
2131 #[cfg(feature = "full")]
expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn>2132 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2133 Ok(ExprReturn {
2134 attrs: Vec::new(),
2135 return_token: input.parse()?,
2136 expr: {
2137 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2138 None
2139 } else {
2140 // NOTE: return is greedy and eats blocks after it even when in a
2141 // position where structs are not allowed, such as in if statement
2142 // conditions. For example:
2143 //
2144 // if return { println!("A") } {} // Prints "A"
2145 let expr = ambiguous_expr(input, allow_struct)?;
2146 Some(Box::new(expr))
2147 }
2148 },
2149 })
2150 }
2151
2152 #[cfg(feature = "full")]
2153 impl Parse for FieldValue {
parse(input: ParseStream) -> Result<Self>2154 fn parse(input: ParseStream) -> Result<Self> {
2155 let member: Member = input.parse()?;
2156 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2157 let colon_token: Token![:] = input.parse()?;
2158 let value: Expr = input.parse()?;
2159 (Some(colon_token), value)
2160 } else if let Member::Named(ref ident) = member {
2161 let value = Expr::Path(ExprPath {
2162 attrs: Vec::new(),
2163 qself: None,
2164 path: Path::from(ident.clone()),
2165 });
2166 (None, value)
2167 } else {
2168 unreachable!()
2169 };
2170
2171 Ok(FieldValue {
2172 attrs: Vec::new(),
2173 member: member,
2174 colon_token: colon_token,
2175 expr: value,
2176 })
2177 }
2178 }
2179
2180 #[cfg(feature = "full")]
expr_struct_helper( input: ParseStream, outer_attrs: Vec<Attribute>, path: Path, ) -> Result<ExprStruct>2181 fn expr_struct_helper(
2182 input: ParseStream,
2183 outer_attrs: Vec<Attribute>,
2184 path: Path,
2185 ) -> Result<ExprStruct> {
2186 let content;
2187 let brace_token = braced!(content in input);
2188 let inner_attrs = content.call(Attribute::parse_inner)?;
2189
2190 let mut fields = Punctuated::new();
2191 loop {
2192 let attrs = content.call(Attribute::parse_outer)?;
2193 // TODO: optimize using advance_to
2194 if content.fork().parse::<Member>().is_err() {
2195 if attrs.is_empty() {
2196 break;
2197 } else {
2198 return Err(content.error("expected struct field"));
2199 }
2200 }
2201
2202 fields.push(FieldValue {
2203 attrs: attrs,
2204 ..content.parse()?
2205 });
2206
2207 if !content.peek(Token![,]) {
2208 break;
2209 }
2210 let punct: Token![,] = content.parse()?;
2211 fields.push_punct(punct);
2212 }
2213
2214 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2215 let dot2_token: Token![..] = content.parse()?;
2216 let rest: Expr = content.parse()?;
2217 (Some(dot2_token), Some(Box::new(rest)))
2218 } else {
2219 (None, None)
2220 };
2221
2222 Ok(ExprStruct {
2223 attrs: private::attrs(outer_attrs, inner_attrs),
2224 brace_token: brace_token,
2225 path: path,
2226 fields: fields,
2227 dot2_token: dot2_token,
2228 rest: rest,
2229 })
2230 }
2231
2232 #[cfg(feature = "full")]
expr_unsafe(input: ParseStream) -> Result<ExprUnsafe>2233 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2234 let unsafe_token: Token![unsafe] = input.parse()?;
2235
2236 let content;
2237 let brace_token = braced!(content in input);
2238 let inner_attrs = content.call(Attribute::parse_inner)?;
2239 let stmts = content.call(Block::parse_within)?;
2240
2241 Ok(ExprUnsafe {
2242 attrs: inner_attrs,
2243 unsafe_token: unsafe_token,
2244 block: Block {
2245 brace_token: brace_token,
2246 stmts: stmts,
2247 },
2248 })
2249 }
2250
2251 #[cfg(feature = "full")]
expr_block(input: ParseStream) -> Result<ExprBlock>2252 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2253 let label: Option<Label> = input.parse()?;
2254
2255 let content;
2256 let brace_token = braced!(content in input);
2257 let inner_attrs = content.call(Attribute::parse_inner)?;
2258 let stmts = content.call(Block::parse_within)?;
2259
2260 Ok(ExprBlock {
2261 attrs: inner_attrs,
2262 label: label,
2263 block: Block {
2264 brace_token: brace_token,
2265 stmts: stmts,
2266 },
2267 })
2268 }
2269
2270 #[cfg(feature = "full")]
expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange>2271 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2272 Ok(ExprRange {
2273 attrs: Vec::new(),
2274 from: None,
2275 limits: input.parse()?,
2276 to: {
2277 if input.is_empty()
2278 || input.peek(Token![,])
2279 || input.peek(Token![;])
2280 || !allow_struct.0 && input.peek(token::Brace)
2281 {
2282 None
2283 } else {
2284 let to = ambiguous_expr(input, allow_struct)?;
2285 Some(Box::new(to))
2286 }
2287 },
2288 })
2289 }
2290
2291 #[cfg(feature = "full")]
2292 impl Parse for RangeLimits {
parse(input: ParseStream) -> Result<Self>2293 fn parse(input: ParseStream) -> Result<Self> {
2294 let lookahead = input.lookahead1();
2295 if lookahead.peek(Token![..=]) {
2296 input.parse().map(RangeLimits::Closed)
2297 } else if lookahead.peek(Token![...]) {
2298 let dot3: Token![...] = input.parse()?;
2299 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2300 } else if lookahead.peek(Token![..]) {
2301 input.parse().map(RangeLimits::HalfOpen)
2302 } else {
2303 Err(lookahead.error())
2304 }
2305 }
2306 }
2307
2308 impl Parse for ExprPath {
parse(input: ParseStream) -> Result<Self>2309 fn parse(input: ParseStream) -> Result<Self> {
2310 #[cfg(not(feature = "full"))]
2311 let attrs = Vec::new();
2312 #[cfg(feature = "full")]
2313 let attrs = input.call(Attribute::parse_outer)?;
2314
2315 let (qself, path) = path::parsing::qpath(input, true)?;
2316
2317 Ok(ExprPath {
2318 attrs: attrs,
2319 qself: qself,
2320 path: path,
2321 })
2322 }
2323 }
2324
2325 #[cfg(feature = "full")]
2326 impl Parse for Block {
parse(input: ParseStream) -> Result<Self>2327 fn parse(input: ParseStream) -> Result<Self> {
2328 let content;
2329 Ok(Block {
2330 brace_token: braced!(content in input),
2331 stmts: content.call(Block::parse_within)?,
2332 })
2333 }
2334 }
2335
2336 #[cfg(feature = "full")]
2337 impl Block {
2338 /// Parse the body of a block as zero or more statements, possibly
2339 /// including one trailing expression.
2340 ///
2341 /// *This function is available if Syn is built with the `"parsing"`
2342 /// feature.*
2343 ///
2344 /// # Example
2345 ///
2346 /// ```edition2018
2347 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
2348 /// use syn::parse::{Parse, ParseStream};
2349 ///
2350 /// // Parse a function with no generics or parameter list.
2351 /// //
2352 /// // fn playground {
2353 /// // let mut x = 1;
2354 /// // x += 1;
2355 /// // println!("{}", x);
2356 /// // }
2357 /// struct MiniFunction {
2358 /// attrs: Vec<Attribute>,
2359 /// fn_token: Token![fn],
2360 /// name: Ident,
2361 /// brace_token: token::Brace,
2362 /// stmts: Vec<Stmt>,
2363 /// }
2364 ///
2365 /// impl Parse for MiniFunction {
2366 /// fn parse(input: ParseStream) -> Result<Self> {
2367 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2368 /// let fn_token: Token![fn] = input.parse()?;
2369 /// let name: Ident = input.parse()?;
2370 ///
2371 /// let content;
2372 /// let brace_token = braced!(content in input);
2373 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2374 /// let stmts = content.call(Block::parse_within)?;
2375 ///
2376 /// Ok(MiniFunction {
2377 /// attrs: {
2378 /// let mut attrs = outer_attrs;
2379 /// attrs.extend(inner_attrs);
2380 /// attrs
2381 /// },
2382 /// fn_token: fn_token,
2383 /// name: name,
2384 /// brace_token: brace_token,
2385 /// stmts: stmts,
2386 /// })
2387 /// }
2388 /// }
2389 /// ```
parse_within(input: ParseStream) -> Result<Vec<Stmt>>2390 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
2391 let mut stmts = Vec::new();
2392 loop {
2393 while input.peek(Token![;]) {
2394 input.parse::<Token![;]>()?;
2395 }
2396 if input.is_empty() {
2397 break;
2398 }
2399 let s = parse_stmt(input, true)?;
2400 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2401 requires_terminator(s)
2402 } else {
2403 false
2404 };
2405 stmts.push(s);
2406 if input.is_empty() {
2407 break;
2408 } else if requires_semicolon {
2409 return Err(input.error("unexpected token"));
2410 }
2411 }
2412 Ok(stmts)
2413 }
2414 }
2415
2416 #[cfg(feature = "full")]
2417 impl Parse for Stmt {
parse(input: ParseStream) -> Result<Self>2418 fn parse(input: ParseStream) -> Result<Self> {
2419 parse_stmt(input, false)
2420 }
2421 }
2422
2423 #[cfg(feature = "full")]
parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt>2424 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2425 // TODO: optimize using advance_to
2426 let ahead = input.fork();
2427 ahead.call(Attribute::parse_outer)?;
2428
2429 if {
2430 let ahead = ahead.fork();
2431 // Only parse braces here; paren and bracket will get parsed as
2432 // expression statements
2433 ahead.call(Path::parse_mod_style).is_ok()
2434 && ahead.parse::<Token![!]>().is_ok()
2435 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2436 } {
2437 stmt_mac(input)
2438 } else if ahead.peek(Token![let]) {
2439 stmt_local(input).map(Stmt::Local)
2440 } else if ahead.peek(Token![pub])
2441 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2442 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2443 || ahead.peek(Token![use])
2444 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2445 || ahead.peek(Token![const])
2446 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2447 || ahead.peek(Token![async])
2448 && (ahead.peek2(Token![unsafe])
2449 || ahead.peek2(Token![extern])
2450 || ahead.peek2(Token![fn]))
2451 || ahead.peek(Token![fn])
2452 || ahead.peek(Token![mod])
2453 || ahead.peek(Token![type])
2454 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2455 || ahead.peek(Token![struct])
2456 || ahead.peek(Token![enum])
2457 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2458 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2459 || ahead.peek(Token![trait])
2460 || ahead.peek(Token![default])
2461 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2462 || ahead.peek(Token![impl])
2463 || ahead.peek(Token![macro])
2464 {
2465 input.parse().map(Stmt::Item)
2466 } else {
2467 stmt_expr(input, allow_nosemi)
2468 }
2469 }
2470
2471 #[cfg(feature = "full")]
stmt_mac(input: ParseStream) -> Result<Stmt>2472 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2473 let attrs = input.call(Attribute::parse_outer)?;
2474 let path = input.call(Path::parse_mod_style)?;
2475 let bang_token: Token![!] = input.parse()?;
2476 let ident: Option<Ident> = input.parse()?;
2477 let (delimiter, tts) = mac::parse_delimiter(input)?;
2478 let semi_token: Option<Token![;]> = input.parse()?;
2479
2480 Ok(Stmt::Item(Item::Macro(ItemMacro {
2481 attrs: attrs,
2482 ident: ident,
2483 mac: Macro {
2484 path: path,
2485 bang_token: bang_token,
2486 delimiter: delimiter,
2487 tts: tts,
2488 },
2489 semi_token: semi_token,
2490 })))
2491 }
2492
2493 #[cfg(feature = "full")]
stmt_local(input: ParseStream) -> Result<Local>2494 fn stmt_local(input: ParseStream) -> Result<Local> {
2495 Ok(Local {
2496 attrs: input.call(Attribute::parse_outer)?,
2497 let_token: input.parse()?,
2498 pats: {
2499 let mut pats = Punctuated::new();
2500 let value: Pat = input.parse()?;
2501 pats.push_value(value);
2502 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2503 let punct = input.parse()?;
2504 pats.push_punct(punct);
2505 let value: Pat = input.parse()?;
2506 pats.push_value(value);
2507 }
2508 pats
2509 },
2510 ty: {
2511 if input.peek(Token![:]) {
2512 let colon_token: Token![:] = input.parse()?;
2513 let ty: Type = input.parse()?;
2514 Some((colon_token, Box::new(ty)))
2515 } else {
2516 None
2517 }
2518 },
2519 init: {
2520 if input.peek(Token![=]) {
2521 let eq_token: Token![=] = input.parse()?;
2522 let init: Expr = input.parse()?;
2523 Some((eq_token, Box::new(init)))
2524 } else {
2525 None
2526 }
2527 },
2528 semi_token: input.parse()?,
2529 })
2530 }
2531
2532 #[cfg(feature = "full")]
stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt>2533 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2534 let mut attrs = input.call(Attribute::parse_outer)?;
2535 let mut e = expr_early(input)?;
2536
2537 attrs.extend(e.replace_attrs(Vec::new()));
2538 e.replace_attrs(attrs);
2539
2540 if input.peek(Token![;]) {
2541 return Ok(Stmt::Semi(e, input.parse()?));
2542 }
2543
2544 if allow_nosemi || !requires_terminator(&e) {
2545 Ok(Stmt::Expr(e))
2546 } else {
2547 Err(input.error("expected semicolon"))
2548 }
2549 }
2550
2551 #[cfg(feature = "full")]
2552 impl Parse for Pat {
parse(input: ParseStream) -> Result<Self>2553 fn parse(input: ParseStream) -> Result<Self> {
2554 let lookahead = input.lookahead1();
2555 if lookahead.peek(Token![_]) {
2556 input.call(pat_wild).map(Pat::Wild)
2557 } else if lookahead.peek(Token![box]) {
2558 input.call(pat_box).map(Pat::Box)
2559 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2560 pat_lit_or_range(input)
2561 } else if input.peek(Ident)
2562 && ({
2563 input.peek2(Token![::])
2564 || input.peek2(Token![!])
2565 || input.peek2(token::Brace)
2566 || input.peek2(token::Paren)
2567 || input.peek2(Token![..])
2568 && !{
2569 let ahead = input.fork();
2570 ahead.parse::<Ident>()?;
2571 ahead.parse::<RangeLimits>()?;
2572 ahead.is_empty() || ahead.peek(Token![,])
2573 }
2574 })
2575 || input.peek(Token![self]) && input.peek2(Token![::])
2576 || input.peek(Token![::])
2577 || input.peek(Token![<])
2578 || input.peek(Token![Self])
2579 || input.peek(Token![super])
2580 || input.peek(Token![extern])
2581 || input.peek(Token![crate])
2582 {
2583 pat_path_or_macro_or_struct_or_range(input)
2584 } else if input.peek(Token![ref])
2585 || input.peek(Token![mut])
2586 || input.peek(Token![self])
2587 || input.peek(Ident)
2588 {
2589 input.call(pat_ident).map(Pat::Ident)
2590 } else if lookahead.peek(token::Paren) {
2591 input.call(pat_tuple).map(Pat::Tuple)
2592 } else if lookahead.peek(Token![&]) {
2593 input.call(pat_ref).map(Pat::Ref)
2594 } else if lookahead.peek(token::Bracket) {
2595 input.call(pat_slice).map(Pat::Slice)
2596 } else {
2597 Err(lookahead.error())
2598 }
2599 }
2600 }
2601
2602 #[cfg(feature = "full")]
pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat>2603 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2604 let (qself, path) = path::parsing::qpath(input, true)?;
2605
2606 if input.peek(Token![..]) {
2607 return pat_range(input, qself, path).map(Pat::Range);
2608 }
2609
2610 if qself.is_some() {
2611 return Ok(Pat::Path(PatPath {
2612 qself: qself,
2613 path: path,
2614 }));
2615 }
2616
2617 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2618 let mut contains_arguments = false;
2619 for segment in &path.segments {
2620 match segment.arguments {
2621 PathArguments::None => {}
2622 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2623 contains_arguments = true;
2624 }
2625 }
2626 }
2627
2628 if !contains_arguments {
2629 let bang_token: Token![!] = input.parse()?;
2630 let (delimiter, tts) = mac::parse_delimiter(input)?;
2631 return Ok(Pat::Macro(PatMacro {
2632 mac: Macro {
2633 path: path,
2634 bang_token: bang_token,
2635 delimiter: delimiter,
2636 tts: tts,
2637 },
2638 }));
2639 }
2640 }
2641
2642 if input.peek(token::Brace) {
2643 pat_struct(input, path).map(Pat::Struct)
2644 } else if input.peek(token::Paren) {
2645 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2646 } else if input.peek(Token![..]) {
2647 pat_range(input, qself, path).map(Pat::Range)
2648 } else {
2649 Ok(Pat::Path(PatPath {
2650 qself: qself,
2651 path: path,
2652 }))
2653 }
2654 }
2655
2656 #[cfg(feature = "full")]
pat_wild(input: ParseStream) -> Result<PatWild>2657 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2658 Ok(PatWild {
2659 underscore_token: input.parse()?,
2660 })
2661 }
2662
2663 #[cfg(feature = "full")]
pat_box(input: ParseStream) -> Result<PatBox>2664 fn pat_box(input: ParseStream) -> Result<PatBox> {
2665 Ok(PatBox {
2666 box_token: input.parse()?,
2667 pat: input.parse()?,
2668 })
2669 }
2670
2671 #[cfg(feature = "full")]
pat_ident(input: ParseStream) -> Result<PatIdent>2672 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2673 Ok(PatIdent {
2674 by_ref: input.parse()?,
2675 mutability: input.parse()?,
2676 ident: input.call(Ident::parse_any)?,
2677 subpat: {
2678 if input.peek(Token![@]) {
2679 let at_token: Token![@] = input.parse()?;
2680 let subpat: Pat = input.parse()?;
2681 Some((at_token, Box::new(subpat)))
2682 } else {
2683 None
2684 }
2685 },
2686 })
2687 }
2688
2689 #[cfg(feature = "full")]
pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct>2690 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
2691 Ok(PatTupleStruct {
2692 path: path,
2693 pat: input.call(pat_tuple)?,
2694 })
2695 }
2696
2697 #[cfg(feature = "full")]
pat_struct(input: ParseStream, path: Path) -> Result<PatStruct>2698 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
2699 let content;
2700 let brace_token = braced!(content in input);
2701
2702 let mut fields = Punctuated::new();
2703 while !content.is_empty() && !content.peek(Token![..]) {
2704 let value = content.call(field_pat)?;
2705 fields.push_value(value);
2706 if !content.peek(Token![,]) {
2707 break;
2708 }
2709 let punct: Token![,] = content.parse()?;
2710 fields.push_punct(punct);
2711 }
2712
2713 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2714 Some(content.parse()?)
2715 } else {
2716 None
2717 };
2718
2719 Ok(PatStruct {
2720 path: path,
2721 brace_token: brace_token,
2722 fields: fields,
2723 dot2_token: dot2_token,
2724 })
2725 }
2726
2727 #[cfg(feature = "full")]
field_pat(input: ParseStream) -> Result<FieldPat>2728 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2729 let boxed: Option<Token![box]> = input.parse()?;
2730 let by_ref: Option<Token![ref]> = input.parse()?;
2731 let mutability: Option<Token![mut]> = input.parse()?;
2732 let member: Member = input.parse()?;
2733
2734 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2735 || member.is_unnamed()
2736 {
2737 return Ok(FieldPat {
2738 attrs: Vec::new(),
2739 member: member,
2740 colon_token: input.parse()?,
2741 pat: input.parse()?,
2742 });
2743 }
2744
2745 let ident = match member {
2746 Member::Named(ident) => ident,
2747 Member::Unnamed(_) => unreachable!(),
2748 };
2749
2750 let mut pat = Pat::Ident(PatIdent {
2751 by_ref: by_ref,
2752 mutability: mutability,
2753 ident: ident.clone(),
2754 subpat: None,
2755 });
2756
2757 if let Some(boxed) = boxed {
2758 pat = Pat::Box(PatBox {
2759 pat: Box::new(pat),
2760 box_token: boxed,
2761 });
2762 }
2763
2764 Ok(FieldPat {
2765 member: Member::Named(ident),
2766 pat: Box::new(pat),
2767 attrs: Vec::new(),
2768 colon_token: None,
2769 })
2770 }
2771
2772 impl Parse for Member {
parse(input: ParseStream) -> Result<Self>2773 fn parse(input: ParseStream) -> Result<Self> {
2774 if input.peek(Ident) {
2775 input.parse().map(Member::Named)
2776 } else if input.peek(LitInt) {
2777 input.parse().map(Member::Unnamed)
2778 } else {
2779 Err(input.error("expected identifier or integer"))
2780 }
2781 }
2782 }
2783
2784 #[cfg(feature = "full")]
2785 impl Parse for Arm {
parse(input: ParseStream) -> Result<Arm>2786 fn parse(input: ParseStream) -> Result<Arm> {
2787 let requires_comma;
2788 Ok(Arm {
2789 attrs: input.call(Attribute::parse_outer)?,
2790 leading_vert: input.parse()?,
2791 pats: {
2792 let mut pats = Punctuated::new();
2793 let value: Pat = input.parse()?;
2794 pats.push_value(value);
2795 loop {
2796 if !input.peek(Token![|]) {
2797 break;
2798 }
2799 let punct = input.parse()?;
2800 pats.push_punct(punct);
2801 let value: Pat = input.parse()?;
2802 pats.push_value(value);
2803 }
2804 pats
2805 },
2806 guard: {
2807 if input.peek(Token![if]) {
2808 let if_token: Token![if] = input.parse()?;
2809 let guard: Expr = input.parse()?;
2810 Some((if_token, Box::new(guard)))
2811 } else {
2812 None
2813 }
2814 },
2815 fat_arrow_token: input.parse()?,
2816 body: {
2817 let body = input.call(expr_early)?;
2818 requires_comma = requires_terminator(&body);
2819 Box::new(body)
2820 },
2821 comma: {
2822 if requires_comma && !input.is_empty() {
2823 Some(input.parse()?)
2824 } else {
2825 input.parse()?
2826 }
2827 },
2828 })
2829 }
2830 }
2831
2832 impl Parse for Index {
parse(input: ParseStream) -> Result<Self>2833 fn parse(input: ParseStream) -> Result<Self> {
2834 let lit: LitInt = input.parse()?;
2835 if let IntSuffix::None = lit.suffix() {
2836 Ok(Index {
2837 index: lit.value() as u32,
2838 span: lit.span(),
2839 })
2840 } else {
2841 Err(Error::new(lit.span(), "expected unsuffixed integer"))
2842 }
2843 }
2844 }
2845
2846 #[cfg(feature = "full")]
pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange>2847 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2848 Ok(PatRange {
2849 lo: Box::new(Expr::Path(ExprPath {
2850 attrs: Vec::new(),
2851 qself: qself,
2852 path: path,
2853 })),
2854 limits: input.parse()?,
2855 hi: input.call(pat_lit_expr)?,
2856 })
2857 }
2858
2859 #[cfg(feature = "full")]
pat_tuple(input: ParseStream) -> Result<PatTuple>2860 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2861 let content;
2862 let paren_token = parenthesized!(content in input);
2863
2864 let mut front = Punctuated::new();
2865 let mut dot2_token = None::<Token![..]>;
2866 let mut comma_token = None::<Token![,]>;
2867 loop {
2868 if content.is_empty() {
2869 break;
2870 }
2871 if content.peek(Token![..]) {
2872 dot2_token = Some(content.parse()?);
2873 comma_token = content.parse()?;
2874 break;
2875 }
2876 let value: Pat = content.parse()?;
2877 front.push_value(value);
2878 if content.is_empty() {
2879 break;
2880 }
2881 let punct = content.parse()?;
2882 front.push_punct(punct);
2883 }
2884
2885 let mut back = Punctuated::new();
2886 while !content.is_empty() {
2887 let value: Pat = content.parse()?;
2888 back.push_value(value);
2889 if content.is_empty() {
2890 break;
2891 }
2892 let punct = content.parse()?;
2893 back.push_punct(punct);
2894 }
2895
2896 Ok(PatTuple {
2897 paren_token: paren_token,
2898 front: front,
2899 dot2_token: dot2_token,
2900 comma_token: comma_token,
2901 back: back,
2902 })
2903 }
2904
2905 #[cfg(feature = "full")]
pat_ref(input: ParseStream) -> Result<PatRef>2906 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2907 Ok(PatRef {
2908 and_token: input.parse()?,
2909 mutability: input.parse()?,
2910 pat: input.parse()?,
2911 })
2912 }
2913
2914 #[cfg(feature = "full")]
pat_lit_or_range(input: ParseStream) -> Result<Pat>2915 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2916 let lo = input.call(pat_lit_expr)?;
2917 if input.peek(Token![..]) {
2918 Ok(Pat::Range(PatRange {
2919 lo: lo,
2920 limits: input.parse()?,
2921 hi: input.call(pat_lit_expr)?,
2922 }))
2923 } else {
2924 Ok(Pat::Lit(PatLit { expr: lo }))
2925 }
2926 }
2927
2928 #[cfg(feature = "full")]
pat_lit_expr(input: ParseStream) -> Result<Box<Expr>>2929 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2930 let neg: Option<Token![-]> = input.parse()?;
2931
2932 let lookahead = input.lookahead1();
2933 let expr = if lookahead.peek(Lit) {
2934 Expr::Lit(input.parse()?)
2935 } else if lookahead.peek(Ident)
2936 || lookahead.peek(Token![::])
2937 || lookahead.peek(Token![<])
2938 || lookahead.peek(Token![self])
2939 || lookahead.peek(Token![Self])
2940 || lookahead.peek(Token![super])
2941 || lookahead.peek(Token![extern])
2942 || lookahead.peek(Token![crate])
2943 {
2944 Expr::Path(input.parse()?)
2945 } else {
2946 return Err(lookahead.error());
2947 };
2948
2949 Ok(Box::new(if let Some(neg) = neg {
2950 Expr::Unary(ExprUnary {
2951 attrs: Vec::new(),
2952 op: UnOp::Neg(neg),
2953 expr: Box::new(expr),
2954 })
2955 } else {
2956 expr
2957 }))
2958 }
2959
2960 #[cfg(feature = "full")]
pat_slice(input: ParseStream) -> Result<PatSlice>2961 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2962 let content;
2963 let bracket_token = bracketed!(content in input);
2964
2965 let mut front = Punctuated::new();
2966 let mut middle = None;
2967 loop {
2968 if content.is_empty() || content.peek(Token![..]) {
2969 break;
2970 }
2971 let value: Pat = content.parse()?;
2972 if content.peek(Token![..]) {
2973 middle = Some(Box::new(value));
2974 break;
2975 }
2976 front.push_value(value);
2977 if content.is_empty() {
2978 break;
2979 }
2980 let punct = content.parse()?;
2981 front.push_punct(punct);
2982 }
2983
2984 let dot2_token: Option<Token![..]> = content.parse()?;
2985 let mut comma_token = None::<Token![,]>;
2986 let mut back = Punctuated::new();
2987 if dot2_token.is_some() {
2988 comma_token = content.parse()?;
2989 if comma_token.is_some() {
2990 loop {
2991 if content.is_empty() {
2992 break;
2993 }
2994 let value: Pat = content.parse()?;
2995 back.push_value(value);
2996 if content.is_empty() {
2997 break;
2998 }
2999 let punct = content.parse()?;
3000 back.push_punct(punct);
3001 }
3002 }
3003 }
3004
3005 Ok(PatSlice {
3006 bracket_token: bracket_token,
3007 front: front,
3008 middle: middle,
3009 dot2_token: dot2_token,
3010 comma_token: comma_token,
3011 back: back,
3012 })
3013 }
3014
3015 #[cfg(feature = "full")]
3016 impl Member {
is_named(&self) -> bool3017 fn is_named(&self) -> bool {
3018 match *self {
3019 Member::Named(_) => true,
3020 Member::Unnamed(_) => false,
3021 }
3022 }
3023
is_unnamed(&self) -> bool3024 fn is_unnamed(&self) -> bool {
3025 match *self {
3026 Member::Named(_) => false,
3027 Member::Unnamed(_) => true,
3028 }
3029 }
3030 }
3031 }
3032
3033 #[cfg(feature = "printing")]
3034 mod printing {
3035 use super::*;
3036
3037 use proc_macro2::{Literal, TokenStream};
3038 use quote::{ToTokens, TokenStreamExt};
3039
3040 #[cfg(feature = "full")]
3041 use attr::FilterAttrs;
3042 #[cfg(feature = "full")]
3043 use print::TokensOrDefault;
3044
3045 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
3046 // before appending it to `TokenStream`.
3047 #[cfg(feature = "full")]
wrap_bare_struct(tokens: &mut TokenStream, e: &Expr)3048 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
3049 if let Expr::Struct(_) = *e {
3050 token::Paren::default().surround(tokens, |tokens| {
3051 e.to_tokens(tokens);
3052 });
3053 } else {
3054 e.to_tokens(tokens);
3055 }
3056 }
3057
3058 #[cfg(feature = "full")]
outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)3059 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3060 tokens.append_all(attrs.outer());
3061 }
3062
3063 #[cfg(feature = "full")]
inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)3064 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3065 tokens.append_all(attrs.inner());
3066 }
3067
3068 #[cfg(not(feature = "full"))]
outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)3069 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3070
3071 #[cfg(not(feature = "full"))]
inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)3072 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3073
3074 #[cfg(feature = "full")]
3075 impl ToTokens for ExprBox {
to_tokens(&self, tokens: &mut TokenStream)3076 fn to_tokens(&self, tokens: &mut TokenStream) {
3077 outer_attrs_to_tokens(&self.attrs, tokens);
3078 self.box_token.to_tokens(tokens);
3079 self.expr.to_tokens(tokens);
3080 }
3081 }
3082
3083 #[cfg(feature = "full")]
3084 impl ToTokens for ExprInPlace {
to_tokens(&self, tokens: &mut TokenStream)3085 fn to_tokens(&self, tokens: &mut TokenStream) {
3086 outer_attrs_to_tokens(&self.attrs, tokens);
3087 self.place.to_tokens(tokens);
3088 self.arrow_token.to_tokens(tokens);
3089 self.value.to_tokens(tokens);
3090 }
3091 }
3092
3093 #[cfg(feature = "full")]
3094 impl ToTokens for ExprArray {
to_tokens(&self, tokens: &mut TokenStream)3095 fn to_tokens(&self, tokens: &mut TokenStream) {
3096 outer_attrs_to_tokens(&self.attrs, tokens);
3097 self.bracket_token.surround(tokens, |tokens| {
3098 inner_attrs_to_tokens(&self.attrs, tokens);
3099 self.elems.to_tokens(tokens);
3100 })
3101 }
3102 }
3103
3104 impl ToTokens for ExprCall {
to_tokens(&self, tokens: &mut TokenStream)3105 fn to_tokens(&self, tokens: &mut TokenStream) {
3106 outer_attrs_to_tokens(&self.attrs, tokens);
3107 self.func.to_tokens(tokens);
3108 self.paren_token.surround(tokens, |tokens| {
3109 self.args.to_tokens(tokens);
3110 })
3111 }
3112 }
3113
3114 #[cfg(feature = "full")]
3115 impl ToTokens for ExprMethodCall {
to_tokens(&self, tokens: &mut TokenStream)3116 fn to_tokens(&self, tokens: &mut TokenStream) {
3117 outer_attrs_to_tokens(&self.attrs, tokens);
3118 self.receiver.to_tokens(tokens);
3119 self.dot_token.to_tokens(tokens);
3120 self.method.to_tokens(tokens);
3121 self.turbofish.to_tokens(tokens);
3122 self.paren_token.surround(tokens, |tokens| {
3123 self.args.to_tokens(tokens);
3124 });
3125 }
3126 }
3127
3128 #[cfg(feature = "full")]
3129 impl ToTokens for MethodTurbofish {
to_tokens(&self, tokens: &mut TokenStream)3130 fn to_tokens(&self, tokens: &mut TokenStream) {
3131 self.colon2_token.to_tokens(tokens);
3132 self.lt_token.to_tokens(tokens);
3133 self.args.to_tokens(tokens);
3134 self.gt_token.to_tokens(tokens);
3135 }
3136 }
3137
3138 #[cfg(feature = "full")]
3139 impl ToTokens for GenericMethodArgument {
to_tokens(&self, tokens: &mut TokenStream)3140 fn to_tokens(&self, tokens: &mut TokenStream) {
3141 match *self {
3142 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3143 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3144 }
3145 }
3146 }
3147
3148 #[cfg(feature = "full")]
3149 impl ToTokens for ExprTuple {
to_tokens(&self, tokens: &mut TokenStream)3150 fn to_tokens(&self, tokens: &mut TokenStream) {
3151 outer_attrs_to_tokens(&self.attrs, tokens);
3152 self.paren_token.surround(tokens, |tokens| {
3153 inner_attrs_to_tokens(&self.attrs, tokens);
3154 self.elems.to_tokens(tokens);
3155 // If we only have one argument, we need a trailing comma to
3156 // distinguish ExprTuple from ExprParen.
3157 if self.elems.len() == 1 && !self.elems.trailing_punct() {
3158 <Token![,]>::default().to_tokens(tokens);
3159 }
3160 })
3161 }
3162 }
3163
3164 impl ToTokens for ExprBinary {
to_tokens(&self, tokens: &mut TokenStream)3165 fn to_tokens(&self, tokens: &mut TokenStream) {
3166 outer_attrs_to_tokens(&self.attrs, tokens);
3167 self.left.to_tokens(tokens);
3168 self.op.to_tokens(tokens);
3169 self.right.to_tokens(tokens);
3170 }
3171 }
3172
3173 impl ToTokens for ExprUnary {
to_tokens(&self, tokens: &mut TokenStream)3174 fn to_tokens(&self, tokens: &mut TokenStream) {
3175 outer_attrs_to_tokens(&self.attrs, tokens);
3176 self.op.to_tokens(tokens);
3177 self.expr.to_tokens(tokens);
3178 }
3179 }
3180
3181 impl ToTokens for ExprLit {
to_tokens(&self, tokens: &mut TokenStream)3182 fn to_tokens(&self, tokens: &mut TokenStream) {
3183 outer_attrs_to_tokens(&self.attrs, tokens);
3184 self.lit.to_tokens(tokens);
3185 }
3186 }
3187
3188 impl ToTokens for ExprCast {
to_tokens(&self, tokens: &mut TokenStream)3189 fn to_tokens(&self, tokens: &mut TokenStream) {
3190 outer_attrs_to_tokens(&self.attrs, tokens);
3191 self.expr.to_tokens(tokens);
3192 self.as_token.to_tokens(tokens);
3193 self.ty.to_tokens(tokens);
3194 }
3195 }
3196
3197 #[cfg(feature = "full")]
3198 impl ToTokens for ExprType {
to_tokens(&self, tokens: &mut TokenStream)3199 fn to_tokens(&self, tokens: &mut TokenStream) {
3200 outer_attrs_to_tokens(&self.attrs, tokens);
3201 self.expr.to_tokens(tokens);
3202 self.colon_token.to_tokens(tokens);
3203 self.ty.to_tokens(tokens);
3204 }
3205 }
3206
3207 #[cfg(feature = "full")]
maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>)3208 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
3209 if let Some((ref else_token, ref else_)) = *else_ {
3210 else_token.to_tokens(tokens);
3211
3212 // If we are not one of the valid expressions to exist in an else
3213 // clause, wrap ourselves in a block.
3214 match **else_ {
3215 Expr::If(_) | Expr::Block(_) => {
3216 else_.to_tokens(tokens);
3217 }
3218 _ => {
3219 token::Brace::default().surround(tokens, |tokens| {
3220 else_.to_tokens(tokens);
3221 });
3222 }
3223 }
3224 }
3225 }
3226
3227 #[cfg(feature = "full")]
3228 impl ToTokens for ExprLet {
to_tokens(&self, tokens: &mut TokenStream)3229 fn to_tokens(&self, tokens: &mut TokenStream) {
3230 outer_attrs_to_tokens(&self.attrs, tokens);
3231 self.let_token.to_tokens(tokens);
3232 self.pats.to_tokens(tokens);
3233 self.eq_token.to_tokens(tokens);
3234 wrap_bare_struct(tokens, &self.expr);
3235 }
3236 }
3237
3238 #[cfg(feature = "full")]
3239 impl ToTokens for ExprIf {
to_tokens(&self, tokens: &mut TokenStream)3240 fn to_tokens(&self, tokens: &mut TokenStream) {
3241 outer_attrs_to_tokens(&self.attrs, tokens);
3242 self.if_token.to_tokens(tokens);
3243 wrap_bare_struct(tokens, &self.cond);
3244 self.then_branch.to_tokens(tokens);
3245 maybe_wrap_else(tokens, &self.else_branch);
3246 }
3247 }
3248
3249 #[cfg(feature = "full")]
3250 impl ToTokens for ExprWhile {
to_tokens(&self, tokens: &mut TokenStream)3251 fn to_tokens(&self, tokens: &mut TokenStream) {
3252 outer_attrs_to_tokens(&self.attrs, tokens);
3253 self.label.to_tokens(tokens);
3254 self.while_token.to_tokens(tokens);
3255 wrap_bare_struct(tokens, &self.cond);
3256 self.body.brace_token.surround(tokens, |tokens| {
3257 inner_attrs_to_tokens(&self.attrs, tokens);
3258 tokens.append_all(&self.body.stmts);
3259 });
3260 }
3261 }
3262
3263 #[cfg(feature = "full")]
3264 impl ToTokens for ExprForLoop {
to_tokens(&self, tokens: &mut TokenStream)3265 fn to_tokens(&self, tokens: &mut TokenStream) {
3266 outer_attrs_to_tokens(&self.attrs, tokens);
3267 self.label.to_tokens(tokens);
3268 self.for_token.to_tokens(tokens);
3269 self.pat.to_tokens(tokens);
3270 self.in_token.to_tokens(tokens);
3271 wrap_bare_struct(tokens, &self.expr);
3272 self.body.brace_token.surround(tokens, |tokens| {
3273 inner_attrs_to_tokens(&self.attrs, tokens);
3274 tokens.append_all(&self.body.stmts);
3275 });
3276 }
3277 }
3278
3279 #[cfg(feature = "full")]
3280 impl ToTokens for ExprLoop {
to_tokens(&self, tokens: &mut TokenStream)3281 fn to_tokens(&self, tokens: &mut TokenStream) {
3282 outer_attrs_to_tokens(&self.attrs, tokens);
3283 self.label.to_tokens(tokens);
3284 self.loop_token.to_tokens(tokens);
3285 self.body.brace_token.surround(tokens, |tokens| {
3286 inner_attrs_to_tokens(&self.attrs, tokens);
3287 tokens.append_all(&self.body.stmts);
3288 });
3289 }
3290 }
3291
3292 #[cfg(feature = "full")]
3293 impl ToTokens for ExprMatch {
to_tokens(&self, tokens: &mut TokenStream)3294 fn to_tokens(&self, tokens: &mut TokenStream) {
3295 outer_attrs_to_tokens(&self.attrs, tokens);
3296 self.match_token.to_tokens(tokens);
3297 wrap_bare_struct(tokens, &self.expr);
3298 self.brace_token.surround(tokens, |tokens| {
3299 inner_attrs_to_tokens(&self.attrs, tokens);
3300 for (i, arm) in self.arms.iter().enumerate() {
3301 arm.to_tokens(tokens);
3302 // Ensure that we have a comma after a non-block arm, except
3303 // for the last one.
3304 let is_last = i == self.arms.len() - 1;
3305 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
3306 <Token![,]>::default().to_tokens(tokens);
3307 }
3308 }
3309 });
3310 }
3311 }
3312
3313 #[cfg(feature = "full")]
3314 impl ToTokens for ExprAsync {
to_tokens(&self, tokens: &mut TokenStream)3315 fn to_tokens(&self, tokens: &mut TokenStream) {
3316 outer_attrs_to_tokens(&self.attrs, tokens);
3317 self.async_token.to_tokens(tokens);
3318 self.capture.to_tokens(tokens);
3319 self.block.to_tokens(tokens);
3320 }
3321 }
3322
3323 #[cfg(feature = "full")]
3324 impl ToTokens for ExprTryBlock {
to_tokens(&self, tokens: &mut TokenStream)3325 fn to_tokens(&self, tokens: &mut TokenStream) {
3326 outer_attrs_to_tokens(&self.attrs, tokens);
3327 self.try_token.to_tokens(tokens);
3328 self.block.to_tokens(tokens);
3329 }
3330 }
3331
3332 #[cfg(feature = "full")]
3333 impl ToTokens for ExprYield {
to_tokens(&self, tokens: &mut TokenStream)3334 fn to_tokens(&self, tokens: &mut TokenStream) {
3335 outer_attrs_to_tokens(&self.attrs, tokens);
3336 self.yield_token.to_tokens(tokens);
3337 self.expr.to_tokens(tokens);
3338 }
3339 }
3340
3341 #[cfg(feature = "full")]
3342 impl ToTokens for ExprClosure {
to_tokens(&self, tokens: &mut TokenStream)3343 fn to_tokens(&self, tokens: &mut TokenStream) {
3344 outer_attrs_to_tokens(&self.attrs, tokens);
3345 self.asyncness.to_tokens(tokens);
3346 self.movability.to_tokens(tokens);
3347 self.capture.to_tokens(tokens);
3348 self.or1_token.to_tokens(tokens);
3349 for input in self.inputs.pairs() {
3350 match **input.value() {
3351 FnArg::Captured(ArgCaptured {
3352 ref pat,
3353 ty: Type::Infer(_),
3354 ..
3355 }) => {
3356 pat.to_tokens(tokens);
3357 }
3358 _ => input.value().to_tokens(tokens),
3359 }
3360 input.punct().to_tokens(tokens);
3361 }
3362 self.or2_token.to_tokens(tokens);
3363 self.output.to_tokens(tokens);
3364 self.body.to_tokens(tokens);
3365 }
3366 }
3367
3368 #[cfg(feature = "full")]
3369 impl ToTokens for ExprUnsafe {
to_tokens(&self, tokens: &mut TokenStream)3370 fn to_tokens(&self, tokens: &mut TokenStream) {
3371 outer_attrs_to_tokens(&self.attrs, tokens);
3372 self.unsafe_token.to_tokens(tokens);
3373 self.block.brace_token.surround(tokens, |tokens| {
3374 inner_attrs_to_tokens(&self.attrs, tokens);
3375 tokens.append_all(&self.block.stmts);
3376 });
3377 }
3378 }
3379
3380 #[cfg(feature = "full")]
3381 impl ToTokens for ExprBlock {
to_tokens(&self, tokens: &mut TokenStream)3382 fn to_tokens(&self, tokens: &mut TokenStream) {
3383 outer_attrs_to_tokens(&self.attrs, tokens);
3384 self.label.to_tokens(tokens);
3385 self.block.brace_token.surround(tokens, |tokens| {
3386 inner_attrs_to_tokens(&self.attrs, tokens);
3387 tokens.append_all(&self.block.stmts);
3388 });
3389 }
3390 }
3391
3392 #[cfg(feature = "full")]
3393 impl ToTokens for ExprAssign {
to_tokens(&self, tokens: &mut TokenStream)3394 fn to_tokens(&self, tokens: &mut TokenStream) {
3395 outer_attrs_to_tokens(&self.attrs, tokens);
3396 self.left.to_tokens(tokens);
3397 self.eq_token.to_tokens(tokens);
3398 self.right.to_tokens(tokens);
3399 }
3400 }
3401
3402 #[cfg(feature = "full")]
3403 impl ToTokens for ExprAssignOp {
to_tokens(&self, tokens: &mut TokenStream)3404 fn to_tokens(&self, tokens: &mut TokenStream) {
3405 outer_attrs_to_tokens(&self.attrs, tokens);
3406 self.left.to_tokens(tokens);
3407 self.op.to_tokens(tokens);
3408 self.right.to_tokens(tokens);
3409 }
3410 }
3411
3412 impl ToTokens for ExprField {
to_tokens(&self, tokens: &mut TokenStream)3413 fn to_tokens(&self, tokens: &mut TokenStream) {
3414 outer_attrs_to_tokens(&self.attrs, tokens);
3415 self.base.to_tokens(tokens);
3416 self.dot_token.to_tokens(tokens);
3417 self.member.to_tokens(tokens);
3418 }
3419 }
3420
3421 impl ToTokens for Member {
to_tokens(&self, tokens: &mut TokenStream)3422 fn to_tokens(&self, tokens: &mut TokenStream) {
3423 match *self {
3424 Member::Named(ref ident) => ident.to_tokens(tokens),
3425 Member::Unnamed(ref index) => index.to_tokens(tokens),
3426 }
3427 }
3428 }
3429
3430 impl ToTokens for Index {
to_tokens(&self, tokens: &mut TokenStream)3431 fn to_tokens(&self, tokens: &mut TokenStream) {
3432 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3433 lit.set_span(self.span);
3434 tokens.append(lit);
3435 }
3436 }
3437
3438 impl ToTokens for ExprIndex {
to_tokens(&self, tokens: &mut TokenStream)3439 fn to_tokens(&self, tokens: &mut TokenStream) {
3440 outer_attrs_to_tokens(&self.attrs, tokens);
3441 self.expr.to_tokens(tokens);
3442 self.bracket_token.surround(tokens, |tokens| {
3443 self.index.to_tokens(tokens);
3444 });
3445 }
3446 }
3447
3448 #[cfg(feature = "full")]
3449 impl ToTokens for ExprRange {
to_tokens(&self, tokens: &mut TokenStream)3450 fn to_tokens(&self, tokens: &mut TokenStream) {
3451 outer_attrs_to_tokens(&self.attrs, tokens);
3452 self.from.to_tokens(tokens);
3453 match self.limits {
3454 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3455 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3456 }
3457 self.to.to_tokens(tokens);
3458 }
3459 }
3460
3461 impl ToTokens for ExprPath {
to_tokens(&self, tokens: &mut TokenStream)3462 fn to_tokens(&self, tokens: &mut TokenStream) {
3463 outer_attrs_to_tokens(&self.attrs, tokens);
3464 private::print_path(tokens, &self.qself, &self.path);
3465 }
3466 }
3467
3468 #[cfg(feature = "full")]
3469 impl ToTokens for ExprReference {
to_tokens(&self, tokens: &mut TokenStream)3470 fn to_tokens(&self, tokens: &mut TokenStream) {
3471 outer_attrs_to_tokens(&self.attrs, tokens);
3472 self.and_token.to_tokens(tokens);
3473 self.mutability.to_tokens(tokens);
3474 self.expr.to_tokens(tokens);
3475 }
3476 }
3477
3478 #[cfg(feature = "full")]
3479 impl ToTokens for ExprBreak {
to_tokens(&self, tokens: &mut TokenStream)3480 fn to_tokens(&self, tokens: &mut TokenStream) {
3481 outer_attrs_to_tokens(&self.attrs, tokens);
3482 self.break_token.to_tokens(tokens);
3483 self.label.to_tokens(tokens);
3484 self.expr.to_tokens(tokens);
3485 }
3486 }
3487
3488 #[cfg(feature = "full")]
3489 impl ToTokens for ExprContinue {
to_tokens(&self, tokens: &mut TokenStream)3490 fn to_tokens(&self, tokens: &mut TokenStream) {
3491 outer_attrs_to_tokens(&self.attrs, tokens);
3492 self.continue_token.to_tokens(tokens);
3493 self.label.to_tokens(tokens);
3494 }
3495 }
3496
3497 #[cfg(feature = "full")]
3498 impl ToTokens for ExprReturn {
to_tokens(&self, tokens: &mut TokenStream)3499 fn to_tokens(&self, tokens: &mut TokenStream) {
3500 outer_attrs_to_tokens(&self.attrs, tokens);
3501 self.return_token.to_tokens(tokens);
3502 self.expr.to_tokens(tokens);
3503 }
3504 }
3505
3506 #[cfg(feature = "full")]
3507 impl ToTokens for ExprMacro {
to_tokens(&self, tokens: &mut TokenStream)3508 fn to_tokens(&self, tokens: &mut TokenStream) {
3509 outer_attrs_to_tokens(&self.attrs, tokens);
3510 self.mac.to_tokens(tokens);
3511 }
3512 }
3513
3514 #[cfg(feature = "full")]
3515 impl ToTokens for ExprStruct {
to_tokens(&self, tokens: &mut TokenStream)3516 fn to_tokens(&self, tokens: &mut TokenStream) {
3517 outer_attrs_to_tokens(&self.attrs, tokens);
3518 self.path.to_tokens(tokens);
3519 self.brace_token.surround(tokens, |tokens| {
3520 inner_attrs_to_tokens(&self.attrs, tokens);
3521 self.fields.to_tokens(tokens);
3522 if self.rest.is_some() {
3523 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
3524 self.rest.to_tokens(tokens);
3525 }
3526 })
3527 }
3528 }
3529
3530 #[cfg(feature = "full")]
3531 impl ToTokens for ExprRepeat {
to_tokens(&self, tokens: &mut TokenStream)3532 fn to_tokens(&self, tokens: &mut TokenStream) {
3533 outer_attrs_to_tokens(&self.attrs, tokens);
3534 self.bracket_token.surround(tokens, |tokens| {
3535 inner_attrs_to_tokens(&self.attrs, tokens);
3536 self.expr.to_tokens(tokens);
3537 self.semi_token.to_tokens(tokens);
3538 self.len.to_tokens(tokens);
3539 })
3540 }
3541 }
3542
3543 #[cfg(feature = "full")]
3544 impl ToTokens for ExprGroup {
to_tokens(&self, tokens: &mut TokenStream)3545 fn to_tokens(&self, tokens: &mut TokenStream) {
3546 outer_attrs_to_tokens(&self.attrs, tokens);
3547 self.group_token.surround(tokens, |tokens| {
3548 self.expr.to_tokens(tokens);
3549 });
3550 }
3551 }
3552
3553 impl ToTokens for ExprParen {
to_tokens(&self, tokens: &mut TokenStream)3554 fn to_tokens(&self, tokens: &mut TokenStream) {
3555 outer_attrs_to_tokens(&self.attrs, tokens);
3556 self.paren_token.surround(tokens, |tokens| {
3557 inner_attrs_to_tokens(&self.attrs, tokens);
3558 self.expr.to_tokens(tokens);
3559 });
3560 }
3561 }
3562
3563 #[cfg(feature = "full")]
3564 impl ToTokens for ExprTry {
to_tokens(&self, tokens: &mut TokenStream)3565 fn to_tokens(&self, tokens: &mut TokenStream) {
3566 outer_attrs_to_tokens(&self.attrs, tokens);
3567 self.expr.to_tokens(tokens);
3568 self.question_token.to_tokens(tokens);
3569 }
3570 }
3571
3572 impl ToTokens for ExprVerbatim {
to_tokens(&self, tokens: &mut TokenStream)3573 fn to_tokens(&self, tokens: &mut TokenStream) {
3574 self.tts.to_tokens(tokens);
3575 }
3576 }
3577
3578 #[cfg(feature = "full")]
3579 impl ToTokens for Label {
to_tokens(&self, tokens: &mut TokenStream)3580 fn to_tokens(&self, tokens: &mut TokenStream) {
3581 self.name.to_tokens(tokens);
3582 self.colon_token.to_tokens(tokens);
3583 }
3584 }
3585
3586 #[cfg(feature = "full")]
3587 impl ToTokens for FieldValue {
to_tokens(&self, tokens: &mut TokenStream)3588 fn to_tokens(&self, tokens: &mut TokenStream) {
3589 outer_attrs_to_tokens(&self.attrs, tokens);
3590 self.member.to_tokens(tokens);
3591 if let Some(ref colon_token) = self.colon_token {
3592 colon_token.to_tokens(tokens);
3593 self.expr.to_tokens(tokens);
3594 }
3595 }
3596 }
3597
3598 #[cfg(feature = "full")]
3599 impl ToTokens for Arm {
to_tokens(&self, tokens: &mut TokenStream)3600 fn to_tokens(&self, tokens: &mut TokenStream) {
3601 tokens.append_all(&self.attrs);
3602 self.leading_vert.to_tokens(tokens);
3603 self.pats.to_tokens(tokens);
3604 if let Some((ref if_token, ref guard)) = self.guard {
3605 if_token.to_tokens(tokens);
3606 guard.to_tokens(tokens);
3607 }
3608 self.fat_arrow_token.to_tokens(tokens);
3609 self.body.to_tokens(tokens);
3610 self.comma.to_tokens(tokens);
3611 }
3612 }
3613
3614 #[cfg(feature = "full")]
3615 impl ToTokens for PatWild {
to_tokens(&self, tokens: &mut TokenStream)3616 fn to_tokens(&self, tokens: &mut TokenStream) {
3617 self.underscore_token.to_tokens(tokens);
3618 }
3619 }
3620
3621 #[cfg(feature = "full")]
3622 impl ToTokens for PatIdent {
to_tokens(&self, tokens: &mut TokenStream)3623 fn to_tokens(&self, tokens: &mut TokenStream) {
3624 self.by_ref.to_tokens(tokens);
3625 self.mutability.to_tokens(tokens);
3626 self.ident.to_tokens(tokens);
3627 if let Some((ref at_token, ref subpat)) = self.subpat {
3628 at_token.to_tokens(tokens);
3629 subpat.to_tokens(tokens);
3630 }
3631 }
3632 }
3633
3634 #[cfg(feature = "full")]
3635 impl ToTokens for PatStruct {
to_tokens(&self, tokens: &mut TokenStream)3636 fn to_tokens(&self, tokens: &mut TokenStream) {
3637 self.path.to_tokens(tokens);
3638 self.brace_token.surround(tokens, |tokens| {
3639 self.fields.to_tokens(tokens);
3640 // NOTE: We need a comma before the dot2 token if it is present.
3641 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
3642 <Token![,]>::default().to_tokens(tokens);
3643 }
3644 self.dot2_token.to_tokens(tokens);
3645 });
3646 }
3647 }
3648
3649 #[cfg(feature = "full")]
3650 impl ToTokens for PatTupleStruct {
to_tokens(&self, tokens: &mut TokenStream)3651 fn to_tokens(&self, tokens: &mut TokenStream) {
3652 self.path.to_tokens(tokens);
3653 self.pat.to_tokens(tokens);
3654 }
3655 }
3656
3657 #[cfg(feature = "full")]
3658 impl ToTokens for PatPath {
to_tokens(&self, tokens: &mut TokenStream)3659 fn to_tokens(&self, tokens: &mut TokenStream) {
3660 private::print_path(tokens, &self.qself, &self.path);
3661 }
3662 }
3663
3664 #[cfg(feature = "full")]
3665 impl ToTokens for PatTuple {
to_tokens(&self, tokens: &mut TokenStream)3666 fn to_tokens(&self, tokens: &mut TokenStream) {
3667 self.paren_token.surround(tokens, |tokens| {
3668 self.front.to_tokens(tokens);
3669 if let Some(ref dot2_token) = self.dot2_token {
3670 if !self.front.empty_or_trailing() {
3671 // Ensure there is a comma before the .. token.
3672 <Token![,]>::default().to_tokens(tokens);
3673 }
3674 dot2_token.to_tokens(tokens);
3675 self.comma_token.to_tokens(tokens);
3676 if self.comma_token.is_none() && !self.back.is_empty() {
3677 // Ensure there is a comma after the .. token.
3678 <Token![,]>::default().to_tokens(tokens);
3679 }
3680 }
3681 self.back.to_tokens(tokens);
3682 });
3683 }
3684 }
3685
3686 #[cfg(feature = "full")]
3687 impl ToTokens for PatBox {
to_tokens(&self, tokens: &mut TokenStream)3688 fn to_tokens(&self, tokens: &mut TokenStream) {
3689 self.box_token.to_tokens(tokens);
3690 self.pat.to_tokens(tokens);
3691 }
3692 }
3693
3694 #[cfg(feature = "full")]
3695 impl ToTokens for PatRef {
to_tokens(&self, tokens: &mut TokenStream)3696 fn to_tokens(&self, tokens: &mut TokenStream) {
3697 self.and_token.to_tokens(tokens);
3698 self.mutability.to_tokens(tokens);
3699 self.pat.to_tokens(tokens);
3700 }
3701 }
3702
3703 #[cfg(feature = "full")]
3704 impl ToTokens for PatLit {
to_tokens(&self, tokens: &mut TokenStream)3705 fn to_tokens(&self, tokens: &mut TokenStream) {
3706 self.expr.to_tokens(tokens);
3707 }
3708 }
3709
3710 #[cfg(feature = "full")]
3711 impl ToTokens for PatRange {
to_tokens(&self, tokens: &mut TokenStream)3712 fn to_tokens(&self, tokens: &mut TokenStream) {
3713 self.lo.to_tokens(tokens);
3714 match self.limits {
3715 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3716 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3717 }
3718 self.hi.to_tokens(tokens);
3719 }
3720 }
3721
3722 #[cfg(feature = "full")]
3723 impl ToTokens for PatSlice {
to_tokens(&self, tokens: &mut TokenStream)3724 fn to_tokens(&self, tokens: &mut TokenStream) {
3725 self.bracket_token.surround(tokens, |tokens| {
3726 self.front.to_tokens(tokens);
3727
3728 // If we need a comma before the middle or standalone .. token,
3729 // then make sure it's present.
3730 if !self.front.empty_or_trailing()
3731 && (self.middle.is_some() || self.dot2_token.is_some())
3732 {
3733 <Token![,]>::default().to_tokens(tokens);
3734 }
3735
3736 // If we have an identifier, we always need a .. token.
3737 if self.middle.is_some() {
3738 self.middle.to_tokens(tokens);
3739 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
3740 } else if self.dot2_token.is_some() {
3741 self.dot2_token.to_tokens(tokens);
3742 }
3743
3744 // Make sure we have a comma before the back half.
3745 if !self.back.is_empty() {
3746 TokensOrDefault(&self.comma_token).to_tokens(tokens);
3747 self.back.to_tokens(tokens);
3748 } else {
3749 self.comma_token.to_tokens(tokens);
3750 }
3751 })
3752 }
3753 }
3754
3755 #[cfg(feature = "full")]
3756 impl ToTokens for PatMacro {
to_tokens(&self, tokens: &mut TokenStream)3757 fn to_tokens(&self, tokens: &mut TokenStream) {
3758 self.mac.to_tokens(tokens);
3759 }
3760 }
3761
3762 #[cfg(feature = "full")]
3763 impl ToTokens for PatVerbatim {
to_tokens(&self, tokens: &mut TokenStream)3764 fn to_tokens(&self, tokens: &mut TokenStream) {
3765 self.tts.to_tokens(tokens);
3766 }
3767 }
3768
3769 #[cfg(feature = "full")]
3770 impl ToTokens for FieldPat {
to_tokens(&self, tokens: &mut TokenStream)3771 fn to_tokens(&self, tokens: &mut TokenStream) {
3772 if let Some(ref colon_token) = self.colon_token {
3773 self.member.to_tokens(tokens);
3774 colon_token.to_tokens(tokens);
3775 }
3776 self.pat.to_tokens(tokens);
3777 }
3778 }
3779
3780 #[cfg(feature = "full")]
3781 impl ToTokens for Block {
to_tokens(&self, tokens: &mut TokenStream)3782 fn to_tokens(&self, tokens: &mut TokenStream) {
3783 self.brace_token.surround(tokens, |tokens| {
3784 tokens.append_all(&self.stmts);
3785 });
3786 }
3787 }
3788
3789 #[cfg(feature = "full")]
3790 impl ToTokens for Stmt {
to_tokens(&self, tokens: &mut TokenStream)3791 fn to_tokens(&self, tokens: &mut TokenStream) {
3792 match *self {
3793 Stmt::Local(ref local) => local.to_tokens(tokens),
3794 Stmt::Item(ref item) => item.to_tokens(tokens),
3795 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
3796 Stmt::Semi(ref expr, ref semi) => {
3797 expr.to_tokens(tokens);
3798 semi.to_tokens(tokens);
3799 }
3800 }
3801 }
3802 }
3803
3804 #[cfg(feature = "full")]
3805 impl ToTokens for Local {
to_tokens(&self, tokens: &mut TokenStream)3806 fn to_tokens(&self, tokens: &mut TokenStream) {
3807 outer_attrs_to_tokens(&self.attrs, tokens);
3808 self.let_token.to_tokens(tokens);
3809 self.pats.to_tokens(tokens);
3810 if let Some((ref colon_token, ref ty)) = self.ty {
3811 colon_token.to_tokens(tokens);
3812 ty.to_tokens(tokens);
3813 }
3814 if let Some((ref eq_token, ref init)) = self.init {
3815 eq_token.to_tokens(tokens);
3816 init.to_tokens(tokens);
3817 }
3818 self.semi_token.to_tokens(tokens);
3819 }
3820 }
3821 }
3822