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