1use core::mem::take;
2use core::ops;
3
4use crate::ast::prelude::*;
5
6#[test]
7#[cfg(not(miri))]
8fn ast_parse() {
9 rt::<ast::Expr>("()");
10 rt::<ast::Expr>("foo[\"foo\"]");
11 rt::<ast::Expr>("foo[\"bar\"]");
12 rt::<ast::Expr>("foo.bar()");
13 rt::<ast::Expr>("var()");
14 rt::<ast::Expr>("var");
15 rt::<ast::Expr>("42");
16 rt::<ast::Expr>("1 + 2 / 3 - 4 * 1");
17 rt::<ast::Expr>("let var = 42");
18 rt::<ast::Expr>("let var = \"foo bar\"");
19 rt::<ast::Expr>("var[\"foo\"] = \"bar\"");
20 rt::<ast::Expr>("let var = objects[\"foo\"] + 1");
21 rt::<ast::Expr>("var = 42");
22
23 let expr = rt::<ast::Expr>(
24 r#"
25 if 1 { } else { if 2 { } else { } }
26 "#,
27 );
28 assert!(matches!(expr, ast::Expr::If(..)));
29
30 rt::<ast::Expr>("foo.bar.baz()");
32 rt::<ast::Expr>("foo[0][1][2]");
33 rt::<ast::Expr>("foo.bar()[0].baz()[1]");
34
35 rt::<ast::Expr>("42 is i64::i64");
36 rt::<ast::Expr>("{ let x = 1; x }");
37
38 let expr = rt::<ast::Expr>("#[cfg(debug_assertions)] { assert_eq(x, 32); }");
39 assert!(
40 matches!(expr, ast::Expr::Block(b) if b.attributes.len() == 1 && b.block.statements.len() == 1)
41 );
42
43 rt::<ast::Expr>("#{\"foo\": b\"bar\"}");
44 rt::<ast::Expr>("Disco {\"never_died\": true }");
45 rt::<ast::Expr>("(false, 1, 'n')");
46 rt::<ast::Expr>("[false, 1, 'b']");
47
48 let expr = rt::<ast::Expr>(r#"if true {} else {}"#);
49 assert!(matches!(expr, ast::Expr::If(..)));
50
51 let expr = rt::<ast::Expr>("if 1 { } else { if 2 { } else { } }");
52 assert!(matches!(expr, ast::Expr::If(..)));
53
54 let expr = rt::<ast::Expr>(r#"while true {}"#);
55 assert!(matches!(expr, ast::Expr::While(..)));
56
57 rt::<ast::Expr>("format!(\"{}\", a).bar()");
58}
59
60#[derive(Debug, Clone, Copy)]
62pub(crate) struct EagerBrace(bool);
63
64pub(crate) const EAGER_BRACE: EagerBrace = EagerBrace(true);
66
67pub(crate) const NOT_EAGER_BRACE: EagerBrace = EagerBrace(false);
70
71impl ops::Deref for EagerBrace {
72 type Target = bool;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79#[derive(Debug, Clone, Copy)]
81pub(crate) struct EagerBinary(bool);
82
83pub(crate) const EAGER_BINARY: EagerBinary = EagerBinary(true);
85
86pub(crate) const NOT_EAGER_BINARY: EagerBinary = EagerBinary(false);
88
89impl ops::Deref for EagerBinary {
90 type Target = bool;
91
92 fn deref(&self) -> &Self::Target {
93 &self.0
94 }
95}
96
97#[derive(Debug, Clone, Copy)]
101pub(crate) struct Callable(bool);
102
103pub(crate) const CALLABLE: Callable = Callable(true);
106
107pub(crate) const NOT_CALLABLE: Callable = Callable(false);
110
111impl ops::Deref for Callable {
112 type Target = bool;
113
114 fn deref(&self) -> &Self::Target {
115 &self.0
116 }
117}
118
119#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
121#[non_exhaustive]
122pub enum Expr {
123 Path(ast::Path),
125 Assign(ast::ExprAssign),
127 While(ast::ExprWhile),
129 Loop(ast::ExprLoop),
131 For(ast::ExprFor),
133 Let(ast::ExprLet),
135 If(ast::ExprIf),
137 Match(ast::ExprMatch),
139 Call(ast::ExprCall),
141 FieldAccess(ast::ExprFieldAccess),
143 Binary(ast::ExprBinary),
145 Unary(ast::ExprUnary),
147 Index(ast::ExprIndex),
149 Break(ast::ExprBreak),
151 Continue(ast::ExprContinue),
153 Yield(ast::ExprYield),
155 Block(ast::ExprBlock),
157 Return(ast::ExprReturn),
159 Await(ast::ExprAwait),
161 Try(ast::ExprTry),
163 Select(ast::ExprSelect),
165 Closure(ast::ExprClosure),
167 Lit(ast::ExprLit),
169 Object(ast::ExprObject),
171 Tuple(ast::ExprTuple),
173 Vec(ast::ExprVec),
175 Range(ast::ExprRange),
177 Empty(ast::ExprEmpty),
179 Group(ast::ExprGroup),
181 MacroCall(ast::MacroCall),
183}
184
185impl Expr {
186 pub(crate) fn attributes(&self) -> &[ast::Attribute] {
188 match self {
189 Self::Path(_) => &[],
190 Self::Break(expr) => &expr.attributes,
191 Self::Continue(expr) => &expr.attributes,
192 Self::Yield(expr) => &expr.attributes,
193 Self::Block(expr) => &expr.attributes,
194 Self::Return(expr) => &expr.attributes,
195 Self::Closure(expr) => &expr.attributes,
196 Self::Match(expr) => &expr.attributes,
197 Self::While(expr) => &expr.attributes,
198 Self::Loop(expr) => &expr.attributes,
199 Self::For(expr) => &expr.attributes,
200 Self::Let(expr) => &expr.attributes,
201 Self::If(expr) => &expr.attributes,
202 Self::Select(expr) => &expr.attributes,
203 Self::Lit(expr) => &expr.attributes,
204 Self::Assign(expr) => &expr.attributes,
205 Self::Binary(expr) => &expr.attributes,
206 Self::Call(expr) => &expr.attributes,
207 Self::FieldAccess(expr) => &expr.attributes,
208 Self::Group(expr) => &expr.attributes,
209 Self::Empty(expr) => &expr.attributes,
210 Self::Unary(expr) => &expr.attributes,
211 Self::Index(expr) => &expr.attributes,
212 Self::Await(expr) => &expr.attributes,
213 Self::Try(expr) => &expr.attributes,
214 Self::MacroCall(expr) => &expr.attributes,
215 Self::Object(expr) => &expr.attributes,
216 Self::Range(expr) => &expr.attributes,
217 Self::Tuple(expr) => &expr.attributes,
218 Self::Vec(expr) => &expr.attributes,
219 }
220 }
221
222 pub(crate) fn needs_semi(&self) -> bool {
224 match self {
225 Self::While(_) => false,
226 Self::Loop(_) => false,
227 Self::For(_) => false,
228 Self::If(_) => false,
229 Self::Match(_) => false,
230 Self::Block(_) => false,
231 Self::Select(_) => false,
232 Self::MacroCall(macro_call) => macro_call.needs_semi(),
233 _ => true,
234 }
235 }
236
237 pub(crate) fn is_callable(&self, callable: bool) -> bool {
240 match self {
241 Self::While(_) => false,
242 Self::Loop(_) => callable,
243 Self::For(_) => false,
244 Self::If(_) => callable,
245 Self::Match(_) => callable,
246 Self::Select(_) => callable,
247 _ => true,
248 }
249 }
250
251 pub(crate) fn take_attributes(&mut self) -> Vec<ast::Attribute> {
253 match self {
254 Self::Path(_) => Vec::new(),
255 Self::Break(expr) => take(&mut expr.attributes),
256 Self::Continue(expr) => take(&mut expr.attributes),
257 Self::Yield(expr) => take(&mut expr.attributes),
258 Self::Block(expr) => take(&mut expr.attributes),
259 Self::Return(expr) => take(&mut expr.attributes),
260 Self::Closure(expr) => take(&mut expr.attributes),
261 Self::Match(expr) => take(&mut expr.attributes),
262 Self::While(expr) => take(&mut expr.attributes),
263 Self::Loop(expr) => take(&mut expr.attributes),
264 Self::For(expr) => take(&mut expr.attributes),
265 Self::Let(expr) => take(&mut expr.attributes),
266 Self::If(expr) => take(&mut expr.attributes),
267 Self::Select(expr) => take(&mut expr.attributes),
268 Self::Lit(expr) => take(&mut expr.attributes),
269 Self::Assign(expr) => take(&mut expr.attributes),
270 Self::Binary(expr) => take(&mut expr.attributes),
271 Self::Call(expr) => take(&mut expr.attributes),
272 Self::FieldAccess(expr) => take(&mut expr.attributes),
273 Self::Group(expr) => take(&mut expr.attributes),
274 Self::Empty(expr) => take(&mut expr.attributes),
275 Self::Unary(expr) => take(&mut expr.attributes),
276 Self::Index(expr) => take(&mut expr.attributes),
277 Self::Await(expr) => take(&mut expr.attributes),
278 Self::Try(expr) => take(&mut expr.attributes),
279 Self::Object(expr) => take(&mut expr.attributes),
280 Self::Range(expr) => take(&mut expr.attributes),
281 Self::Vec(expr) => take(&mut expr.attributes),
282 Self::Tuple(expr) => take(&mut expr.attributes),
283 Self::MacroCall(expr) => take(&mut expr.attributes),
284 }
285 }
286
287 pub(crate) fn is_lit(&self) -> bool {
293 match self {
294 Self::Lit(..) => return true,
295 Self::Unary(ast::ExprUnary {
296 op: ast::UnOp::Neg(..),
297 expr,
298 ..
299 }) => {
300 return matches!(
301 &**expr,
302 Self::Lit(ast::ExprLit {
303 lit: ast::Lit::Number(..),
304 ..
305 })
306 );
307 }
308 _ => (),
309 }
310
311 false
312 }
313
314 pub(crate) fn from_lit(lit: ast::Lit) -> Self {
316 Self::Lit(ast::ExprLit {
317 attributes: Vec::new(),
318 lit,
319 })
320 }
321
322 pub(crate) fn parse_without_eager_brace(p: &mut Parser<'_>) -> Result<Self> {
328 Self::parse_with(p, NOT_EAGER_BRACE, EAGER_BINARY, CALLABLE)
329 }
330
331 pub(crate) fn parse_with_meta(
333 p: &mut Parser<'_>,
334 attributes: &mut Vec<ast::Attribute>,
335 callable: Callable,
336 ) -> Result<Self> {
337 let lhs = primary(p, attributes, EAGER_BRACE, callable)?;
338 let lookahead = ast::BinOp::from_peeker(p.peeker());
339 binary(p, lhs, lookahead, 0, EAGER_BRACE)
340 }
341
342 pub(crate) fn parse_with(
344 p: &mut Parser<'_>,
345 eager_brace: EagerBrace,
346 eager_binary: EagerBinary,
347 callable: Callable,
348 ) -> Result<Self> {
349 let mut attributes = p.parse()?;
350
351 let expr = primary(p, &mut attributes, eager_brace, callable)?;
352
353 let expr = if *eager_binary {
354 let lookeahead = ast::BinOp::from_peeker(p.peeker());
355 binary(p, expr, lookeahead, 0, eager_brace)?
356 } else {
357 expr
358 };
359
360 if let Some(span) = attributes.option_span() {
361 return Err(compile::Error::unsupported(span, "attributes"));
362 }
363
364 Ok(expr)
365 }
366
367 pub(crate) fn parse_with_meta_path(
369 p: &mut Parser<'_>,
370 attributes: &mut Vec<ast::Attribute>,
371 path: ast::Path,
372 eager_brace: EagerBrace,
373 ) -> Result<Self> {
374 if *eager_brace && p.peek::<T!['{']>()? {
375 let ident = ast::ObjectIdent::Named(path);
376
377 return Ok(Self::Object(ast::ExprObject::parse_with_meta(
378 p,
379 take(attributes),
380 ident,
381 )?));
382 }
383
384 if p.peek::<T![!]>()? {
385 return Ok(Self::MacroCall(ast::MacroCall::parse_with_meta_path(
386 p,
387 take(attributes),
388 path,
389 )?));
390 }
391
392 Ok(Self::Path(path))
393 }
394
395 pub(crate) fn peek_with_brace(p: &mut Peeker<'_>, eager_brace: EagerBrace) -> bool {
396 match p.nth(0) {
397 K![async] => true,
398 K![self] => true,
399 K![select] => true,
400 K![#] => true,
401 K![-] => true,
402 K![!] => true,
403 K![&] => true,
404 K![*] => true,
405 K![while] => true,
406 K![loop] => true,
407 K![for] => true,
408 K![let] => true,
409 K![if] => true,
410 K![break] => true,
411 K![continue] => true,
412 K![return] => true,
413 K![true] => true,
414 K![false] => true,
415 K![ident] => true,
416 K![::] => true,
417 K![number] => true,
418 K![char] => true,
419 K![byte] => true,
420 K![str] => true,
421 K![bytestr] => true,
422 K!['label] => matches!(p.nth(1), K![:]),
423 K![..] => true,
424 K!['('] => true,
425 K!['['] => true,
426 K!['{'] if *eager_brace => true,
427 _ => false,
428 }
429 }
430}
431
432impl Parse for Expr {
433 fn parse(p: &mut Parser<'_>) -> Result<Self> {
434 Self::parse_with(p, EAGER_BRACE, EAGER_BINARY, CALLABLE)
435 }
436}
437
438impl Peek for Expr {
439 fn peek(p: &mut Peeker<'_>) -> bool {
440 Self::peek_with_brace(p, EAGER_BRACE)
441 }
442}
443
444fn primary(
446 p: &mut Parser<'_>,
447 attributes: &mut Vec<ast::Attribute>,
448 eager_brace: EagerBrace,
449 callable: Callable,
450) -> Result<Expr> {
451 let expr = base(p, attributes, eager_brace)?;
452 chain(p, expr, callable)
453}
454
455fn base(
457 p: &mut Parser<'_>,
458 attributes: &mut Vec<ast::Attribute>,
459 eager_brace: EagerBrace,
460) -> Result<Expr> {
461 if let Some(path) = p.parse::<Option<ast::Path>>()? {
462 return Expr::parse_with_meta_path(p, attributes, path, eager_brace);
463 }
464
465 if ast::Lit::peek_in_expr(p.peeker()) {
466 return Ok(Expr::Lit(ast::ExprLit::parse_with_meta(
467 p,
468 take(attributes),
469 )?));
470 }
471
472 let mut label = p.parse::<Option<(ast::Label, T![:])>>()?;
473 let mut async_token = p.parse::<Option<T![async]>>()?;
474 let mut const_token = p.parse::<Option<T![const]>>()?;
475 let mut move_token = p.parse::<Option<T![move]>>()?;
476
477 let expr = match p.nth(0)? {
478 K![..] => {
479 let limits = ast::ExprRangeLimits::HalfOpen(p.parse()?);
480 range(p, take(attributes), None, limits, eager_brace)?
481 }
482 K![..=] => {
483 let limits = ast::ExprRangeLimits::Closed(p.parse()?);
484 range(p, take(attributes), None, limits, eager_brace)?
485 }
486 K![#] => {
487 let ident = ast::ObjectIdent::Anonymous(p.parse()?);
488
489 Expr::Object(ast::ExprObject::parse_with_meta(
490 p,
491 take(attributes),
492 ident,
493 )?)
494 }
495 K![||] | K![|] => Expr::Closure(ast::ExprClosure::parse_with_meta(
496 p,
497 take(attributes),
498 take(&mut async_token),
499 take(&mut move_token),
500 )?),
501 K![select] => Expr::Select(ast::ExprSelect::parse_with_attributes(p, take(attributes))?),
502 K![!] | K![-] | K![&] | K![*] => Expr::Unary(ast::ExprUnary::parse_with_meta(
503 p,
504 take(attributes),
505 eager_brace,
506 )?),
507 K![while] => Expr::While(ast::ExprWhile::parse_with_meta(
508 p,
509 take(attributes),
510 take(&mut label),
511 )?),
512 K![loop] => Expr::Loop(ast::ExprLoop::parse_with_meta(
513 p,
514 take(attributes),
515 take(&mut label),
516 )?),
517 K![for] => Expr::For(ast::ExprFor::parse_with_meta(
518 p,
519 take(attributes),
520 take(&mut label),
521 )?),
522 K![let] => Expr::Let(ast::ExprLet::parse_with_meta(p, take(attributes))?),
523 K![if] => Expr::If(ast::ExprIf::parse_with_meta(p, take(attributes))?),
524 K![match] => Expr::Match(ast::ExprMatch::parse_with_attributes(p, take(attributes))?),
525 K!['['] => Expr::Vec(ast::ExprVec::parse_with_meta(p, take(attributes))?),
526 ast::Kind::Open(ast::Delimiter::Empty) => empty_group(p, take(attributes))?,
527 K!['('] => paren_group(p, take(attributes))?,
528 K!['{'] => Expr::Block(ast::ExprBlock {
529 attributes: take(attributes),
530 async_token: take(&mut async_token),
531 const_token: take(&mut const_token),
532 move_token: take(&mut move_token),
533 label: take(&mut label),
534 block: p.parse()?,
535 }),
536 K![break] => Expr::Break(ast::ExprBreak::parse_with_meta(p, take(attributes))?),
537 K![continue] => Expr::Continue(ast::ExprContinue::parse_with_meta(p, take(attributes))?),
538 K![yield] => Expr::Yield(ast::ExprYield::parse_with_meta(p, take(attributes))?),
539 K![return] => Expr::Return(ast::ExprReturn::parse_with_meta(p, take(attributes))?),
540 _ => {
541 return Err(compile::Error::expected(
542 p.tok_at(0)?,
543 Expectation::Expression,
544 ));
545 }
546 };
547
548 if let Some(span) = label.option_span() {
549 return Err(compile::Error::unsupported(span, "label"));
550 }
551
552 if let Some(span) = async_token.option_span() {
553 return Err(compile::Error::unsupported(span, "async modifier"));
554 }
555
556 if let Some(span) = const_token.option_span() {
557 return Err(compile::Error::unsupported(span, "const modifier"));
558 }
559
560 if let Some(span) = move_token.option_span() {
561 return Err(compile::Error::unsupported(span, "move modifier"));
562 }
563
564 Ok(expr)
565}
566
567fn chain(p: &mut Parser<'_>, mut expr: Expr, callable: Callable) -> Result<Expr> {
569 while !p.is_eof()? {
570 let is_callable = expr.is_callable(*callable);
571
572 match p.nth(0)? {
573 K!['['] if is_callable => {
574 expr = Expr::Index(ast::ExprIndex {
575 attributes: expr.take_attributes(),
576 target: Box::try_new(expr)?,
577 open: p.parse()?,
578 index: p.parse()?,
579 close: p.parse()?,
580 });
581 }
582 K!['('] if is_callable => {
584 expr = Expr::Call(ast::ExprCall::parse_with_meta(
585 p,
586 expr.take_attributes(),
587 Box::try_new(expr)?,
588 )?);
589 }
590 K![?] => {
591 expr = Expr::Try(ast::ExprTry {
592 attributes: expr.take_attributes(),
593 expr: Box::try_new(expr)?,
594 try_token: p.parse()?,
595 });
596 }
597 K![=] => {
598 let eq = p.parse()?;
599 let rhs = Expr::parse_with(p, EAGER_BRACE, EAGER_BINARY, CALLABLE)?;
600
601 expr = Expr::Assign(ast::ExprAssign {
602 attributes: expr.take_attributes(),
603 lhs: Box::try_new(expr)?,
604 eq,
605 rhs: Box::try_new(rhs)?,
606 });
607 }
608 K![.] => {
609 match p.nth(1)? {
610 K![await] => {
612 expr = Expr::Await(ast::ExprAwait {
613 attributes: expr.take_attributes(),
614 expr: Box::try_new(expr)?,
615 dot: p.parse()?,
616 await_token: p.parse()?,
617 });
618 }
619 K![ident] => {
621 expr = Expr::FieldAccess(ast::ExprFieldAccess {
622 attributes: expr.take_attributes(),
623 expr: Box::try_new(expr)?,
624 dot: p.parse()?,
625 expr_field: ast::ExprField::Path(p.parse()?),
626 });
627 }
628 K![number] => {
630 expr = Expr::FieldAccess(ast::ExprFieldAccess {
631 attributes: expr.take_attributes(),
632 expr: Box::try_new(expr)?,
633 dot: p.parse()?,
634 expr_field: ast::ExprField::LitNumber(p.parse()?),
635 });
636 }
637 _ => {
638 return Err(compile::Error::new(p.span(0..1), ErrorKind::BadFieldAccess));
639 }
640 }
641 }
642 _ => break,
643 }
644 }
645
646 Ok(expr)
647}
648
649fn binary(
651 p: &mut Parser<'_>,
652 mut lhs: Expr,
653 mut lookahead: Option<ast::BinOp>,
654 min_precedence: usize,
655 eager_brace: EagerBrace,
656) -> Result<Expr> {
657 while let Some(op) = lookahead {
658 let precedence = op.precedence();
659
660 if precedence < min_precedence {
661 break;
662 }
663
664 op.advance(p)?;
665
666 match op {
667 ast::BinOp::DotDot(token) => {
668 lhs = range(
669 p,
670 lhs.take_attributes(),
671 Some(Box::try_new(lhs)?),
672 ast::ExprRangeLimits::HalfOpen(token),
673 eager_brace,
674 )?;
675 lookahead = ast::BinOp::from_peeker(p.peeker());
676 continue;
677 }
678 ast::BinOp::DotDotEq(token) => {
679 lhs = range(
680 p,
681 lhs.take_attributes(),
682 Some(Box::try_new(lhs)?),
683 ast::ExprRangeLimits::Closed(token),
684 eager_brace,
685 )?;
686 lookahead = ast::BinOp::from_peeker(p.peeker());
687 continue;
688 }
689 _ => (),
690 }
691
692 let mut rhs = primary(p, &mut Vec::new(), eager_brace, CALLABLE)?;
693 lookahead = ast::BinOp::from_peeker(p.peeker());
694
695 while let Some(next) = lookahead {
696 match (precedence, next.precedence()) {
697 (lh, rh) if lh < rh => {
698 rhs = binary(p, rhs, Some(next), lh + 1, eager_brace)?;
700 lookahead = ast::BinOp::from_peeker(p.peeker());
701 continue;
702 }
703 (lh, rh) if lh == rh => {
704 if !next.is_assoc() {
705 return Err(compile::Error::new(
706 lhs.span().join(rhs.span()),
707 ErrorKind::PrecedenceGroupRequired,
708 ));
709 }
710 }
711 _ => {}
712 };
713
714 break;
715 }
716
717 lhs = Expr::Binary(ast::ExprBinary {
718 attributes: lhs.take_attributes(),
719 lhs: Box::try_new(lhs)?,
720 op,
721 rhs: Box::try_new(rhs)?,
722 });
723 }
724
725 Ok(lhs)
726}
727
728fn range(
730 p: &mut Parser<'_>,
731 attributes: Vec<ast::Attribute>,
732 from: Option<Box<Expr>>,
733 limits: ast::ExprRangeLimits,
734 eager_brace: EagerBrace,
735) -> Result<Expr> {
736 let to = if Expr::peek_with_brace(p.peeker(), eager_brace) {
737 Some(Box::try_new(Expr::parse_with(
738 p,
739 eager_brace,
740 EAGER_BINARY,
741 CALLABLE,
742 )?)?)
743 } else {
744 None
745 };
746
747 Ok(Expr::Range(ast::ExprRange {
748 attributes,
749 start: from,
750 limits,
751 end: to,
752 }))
753}
754
755fn empty_group(p: &mut Parser<'_>, attributes: Vec<ast::Attribute>) -> Result<Expr> {
757 let open = p.parse::<ast::OpenEmpty>()?;
758 let expr = p.parse::<Expr>()?;
759 let close = p.parse::<ast::CloseEmpty>()?;
760
761 Ok(Expr::Empty(ast::ExprEmpty {
762 attributes,
763 open,
764 expr: Box::try_new(expr)?,
765 close,
766 }))
767}
768
769fn paren_group(p: &mut Parser<'_>, attributes: Vec<ast::Attribute>) -> Result<Expr> {
771 if let (K!['('], K![')']) = (p.nth(0)?, p.nth(1)?) {
773 return Ok(Expr::Tuple(ast::ExprTuple::parse_with_meta(p, attributes)?));
774 }
775
776 let open = p.parse::<T!['(']>()?;
777 let expr = p.parse::<Expr>()?;
778
779 if p.peek::<T![')']>()? {
781 return Ok(Expr::Group(ast::ExprGroup {
782 attributes,
783 open,
784 expr: Box::try_new(expr)?,
785 close: p.parse()?,
786 }));
787 }
788
789 Ok(Expr::Tuple(ast::ExprTuple::parse_from_first_expr(
792 p, attributes, open, expr,
793 )?))
794}