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 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#[allow(clippy::large_enum_variant)]
164enum StmtOrTail<'a> {
165 Stmt(Statement),
167 Tail(Box<Expr>, ParserConsumed<'a>),
169}
170
171fn parse_stmt<'a>(parser: &mut Parser<'a, '_>) -> ParseResult<StmtOrTail<'a>> {
173 let stmt = |s| Ok(StmtOrTail::Stmt(s));
174
175 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 if let Some(item) = parser.guarded_parse::<LetToken, StatementLet>()? {
200 return stmt(Statement::Let(item));
201 }
202
203 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 if let Some(consumed) = parser.check_empty() {
214 return Ok(StmtOrTail::Tail(Box::new(expr), consumed));
215 }
216
217 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
260fn 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)] 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 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 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 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 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
633fn 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 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 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}