sway_parse/expr/
mod.rs

1use crate::{Parse, ParseBracket, ParseResult, ParseToEnd, Parser, ParserConsumed, Peek};
2
3use sway_ast::brackets::{Braces, Parens, SquareBrackets};
4use sway_ast::expr::{LoopControlFlow, ReassignmentOp, ReassignmentOpVariant};
5use sway_ast::keywords::{
6    AbiToken, AddEqToken, AmpersandToken, AsmToken, CommaToken, ConfigurableToken, ConstToken,
7    DivEqToken, DoubleColonToken, EnumToken, EqToken, FalseToken, FnToken, HashToken, IfToken,
8    ImplToken, LetToken, MutToken, OpenAngleBracketToken, PubToken, SemicolonToken, ShlEqToken,
9    ShrEqToken, StarEqToken, StorageToken, StructToken, SubEqToken, TraitToken, TrueToken,
10    TypeToken, UseToken,
11};
12use sway_ast::literal::{LitBool, LitBoolType};
13use sway_ast::punctuated::Punctuated;
14use sway_ast::token::DocComment;
15use sway_ast::{
16    AbiCastArgs, CodeBlockContents, Expr, ExprArrayDescriptor, ExprStructField,
17    ExprTupleDescriptor, GenericArgs, IfCondition, IfExpr, LitInt, Literal, MatchBranch,
18    MatchBranchKind, PathExpr, PathExprSegment, Statement, StatementLet,
19};
20use sway_error::parser_error::ParseErrorKind;
21use sway_types::{ast::Delimiter, Ident, Span, Spanned};
22
23mod asm;
24pub mod op_code;
25
26impl ParseToEnd for AbiCastArgs {
27    fn parse_to_end<'a, 'e>(
28        mut parser: Parser<'a, '_>,
29    ) -> ParseResult<(AbiCastArgs, ParserConsumed<'a>)> {
30        let name = parser.parse()?;
31        let comma_token = parser.parse()?;
32        let address = parser.parse()?;
33        match parser.check_empty() {
34            Some(consumed) => {
35                let abi_cast_args = AbiCastArgs {
36                    name,
37                    comma_token,
38                    address,
39                };
40                Ok((abi_cast_args, consumed))
41            }
42            None => Err(parser.emit_error(ParseErrorKind::UnexpectedTokenAfterAbiAddress)),
43        }
44    }
45}
46
47impl Parse for IfExpr {
48    fn parse(parser: &mut Parser) -> ParseResult<IfExpr> {
49        let if_token = parser.parse()?;
50        let condition = parser.parse()?;
51        let then_block = parser.parse()?;
52        let else_opt = match parser.take() {
53            Some(else_token) => {
54                let else_body = match parser.guarded_parse::<IfToken, _>()? {
55                    Some(if_expr) => LoopControlFlow::Continue(Box::new(if_expr)),
56                    None => LoopControlFlow::Break(parser.parse()?),
57                };
58                Some((else_token, else_body))
59            }
60            None => None,
61        };
62        Ok(IfExpr {
63            if_token,
64            condition,
65            then_block,
66            else_opt,
67        })
68    }
69}
70
71impl Parse for IfCondition {
72    fn parse(parser: &mut Parser) -> ParseResult<IfCondition> {
73        if let Some(let_token) = parser.take() {
74            let lhs = parser.parse()?;
75            let eq_token = parser.parse()?;
76            let rhs = Box::new(parse_condition(parser)?);
77            Ok(IfCondition::Let {
78                let_token,
79                lhs,
80                eq_token,
81                rhs,
82            })
83        } else {
84            let expr = Box::new(parse_condition(parser)?);
85            Ok(IfCondition::Expr(expr))
86        }
87    }
88}
89
90impl Parse for Expr {
91    fn parse(parser: &mut Parser) -> ParseResult<Expr> {
92        parse_reassignment(parser, ParseExprCtx::default())
93    }
94}
95
96impl Parse for StatementLet {
97    fn parse(parser: &mut Parser) -> ParseResult<Self> {
98        let let_token: LetToken = parser.parse()?;
99
100        if parser.peek::<EqToken>().is_some() {
101            return Err(parser.emit_error_with_span(
102                ParseErrorKind::ExpectedPattern,
103                let_token
104                    .span()
105                    .next_char_utf8()
106                    .unwrap_or_else(|| let_token.span()),
107            ));
108        }
109        let pattern = parser.try_parse(true)?;
110
111        let ty_opt = match parser.take() {
112            Some(colon_token) => Some((colon_token, parser.parse()?)),
113            None => None,
114        };
115        let eq_token: EqToken = parser.try_parse(true)?;
116        let expr = parser.try_parse(true)?;
117
118        // Recover on missing semicolon.
119        let semicolon_token = parser.try_parse(true)?;
120
121        Ok(StatementLet {
122            let_token,
123            pattern,
124            ty_opt,
125            eq_token,
126            expr,
127            semicolon_token,
128        })
129    }
130}
131
132impl ParseToEnd for CodeBlockContents {
133    fn parse_to_end<'a, 'e>(
134        mut parser: Parser<'a, '_>,
135    ) -> ParseResult<(CodeBlockContents, ParserConsumed<'a>)> {
136        let mut statements = Vec::new();
137
138        let (final_expr_opt, consumed) = loop {
139            if let Some(consumed) = parser.check_empty() {
140                break (None, consumed);
141            }
142
143            match parser.call_parsing_function_with_recovery(parse_stmt) {
144                Ok(StmtOrTail::Stmt(s)) => statements.push(s),
145                Ok(StmtOrTail::Tail(e, c)) => break (Some(e), c),
146                Err(r) => {
147                    let (spans, error) = r
148                        .recover_at_next_line_with_fallback_error(ParseErrorKind::InvalidStatement);
149                    statements.push(Statement::Error(spans, error));
150                }
151            }
152        };
153
154        let code_block_contents = CodeBlockContents {
155            statements,
156            final_expr_opt,
157            span: parser.full_span().clone(),
158        };
159
160        Ok((code_block_contents, consumed))
161    }
162}
163
164/// A statement or a tail expression in a block.
165#[allow(clippy::large_enum_variant)]
166enum StmtOrTail<'a> {
167    /// A statement.
168    Stmt(Statement),
169    /// Tail expression in a block.
170    Tail(Box<Expr>, ParserConsumed<'a>),
171}
172
173/// Parses either a statement or a tail expression.
174fn parse_stmt<'a>(parser: &mut Parser<'a, '_>) -> ParseResult<StmtOrTail<'a>> {
175    let stmt = |s| Ok(StmtOrTail::Stmt(s));
176
177    // Try parsing an item as a statement.
178    if parser.peek::<UseToken>().is_some()
179        || parser.peek::<StructToken>().is_some()
180        || parser.peek::<EnumToken>().is_some()
181        || parser.peek::<FnToken>().is_some()
182        || parser.peek::<PubToken>().is_some()
183        || parser.peek::<TraitToken>().is_some()
184        || parser.peek::<ImplToken>().is_some()
185        || parser.peek::<(AbiToken, Ident)>().is_some()
186        || parser.peek::<ConstToken>().is_some()
187        || parser.peek::<TypeToken>().is_some()
188        || parser.peek::<DocComment>().is_some()
189        || parser.peek::<HashToken>().is_some()
190        || matches!(
191            parser.peek::<(StorageToken, Delimiter)>(),
192            Some((_, Delimiter::Brace))
193        )
194        || matches!(
195            parser.peek::<(ConfigurableToken, Delimiter)>(),
196            Some((_, Delimiter::Brace))
197        )
198    {
199        return stmt(Statement::Item(parser.parse()?));
200    }
201
202    // Try a `let` statement.
203    if let Some(item) = parser.guarded_parse::<LetToken, StatementLet>()? {
204        return stmt(Statement::Let(item));
205    }
206
207    // Try an `expr;` statement.
208    let expr = parse_statement_expr(parser)?;
209    if let Some(semicolon_token) = parser.take() {
210        return stmt(Statement::Expr {
211            expr,
212            semicolon_token_opt: Some(semicolon_token),
213        });
214    }
215
216    // Reached EOF? Then an expression is a statement.
217    if let Some(consumed) = parser.check_empty() {
218        return Ok(StmtOrTail::Tail(Box::new(expr), consumed));
219    }
220
221    // For statements like `if`,
222    // they don't need to be terminated by `;` to be statements.
223    if expr.is_control_flow() {
224        return stmt(Statement::Expr {
225            expr,
226            semicolon_token_opt: None,
227        });
228    }
229
230    Err(parser.emit_error(ParseErrorKind::UnexpectedTokenInStatement))
231}
232
233#[derive(Clone, Copy, Debug, Default)]
234struct ParseExprCtx {
235    pub parsing_conditional: bool,
236    pub at_start_of_statement: bool,
237}
238
239impl ParseExprCtx {
240    pub fn not_statement(self) -> ParseExprCtx {
241        ParseExprCtx {
242            at_start_of_statement: false,
243            ..self
244        }
245    }
246}
247
248fn parse_condition(parser: &mut Parser) -> ParseResult<Expr> {
249    let ctx = ParseExprCtx {
250        parsing_conditional: true,
251        at_start_of_statement: false,
252    };
253    parse_reassignment(parser, ctx)
254}
255
256fn parse_statement_expr(parser: &mut Parser) -> ParseResult<Expr> {
257    let ctx = ParseExprCtx {
258        parsing_conditional: false,
259        at_start_of_statement: true,
260    };
261    parse_reassignment(parser, ctx)
262}
263
264/// Eats a `ReassignmentOp`, if any, from `parser`.
265fn take_reassignment_op(parser: &mut Parser) -> Option<ReassignmentOp> {
266    let (variant, span) = if let Some(add_eq_token) = parser.take::<AddEqToken>() {
267        (ReassignmentOpVariant::AddEquals, add_eq_token.span())
268    } else if let Some(sub_eq_token) = parser.take::<SubEqToken>() {
269        (ReassignmentOpVariant::SubEquals, sub_eq_token.span())
270    } else if let Some(mul_eq_token) = parser.take::<StarEqToken>() {
271        (ReassignmentOpVariant::MulEquals, mul_eq_token.span())
272    } else if let Some(div_eq_token) = parser.take::<DivEqToken>() {
273        (ReassignmentOpVariant::DivEquals, div_eq_token.span())
274    } else if let Some(shl_eq_token) = parser.take::<ShlEqToken>() {
275        (ReassignmentOpVariant::ShlEquals, shl_eq_token.span())
276    } else if let Some(shr_eq_token) = parser.take::<ShrEqToken>() {
277        (ReassignmentOpVariant::ShrEquals, shr_eq_token.span())
278    } else if let Some(eq_token) = parser.take::<EqToken>() {
279        (ReassignmentOpVariant::Equals, eq_token.span())
280    } else {
281        return None;
282    };
283    Some(ReassignmentOp { variant, span })
284}
285
286fn parse_reassignment(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
287    let expr = parse_logical_or(parser, ctx)?;
288    let expr_span = expr.span();
289
290    if let Some(reassignment_op) = take_reassignment_op(parser) {
291        let assignable = match expr.try_into_assignable() {
292            Ok(assignable) => assignable,
293            Err(expr) => {
294                let span = expr.span();
295                return Err(parser.emit_error_with_span(
296                    ParseErrorKind::UnassignableExpression {
297                        erroneous_expression_kind: expr.friendly_name(),
298                        erroneous_expression_span: span,
299                    },
300                    expr_span,
301                ));
302            }
303        };
304        let expr = Box::new(parse_reassignment(parser, ctx.not_statement())?);
305        return Ok(Expr::Reassignment {
306            assignable,
307            reassignment_op,
308            expr,
309        });
310    }
311    Ok(expr)
312}
313
314fn parse_op_rhs<O: Peek>(
315    parser: &mut Parser,
316    ctx: ParseExprCtx,
317    sub: impl Fn(&mut Parser, ParseExprCtx) -> ParseResult<Expr>,
318) -> ParseResult<Option<(O, Box<Expr>)>> {
319    if let Some(op_token) = parser.take() {
320        let rhs = Box::new(sub(parser, ctx.not_statement())?);
321        return Ok(Some((op_token, rhs)));
322    }
323    Ok(None)
324}
325
326fn parse_binary<O: Peek>(
327    parser: &mut Parser,
328    ctx: ParseExprCtx,
329    sub: impl Fn(&mut Parser, ParseExprCtx) -> ParseResult<Expr>,
330    combine: impl Fn(Box<Expr>, Box<Expr>, O) -> Expr,
331) -> ParseResult<Expr> {
332    let mut expr = sub(parser, ctx)?;
333    if expr.is_control_flow() && ctx.at_start_of_statement {
334        return Ok(expr);
335    }
336    while let Some((op_token, rhs)) = parse_op_rhs(parser, ctx, &sub)? {
337        expr = combine(Box::new(expr), rhs, op_token);
338    }
339    Ok(expr)
340}
341
342fn parse_logical_or(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
343    let combine = |lhs, rhs, double_pipe_token| Expr::LogicalOr {
344        lhs,
345        double_pipe_token,
346        rhs,
347    };
348    parse_binary(parser, ctx, parse_logical_and, combine)
349}
350
351fn parse_logical_and(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
352    let combine = |lhs, rhs, double_ampersand_token| Expr::LogicalAnd {
353        lhs,
354        double_ampersand_token,
355        rhs,
356    };
357    parse_binary(parser, ctx, parse_comparison, combine)
358}
359
360fn parse_comparison(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
361    let expr = parse_bit_or(parser, ctx)?;
362    let expr = if expr.is_control_flow() && ctx.at_start_of_statement {
363        expr
364    } else if let Some((double_eq_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
365        Expr::Equal {
366            lhs: Box::new(expr),
367            double_eq_token,
368            rhs,
369        }
370    } else if let Some((bang_eq_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
371        Expr::NotEqual {
372            lhs: Box::new(expr),
373            bang_eq_token,
374            rhs,
375        }
376    } else if let Some((less_than_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
377        Expr::LessThan {
378            lhs: Box::new(expr),
379            less_than_token,
380            rhs,
381        }
382    } else if let Some((greater_than_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
383        Expr::GreaterThan {
384            lhs: Box::new(expr),
385            greater_than_token,
386            rhs,
387        }
388    } else if let Some((less_than_eq_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
389        Expr::LessThanEq {
390            lhs: Box::new(expr),
391            less_than_eq_token,
392            rhs,
393        }
394    } else if let Some((greater_than_eq_token, rhs)) = parse_op_rhs(parser, ctx, parse_bit_or)? {
395        Expr::GreaterThanEq {
396            lhs: Box::new(expr),
397            greater_than_eq_token,
398            rhs,
399        }
400    } else {
401        expr
402    };
403    Ok(expr)
404}
405
406fn parse_bit_or(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
407    let combine = |lhs, rhs, pipe_token| Expr::BitOr {
408        lhs,
409        pipe_token,
410        rhs,
411    };
412    parse_binary(parser, ctx, parse_bit_xor, combine)
413}
414
415fn parse_bit_xor(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
416    let combine = |lhs, rhs, caret_token| Expr::BitXor {
417        lhs,
418        caret_token,
419        rhs,
420    };
421    parse_binary(parser, ctx, parse_bit_and, combine)
422}
423
424fn parse_bit_and(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
425    let combine = |lhs, rhs, ampersand_token| Expr::BitAnd {
426        lhs,
427        ampersand_token,
428        rhs,
429    };
430    parse_binary(parser, ctx, parse_shift, combine)
431}
432
433fn parse_shift(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
434    let mut expr = parse_add(parser, ctx)?;
435    if expr.is_control_flow() && ctx.at_start_of_statement {
436        return Ok(expr);
437    }
438    loop {
439        expr = if let Some((shl_token, rhs)) = parse_op_rhs(parser, ctx, parse_add)? {
440            Expr::Shl {
441                lhs: Box::new(expr),
442                shl_token,
443                rhs,
444            }
445        } else if let Some((shr_token, rhs)) = parse_op_rhs(parser, ctx, parse_add)? {
446            Expr::Shr {
447                lhs: Box::new(expr),
448                shr_token,
449                rhs,
450            }
451        } else {
452            return Ok(expr);
453        };
454    }
455}
456
457fn parse_add(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
458    let mut expr = parse_mul(parser, ctx)?;
459    if expr.is_control_flow() && ctx.at_start_of_statement {
460        return Ok(expr);
461    }
462    loop {
463        expr = if let Some((add_token, rhs)) = parse_op_rhs(parser, ctx, parse_mul)? {
464            Expr::Add {
465                lhs: Box::new(expr),
466                add_token,
467                rhs,
468            }
469        } else if let Some((sub_token, rhs)) = parse_op_rhs(parser, ctx, parse_mul)? {
470            Expr::Sub {
471                lhs: Box::new(expr),
472                sub_token,
473                rhs,
474            }
475        } else {
476            return Ok(expr);
477        };
478    }
479}
480
481fn parse_mul(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
482    let mut expr = parse_unary_op(parser, ctx)?;
483    if expr.is_control_flow() && ctx.at_start_of_statement {
484        return Ok(expr);
485    }
486    loop {
487        expr = if let Some((double_star_token, rhs)) = parse_op_rhs(parser, ctx, parse_unary_op)? {
488            Expr::Pow {
489                lhs: Box::new(expr),
490                double_star_token,
491                rhs,
492            }
493        } else if let Some((star_token, rhs)) = parse_op_rhs(parser, ctx, parse_unary_op)? {
494            Expr::Mul {
495                lhs: Box::new(expr),
496                star_token,
497                rhs,
498            }
499        } else if let Some((forward_slash_token, rhs)) = parse_op_rhs(parser, ctx, parse_unary_op)?
500        {
501            Expr::Div {
502                lhs: Box::new(expr),
503                forward_slash_token,
504                rhs,
505            }
506        } else if let Some((percent_token, rhs)) = parse_op_rhs(parser, ctx, parse_unary_op)? {
507            Expr::Modulo {
508                lhs: Box::new(expr),
509                percent_token,
510                rhs,
511            }
512        } else {
513            return Ok(expr);
514        };
515    }
516}
517
518fn parse_unary_op(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
519    if let Some((ampersand_token, mut_token, expr)) = parse_referencing(parser, ctx)? {
520        return Ok(Expr::Ref {
521            ampersand_token,
522            mut_token,
523            expr,
524        });
525    }
526    if let Some((star_token, expr)) = parse_op_rhs(parser, ctx, parse_unary_op)? {
527        return Ok(Expr::Deref { star_token, expr });
528    }
529    if let Some((bang_token, expr)) = parse_op_rhs(parser, ctx, parse_unary_op)? {
530        return Ok(Expr::Not { bang_token, expr });
531    }
532    return parse_projection(parser, ctx);
533
534    #[allow(clippy::type_complexity)] // Used just here for getting the three parsed elements.
535    fn parse_referencing(
536        parser: &mut Parser,
537        ctx: ParseExprCtx,
538    ) -> ParseResult<Option<(AmpersandToken, Option<MutToken>, Box<Expr>)>> {
539        if let Some(ampersand_token) = parser.take() {
540            let mut_token = parser.take::<MutToken>();
541            let expr = Box::new(parse_unary_op(parser, ctx.not_statement())?);
542            return Ok(Some((ampersand_token, mut_token, expr)));
543        }
544        Ok(None)
545    }
546}
547
548fn parse_projection(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
549    let mut expr = parse_func_app(parser, ctx)?;
550    loop {
551        if let Some(arg) = SquareBrackets::try_parse_all_inner(parser, |mut parser| {
552            parser.emit_error(ParseErrorKind::UnexpectedTokenAfterArrayIndex)
553        })? {
554            let target = Box::new(expr);
555            expr = Expr::Index { target, arg };
556            continue;
557        }
558        if let Some(dot_token) = parser.take() {
559            let target = Box::new(expr);
560
561            // Try parsing a field access or a method call.
562            if let Some(path_seg) = parser.guarded_parse::<Ident, PathExprSegment>()? {
563                if !ctx.parsing_conditional {
564                    if let Some(contract_args) = Braces::try_parse(parser)? {
565                        expr = Expr::MethodCall {
566                            target,
567                            dot_token,
568                            path_seg,
569                            contract_args_opt: Some(contract_args),
570                            args: Parens::parse(parser)?,
571                        };
572                        continue;
573                    }
574                }
575                if let Some(args) = Parens::try_parse(parser)? {
576                    expr = Expr::MethodCall {
577                        target,
578                        dot_token,
579                        path_seg,
580                        contract_args_opt: None,
581                        args,
582                    };
583                    continue;
584                }
585
586                // No arguments, so this is a field projection.
587                ensure_field_projection_no_generics(parser, &path_seg.generics_opt);
588                expr = Expr::FieldProjection {
589                    target,
590                    dot_token,
591                    name: path_seg.name,
592                };
593                continue;
594            }
595
596            // Try parsing a tuple field projection.
597            if let Some(lit) = parser.take() {
598                let lit_int = match lit {
599                    Literal::Int(lit_int) => lit_int,
600                    _ => {
601                        let span = lit.span();
602                        return Err(parser
603                            .emit_error_with_span(ParseErrorKind::InvalidLiteralFieldName, span));
604                    }
605                };
606                let LitInt {
607                    span,
608                    parsed,
609                    ty_opt,
610                    is_generated_b256: _,
611                } = lit_int;
612                if ty_opt.is_some() {
613                    return Err(
614                        parser.emit_error_with_span(ParseErrorKind::IntFieldWithTypeSuffix, span)
615                    );
616                }
617                let field = parsed;
618                let field_span = span;
619                expr = Expr::TupleFieldProjection {
620                    target,
621                    dot_token,
622                    field,
623                    field_span,
624                };
625                continue;
626            }
627
628            // Nothing expected followed. Now we have parsed `expr .`.
629            // Try to recover as an unknown sort of expression.
630            let err = parser.emit_error(ParseErrorKind::ExpectedFieldName);
631            return Ok(Expr::Error([target.span(), dot_token.span()].into(), err));
632        }
633        return Ok(expr);
634    }
635}
636
637/// Ensure we don't have `foo.bar::<...>` where `bar` isn't a method call.
638fn ensure_field_projection_no_generics(
639    parser: &mut Parser,
640    generic_args: &Option<(DoubleColonToken, GenericArgs)>,
641) {
642    if let Some((dct, generic_args)) = generic_args {
643        let span = Span::join(dct.span(), &generic_args.span());
644        parser.emit_error_with_span(ParseErrorKind::FieldProjectionWithGenericArgs, span);
645    }
646}
647
648fn parse_func_app(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
649    let mut expr = parse_atom(parser, ctx)?;
650    if expr.is_control_flow() && ctx.at_start_of_statement {
651        return Ok(expr);
652    }
653    while let Some(args) = Parens::try_parse(parser)? {
654        let func = Box::new(expr);
655        expr = Expr::FuncApp { func, args };
656    }
657    Ok(expr)
658}
659
660fn parse_atom(parser: &mut Parser, ctx: ParseExprCtx) -> ParseResult<Expr> {
661    if let Some(code_block_inner) = Braces::try_parse(parser)? {
662        return Ok(Expr::Block(code_block_inner));
663    }
664    if let Some(array_inner) = SquareBrackets::try_parse(parser)? {
665        return Ok(Expr::Array(array_inner));
666    }
667    if let Some((mut parser, span)) = parser.enter_delimited(Delimiter::Parenthesis) {
668        if let Some(_consumed) = parser.check_empty() {
669            return Ok(Expr::Tuple(Parens::new(ExprTupleDescriptor::Nil, span)));
670        }
671        let head = parser.parse()?;
672        if let Some(comma_token) = parser.take() {
673            let (tail, _consumed) = parser.parse_to_end()?;
674            let tuple = ExprTupleDescriptor::Cons {
675                head,
676                comma_token,
677                tail,
678            };
679            return Ok(Expr::Tuple(Parens::new(tuple, span)));
680        }
681        if let Some(_consumed) = parser.check_empty() {
682            return Ok(Expr::Parens(Parens::new(head, span)));
683        }
684        return Err(
685            parser.emit_error(ParseErrorKind::ExpectedCommaOrCloseParenInTupleOrParenExpression)
686        );
687    }
688
689    let lit_bool = |span, kind| Ok(Expr::Literal(Literal::Bool(LitBool { span, kind })));
690    if let Some(ident) = parser.take::<TrueToken>() {
691        return lit_bool(ident.span(), LitBoolType::True);
692    }
693    if let Some(ident) = parser.take::<FalseToken>() {
694        return lit_bool(ident.span(), LitBoolType::False);
695    }
696    if let Some(asm_block) = parser.guarded_parse::<AsmToken, _>()? {
697        return Ok(Expr::Asm(asm_block));
698    }
699    if let Some(break_token) = parser.take() {
700        return Ok(Expr::Break { break_token });
701    }
702    if let Some(continue_token) = parser.take() {
703        return Ok(Expr::Continue { continue_token });
704    }
705    if let Some(abi_token) = parser.take() {
706        let args = parser.parse()?;
707        return Ok(Expr::AbiCast { abi_token, args });
708    }
709    if let Some(return_token) = parser.take() {
710        if parser.is_empty()
711            || parser.peek::<CommaToken>().is_some()
712            || parser.peek::<SemicolonToken>().is_some()
713        {
714            return Ok(Expr::Return {
715                return_token,
716                expr_opt: None,
717            });
718        }
719        let expr = parser.parse()?;
720        return Ok(Expr::Return {
721            return_token,
722            expr_opt: Some(expr),
723        });
724    }
725    if let Some(panic_token) = parser.take() {
726        if parser.is_empty()
727            || parser.peek::<CommaToken>().is_some()
728            || parser.peek::<SemicolonToken>().is_some()
729        {
730            return Ok(Expr::Panic {
731                panic_token,
732                expr_opt: None,
733            });
734        }
735        let expr = parser.parse()?;
736        return Ok(Expr::Panic {
737            panic_token,
738            expr_opt: Some(expr),
739        });
740    }
741    if let Some(if_expr) = parser.guarded_parse::<IfToken, _>()? {
742        return Ok(Expr::If(if_expr));
743    }
744    if let Some(match_token) = parser.take() {
745        let condition = Box::new(parse_condition(parser)?);
746        let branches = parser.parse()?;
747        return Ok(Expr::Match {
748            match_token,
749            value: condition,
750            branches,
751        });
752    }
753    if let Some(while_token) = parser.take() {
754        let condition = Box::new(parse_condition(parser)?);
755        let block = parser.parse()?;
756        return Ok(Expr::While {
757            while_token,
758            condition,
759            block,
760        });
761    }
762    if let Some(for_token) = parser.take() {
763        let value_pattern = parser.parse()?;
764        let in_token = parser.parse()?;
765        let iterator = Box::new(parse_condition(parser)?);
766        let block = parser.parse()?;
767        return Ok(Expr::For {
768            for_token,
769            value_pattern,
770            in_token,
771            iterator,
772            block,
773        });
774    }
775    if parser.peek::<OpenAngleBracketToken>().is_some()
776        || parser.peek::<DoubleColonToken>().is_some()
777        || parser.peek::<Ident>().is_some()
778    {
779        let path: PathExpr = parser.parse()?;
780        if path.incomplete_suffix {
781            // We tried parsing it as a path but we didn't succeed so we try to recover this
782            // as an unknown sort of expression. This happens, for instance, when the user
783            // types `foo::`
784            return Ok(Expr::Error(
785                [path.span()].into(),
786                parser.emit_error(ParseErrorKind::ExpectedPathType),
787            ));
788        }
789        if !ctx.parsing_conditional {
790            if let Some(fields) = Braces::try_parse(parser)? {
791                return Ok(Expr::Struct { path, fields });
792            }
793        };
794        return Ok(Expr::Path(path));
795    }
796    if let Some(literal) = parser.take() {
797        return Ok(Expr::Literal(literal));
798    }
799    Err(parser.emit_error(ParseErrorKind::ExpectedExpression))
800}
801
802impl Parse for ExprStructField {
803    fn parse(parser: &mut Parser) -> ParseResult<ExprStructField> {
804        let field_name = parser.parse()?;
805        let expr_opt = match parser.take() {
806            Some(colon_token) => {
807                let expr = parser.parse()?;
808                Some((colon_token, expr))
809            }
810            None => None,
811        };
812        Ok(ExprStructField {
813            field_name,
814            expr_opt,
815        })
816    }
817}
818
819impl ParseToEnd for ExprArrayDescriptor {
820    fn parse_to_end<'a, 'e>(
821        mut parser: Parser<'a, '_>,
822    ) -> ParseResult<(ExprArrayDescriptor, ParserConsumed<'a>)> {
823        if let Some(consumed) = parser.check_empty() {
824            let punctuated = Punctuated::empty();
825            let descriptor = ExprArrayDescriptor::Sequence(punctuated);
826            return Ok((descriptor, consumed));
827        }
828        let value = parser.parse()?;
829        if let Some(semicolon_token) = parser.take() {
830            let length = parser.parse()?;
831            let consumed = match parser.check_empty() {
832                Some(consumed) => consumed,
833                None => {
834                    return Err(parser.emit_error(ParseErrorKind::UnexpectedTokenAfterArrayLength));
835                }
836            };
837            let descriptor = ExprArrayDescriptor::Repeat {
838                value: Box::new(value),
839                semicolon_token,
840                length,
841            };
842            return Ok((descriptor, consumed));
843        }
844        if let Some(comma_token) = parser.take() {
845            let (mut punctuated, consumed): (Punctuated<_, _>, _) = parser.parse_to_end()?;
846            punctuated
847                .value_separator_pairs
848                .insert(0, (value, comma_token));
849            let descriptor = ExprArrayDescriptor::Sequence(punctuated);
850            return Ok((descriptor, consumed));
851        }
852        if let Some(consumed) = parser.check_empty() {
853            let punctuated = Punctuated::single(value);
854            let descriptor = ExprArrayDescriptor::Sequence(punctuated);
855            return Ok((descriptor, consumed));
856        }
857        Err(parser.emit_error(ParseErrorKind::ExpectedCommaSemicolonOrCloseBracketInArray))
858    }
859}
860
861impl Parse for MatchBranch {
862    fn parse(parser: &mut Parser) -> ParseResult<MatchBranch> {
863        let pattern = parser.parse()?;
864        let fat_right_arrow_token = parser.parse()?;
865        let kind = parser.parse()?;
866        Ok(MatchBranch {
867            pattern,
868            fat_right_arrow_token,
869            kind,
870        })
871    }
872}
873
874impl Parse for MatchBranchKind {
875    fn parse(parser: &mut Parser) -> ParseResult<MatchBranchKind> {
876        if let Some(block) = Braces::try_parse(parser)? {
877            return Ok(MatchBranchKind::Block {
878                block,
879                comma_token_opt: parser.take(),
880            });
881        }
882        let expr = parser.parse()?;
883        let comma_token = parser.parse()?;
884        Ok(MatchBranchKind::Expr { expr, comma_token })
885    }
886}