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