1use swc_common::{BytePos, Span, Spanned};
2use swc_ecma_ast::*;
3
4use super::{
5 buffer::Buffer,
6 class_and_fn::parse_fn_decl,
7 expr::parse_assignment_expr,
8 is_directive::IsDirective,
9 pat::parse_binding_pat_or_ident,
10 typescript::{try_parse_ts_type_ann, ts_look_ahead},
11 PResult, Parser,
12};
13use crate::{
14 common::{
15 context::Context,
16 lexer::token::TokenFactory,
17 parser::{
18 class_and_fn::{parse_async_fn_decl, parse_class_decl, parse_decorators},
19 eof_error,
20 expr::{parse_await_expr, parse_bin_op_recursively, parse_for_head_prefix},
21 ident::{parse_binding_ident, parse_label_ident},
22 pat::reparse_expr_as_pat,
23 pat_type::PatType,
24 typescript::{
25 parse_ts_enum_decl, parse_ts_expr_stmt, parse_ts_interface_decl, parse_ts_type,
26 parse_ts_type_alias_decl,
27 },
28 TokenAndSpan,
29 },
30 },
31 error::{Error, SyntaxError},
32};
33
34#[allow(clippy::enum_variant_names)]
35pub enum TempForHead {
36 For {
37 init: Option<VarDeclOrExpr>,
38 test: Option<Box<Expr>>,
39 update: Option<Box<Expr>>,
40 },
41 ForIn {
42 left: ForHead,
43 right: Box<Expr>,
44 },
45 ForOf {
46 left: ForHead,
47 right: Box<Expr>,
48 },
49}
50
51fn parse_normal_for_head<'a, P: Parser<'a>>(
52 p: &mut P,
53 init: Option<VarDeclOrExpr>,
54) -> PResult<TempForHead> {
55 let test = if p.input_mut().eat(&P::Token::SEMI) {
56 None
57 } else {
58 let test = p.allow_in_expr(|p| p.parse_expr()).map(Some)?;
59 p.input_mut().eat(&P::Token::SEMI);
60 test
61 };
62
63 let update = if p.input().is(&P::Token::RPAREN) {
64 None
65 } else {
66 p.allow_in_expr(|p| p.parse_expr()).map(Some)?
67 };
68
69 Ok(TempForHead::For { init, test, update })
70}
71
72fn parse_for_each_head<'a, P: Parser<'a>>(p: &mut P, left: ForHead) -> PResult<TempForHead> {
73 let is_of = p.input().cur().is_of();
74 p.bump();
75 if is_of {
76 let right = p.allow_in_expr(parse_assignment_expr)?;
77 Ok(TempForHead::ForOf { left, right })
78 } else {
79 if let ForHead::UsingDecl(d) = &left {
80 p.emit_err(d.span, SyntaxError::UsingDeclNotAllowedForForInLoop)
81 }
82 let right = p.allow_in_expr(|p| p.parse_expr())?;
83 Ok(TempForHead::ForIn { left, right })
84 }
85}
86
87pub fn parse_return_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
88 let start = p.cur_pos();
89
90 p.assert_and_bump(&P::Token::RETURN);
91
92 let arg = if p.is_general_semi() {
93 None
94 } else {
95 p.allow_in_expr(|p| p.parse_expr()).map(Some)?
96 };
97 p.expect_general_semi()?;
98 let stmt = Ok(ReturnStmt {
99 span: p.span(start),
100 arg,
101 }
102 .into());
103
104 if !p.ctx().contains(Context::InFunction) && !p.input().syntax().allow_return_outside_function()
105 {
106 p.emit_err(p.span(start), SyntaxError::ReturnNotAllowed);
107 }
108
109 stmt
110}
111
112fn parse_var_declarator<'a, P: Parser<'a>>(
113 p: &mut P,
114 for_loop: bool,
115 kind: VarDeclKind,
116) -> PResult<VarDeclarator> {
117 let start = p.cur_pos();
118
119 let is_let_or_const = matches!(kind, VarDeclKind::Let | VarDeclKind::Const);
120
121 let mut name = parse_binding_pat_or_ident(p, is_let_or_const)?;
122
123 let definite = if p.input().syntax().typescript() {
124 match name {
125 Pat::Ident(..) => p.input_mut().eat(&P::Token::BANG),
126 _ => false,
127 }
128 } else {
129 false
130 };
131
132 if p.input().syntax().typescript() && p.input().is(&P::Token::COLON) {
134 let type_annotation = try_parse_ts_type_ann(p)?;
135 match name {
136 Pat::Array(ArrayPat {
137 ref mut type_ann, ..
138 })
139 | Pat::Ident(BindingIdent {
140 ref mut type_ann, ..
141 })
142 | Pat::Object(ObjectPat {
143 ref mut type_ann, ..
144 })
145 | Pat::Rest(RestPat {
146 ref mut type_ann, ..
147 }) => {
148 *type_ann = type_annotation;
149 }
150 _ => unreachable!("invalid syntax: Pat: {:?}", name),
151 }
152 }
153
154 let cur = p.input().cur();
156 let init = if !for_loop || !(cur.is_in() || cur.is_of()) {
157 if p.input_mut().eat(&P::Token::EQUAL) {
158 let expr = parse_assignment_expr(p)?;
159 let expr = p.verify_expr(expr)?;
160
161 Some(expr)
162 } else {
163 if p.ctx().contains(Context::InDeclare) {
166 None
167 } else if kind == VarDeclKind::Const
168 && !for_loop
169 && !p.ctx().contains(Context::InDeclare)
170 {
171 p.emit_err(
172 p.span(start),
173 SyntaxError::ConstDeclarationsRequireInitialization,
174 );
175
176 None
177 } else {
178 match name {
179 Pat::Ident(..) => None,
180 _ => {
181 syntax_error!(p, p.span(start), SyntaxError::PatVarWithoutInit)
182 }
183 }
184 }
185 }
186 } else {
187 None
189 };
190
191 Ok(VarDeclarator {
192 span: p.span(start),
193 name,
194 init,
195 definite,
196 })
197}
198
199pub fn parse_var_stmt<'a, P: Parser<'a>>(p: &mut P, for_loop: bool) -> PResult<Box<VarDecl>> {
200 let start = p.cur_pos();
201 let t = p.input().cur();
202 let kind = if t.is_const() {
203 VarDeclKind::Const
204 } else if t.is_let() {
205 VarDeclKind::Let
206 } else if t.is_var() {
207 VarDeclKind::Var
208 } else {
209 unreachable!()
210 };
211 p.bump();
212 let var_span = p.span(start);
213 let should_include_in = kind != VarDeclKind::Var || !for_loop;
214
215 if p.syntax().typescript() && for_loop {
216 let cur = p.input().cur();
217 let res: PResult<bool> = if cur.is_in() || cur.is_of() {
218 ts_look_ahead(p, |p| {
219 if !p.input_mut().eat(&P::Token::OF) && !p.input_mut().eat(&P::Token::IN) {
221 return Ok(false);
222 }
223
224 parse_assignment_expr(p)?;
225 expect!(p, &P::Token::RPAREN);
226
227 Ok(true)
228 })
229 } else {
230 Ok(false)
231 };
232
233 match res {
234 Ok(true) => {
235 let pos = var_span.hi();
236 let span = Span::new_with_checked(pos, pos);
237 p.emit_err(span, SyntaxError::TS1123);
238
239 return Ok(Box::new(VarDecl {
240 span: p.span(start),
241 kind,
242 declare: false,
243 decls: Vec::new(),
244 ..Default::default()
245 }));
246 }
247 Err(..) => {}
248 _ => {}
249 }
250 }
251
252 let mut decls = Vec::with_capacity(4);
253 loop {
254 if p.input().is(&P::Token::SEMI) {
259 let prev_span = p.input().prev_span();
260 let span = if prev_span == var_span {
261 Span::new_with_checked(prev_span.hi, prev_span.hi)
262 } else {
263 prev_span
264 };
265 p.emit_err(span, SyntaxError::TS1009);
266 break;
267 }
268
269 let decl = if should_include_in {
270 p.do_inside_of_context(Context::IncludeInExpr, |p| {
271 parse_var_declarator(p, for_loop, kind)
272 })
273 } else {
274 parse_var_declarator(p, for_loop, kind)
275 }?;
276
277 decls.push(decl);
278
279 if !p.input_mut().eat(&P::Token::COMMA) {
280 break;
281 }
282 }
283
284 if !for_loop && !p.eat_general_semi() {
285 p.emit_err(p.input().cur_span(), SyntaxError::TS1005);
286
287 let _ = p.parse_expr();
288
289 while !p.eat_general_semi() {
290 p.bump();
291
292 if p.input().cur().is_error() {
293 break;
294 }
295 }
296 }
297
298 Ok(Box::new(VarDecl {
299 span: p.span(start),
300 declare: false,
301 kind,
302 decls,
303 ..Default::default()
304 }))
305}
306
307pub fn parse_using_decl<'a, P: Parser<'a>>(
308 p: &mut P,
309 start: BytePos,
310 is_await: bool,
311) -> PResult<Option<Box<UsingDecl>>> {
312 if p.input_mut().has_linebreak_between_cur_and_peeked() {
317 return Ok(None);
318 }
319
320 if !p.peek_is_ident_ref() {
321 return Ok(None);
322 }
323
324 p.assert_and_bump(&P::Token::USING);
325
326 let mut decls = Vec::new();
327 loop {
328 if p.input().is(&P::Token::SEMI) {
333 let span = p.input().prev_span();
334 p.emit_err(span, SyntaxError::TS1009);
335 break;
336 }
337
338 decls.push(parse_var_declarator(p, false, VarDeclKind::Var)?);
339 if !p.input_mut().eat(&P::Token::COMMA) {
340 break;
341 }
342 }
343
344 if !p.syntax().explicit_resource_management() {
345 p.emit_err(p.span(start), SyntaxError::UsingDeclNotEnabled);
346 }
347
348 if !p.ctx().contains(Context::AllowUsingDecl) {
349 p.emit_err(p.span(start), SyntaxError::UsingDeclNotAllowed);
350 }
351
352 for decl in &decls {
353 match decl.name {
354 Pat::Ident(..) => {}
355 _ => {
356 p.emit_err(p.span(start), SyntaxError::InvalidNameInUsingDecl);
357 }
358 }
359
360 if decl.init.is_none() {
361 p.emit_err(p.span(start), SyntaxError::InitRequiredForUsingDecl);
362 }
363 }
364
365 p.expect_general_semi()?;
366
367 Ok(Some(Box::new(UsingDecl {
368 span: p.span(start),
369 is_await,
370 decls,
371 })))
372}
373
374pub fn parse_for_head<'a, P: Parser<'a>>(p: &mut P) -> PResult<TempForHead> {
375 let cur = p.input().cur();
378 if cur.is_const()
379 || cur.is_var()
380 || (p.input().is(&P::Token::LET) && peek!(p).map_or(false, |v| v.follows_keyword_let()))
381 {
382 let decl = parse_var_stmt(p, true)?;
383
384 let cur = p.input().cur();
385 if cur.is_of() || cur.is_in() {
386 if decl.decls.len() != 1 {
387 for d in decl.decls.iter().skip(1) {
388 p.emit_err(d.name.span(), SyntaxError::TooManyVarInForInHead);
389 }
390 } else {
391 if (p.ctx().contains(Context::Strict) || p.input().is(&P::Token::OF))
392 && decl.decls[0].init.is_some()
393 {
394 p.emit_err(
395 decl.decls[0].name.span(),
396 SyntaxError::VarInitializerInForInHead,
397 );
398 }
399
400 if p.syntax().typescript() {
401 let type_ann = match decl.decls[0].name {
402 Pat::Ident(ref v) => Some(&v.type_ann),
403 Pat::Array(ref v) => Some(&v.type_ann),
404 Pat::Rest(ref v) => Some(&v.type_ann),
405 Pat::Object(ref v) => Some(&v.type_ann),
406 _ => None,
407 };
408
409 if let Some(type_ann) = type_ann {
410 if type_ann.is_some() {
411 p.emit_err(decl.decls[0].name.span(), SyntaxError::TS2483);
412 }
413 }
414 }
415 }
416
417 return parse_for_each_head(p, ForHead::VarDecl(decl));
418 }
419
420 expect!(p, &P::Token::SEMI);
421 return parse_normal_for_head(p, Some(VarDeclOrExpr::VarDecl(decl)));
422 }
423
424 if p.input_mut().eat(&P::Token::SEMI) {
425 return parse_normal_for_head(p, None);
426 }
427
428 let start = p.cur_pos();
429 let init = p.disallow_in_expr(parse_for_head_prefix)?;
430
431 let mut is_using_decl = false;
432 let mut is_await_using_decl = false;
433
434 if p.input().syntax().explicit_resource_management() {
435 let mut maybe_using_decl = init.is_ident_ref_to("using");
437 let mut maybe_await_using_decl = false;
438
439 if !maybe_using_decl
441 && init
442 .as_await_expr()
443 .filter(|e| e.arg.is_ident_ref_to("using"))
444 .is_some()
445 {
446 maybe_using_decl = true;
447 maybe_await_using_decl = true;
448 }
449
450 if maybe_using_decl
451 && !p.input().is(&P::Token::OF)
452 && (peek!(p).is_some_and(|peek| peek.is_of() || peek.is_in()))
453 {
454 is_using_decl = maybe_using_decl;
455 is_await_using_decl = maybe_await_using_decl;
456 }
457 }
458
459 if is_using_decl {
460 let name = parse_binding_ident(p, false)?;
461 let decl = VarDeclarator {
462 name: name.into(),
463 span: p.span(start),
464 init: None,
465 definite: false,
466 };
467
468 let pat = Box::new(UsingDecl {
469 span: p.span(start),
470 is_await: is_await_using_decl,
471 decls: vec![decl],
472 });
473
474 let cur = p.input().cur();
475 if cur.is_error() {
476 let err = p.input_mut().expect_error_token_and_bump();
477 return Err(err);
478 } else if cur.is_eof() {
479 return Err(eof_error(p));
480 }
481
482 return parse_for_each_head(p, ForHead::UsingDecl(pat));
483 }
484
485 let cur = p.input().cur();
487 if cur.is_of() || cur.is_in() {
488 let is_in = p.input().is(&P::Token::IN);
489
490 let pat = reparse_expr_as_pat(p, PatType::AssignPat, init)?;
491
492 if p.input().syntax().typescript() && is_in {
494 match pat {
495 Pat::Ident(..) => {}
496 Pat::Expr(..) => {}
497 ref v => p.emit_err(v.span(), SyntaxError::TS2491),
498 }
499 }
500
501 return parse_for_each_head(p, ForHead::Pat(Box::new(pat)));
502 }
503
504 expect!(p, &P::Token::SEMI);
505
506 let init = p.verify_expr(init)?;
507 parse_normal_for_head(p, Some(VarDeclOrExpr::Expr(init)))
508}
509
510fn parse_for_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
511 let start = p.cur_pos();
512
513 p.assert_and_bump(&P::Token::FOR);
514 let await_start = p.cur_pos();
515 let await_token = if p.input_mut().eat(&P::Token::AWAIT) {
516 Some(p.span(await_start))
517 } else {
518 None
519 };
520 expect!(p, &P::Token::LPAREN);
521
522 let head = p.do_inside_of_context(Context::ForLoopInit, |p| {
523 if await_token.is_some() {
524 p.do_inside_of_context(Context::ForAwaitLoopInit, parse_for_head)
525 } else {
526 p.do_outside_of_context(Context::ForAwaitLoopInit, parse_for_head)
527 }
528 })?;
529
530 expect!(p, &P::Token::RPAREN);
531
532 let body = p
533 .do_inside_of_context(
534 Context::IsBreakAllowed.union(Context::IsContinueAllowed),
535 |p| p.do_outside_of_context(Context::TopLevel, parse_stmt),
536 )
537 .map(Box::new)?;
538
539 let span = p.span(start);
540 Ok(match head {
541 TempForHead::For { init, test, update } => {
542 if let Some(await_token) = await_token {
543 syntax_error!(p, await_token, SyntaxError::AwaitForStmt);
544 }
545
546 ForStmt {
547 span,
548 init,
549 test,
550 update,
551 body,
552 }
553 .into()
554 }
555 TempForHead::ForIn { left, right } => {
556 if let Some(await_token) = await_token {
557 syntax_error!(p, await_token, SyntaxError::AwaitForStmt);
558 }
559
560 ForInStmt {
561 span,
562 left,
563 right,
564 body,
565 }
566 .into()
567 }
568 TempForHead::ForOf { left, right } => ForOfStmt {
569 span,
570 is_await: await_token.is_some(),
571 left,
572 right,
573 body,
574 }
575 .into(),
576 })
577}
578
579pub fn parse_stmt<'a>(p: &mut impl Parser<'a>) -> PResult<Stmt> {
580 trace_cur!(p, parse_stmt);
581 parse_stmt_like(p, false, handle_import_export)
582}
583
584fn adjust_if_else_clause<'a, P: Parser<'a>>(p: &mut P, cur: &mut IfStmt, alt: Box<Stmt>) {
589 cur.span = p.span(cur.span.lo);
590
591 if let Some(Stmt::If(prev_alt)) = cur.alt.as_deref_mut() {
592 adjust_if_else_clause(p, prev_alt, alt)
593 } else {
594 debug_assert_eq!(cur.alt, None);
595 cur.alt = Some(alt);
596 }
597}
598
599fn parse_if_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<IfStmt> {
600 let start = p.cur_pos();
601
602 p.assert_and_bump(&P::Token::IF);
603 let if_token = p.input().prev_span();
604
605 expect!(p, &P::Token::LPAREN);
606
607 let test = p
608 .do_outside_of_context(Context::IgnoreElseClause, |p| {
609 p.allow_in_expr(|p| p.parse_expr())
610 })
611 .map_err(|err| {
612 Error::new(
613 err.span(),
614 SyntaxError::WithLabel {
615 inner: Box::new(err),
616 span: if_token,
617 note: "Tried to parse the condition for an if statement",
618 },
619 )
620 })?;
621
622 expect!(p, &P::Token::RPAREN);
623
624 let cons = {
625 crate::maybe_grow(256 * 1024, 1024 * 1024, || {
627 p.do_outside_of_context(
632 Context::IgnoreElseClause.union(Context::TopLevel),
633 parse_stmt,
634 )
635 .map(Box::new)
636 })?
637 };
638
639 let alt = if p.ctx().contains(Context::IgnoreElseClause) {
643 None
644 } else {
645 let mut cur = None;
646
647 let last = loop {
648 if !p.input_mut().eat(&P::Token::ELSE) {
649 break None;
650 }
651
652 if !p.input().is(&P::Token::IF) {
653 let last = p.do_outside_of_context(
655 Context::IgnoreElseClause.union(Context::TopLevel),
656 parse_stmt,
657 )?;
658 break Some(last);
659 }
660
661 let alt = p.do_inside_of_context(Context::IgnoreElseClause, parse_if_stmt)?;
664
665 match &mut cur {
666 Some(cur) => {
667 adjust_if_else_clause(p, cur, Box::new(alt.into()));
668 }
669 _ => {
670 cur = Some(alt);
671 }
672 }
673 };
674
675 match cur {
676 Some(mut cur) => {
677 if let Some(last) = last {
678 adjust_if_else_clause(p, &mut cur, Box::new(last));
679 }
680 Some(cur.into())
681 }
682 _ => last,
683 }
684 }
685 .map(Box::new);
686
687 let span = p.span(start);
688 Ok(IfStmt {
689 span,
690 test,
691 cons,
692 alt,
693 })
694}
695
696fn parse_throw_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
697 let start = p.cur_pos();
698
699 p.assert_and_bump(&P::Token::THROW);
700
701 if p.input().had_line_break_before_cur() {
702 syntax_error!(p, SyntaxError::LineBreakInThrow);
704 }
705
706 let arg = p.allow_in_expr(|p| p.parse_expr())?;
707 p.expect_general_semi()?;
708
709 let span = p.span(start);
710 Ok(ThrowStmt { span, arg }.into())
711}
712
713fn parse_with_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
714 if p.syntax().typescript() {
715 let span = p.input().cur_span();
716 p.emit_err(span, SyntaxError::TS2410);
717 }
718
719 {
720 let span = p.input().cur_span();
721 p.emit_strict_mode_err(span, SyntaxError::WithInStrict);
722 }
723
724 let start = p.cur_pos();
725
726 p.assert_and_bump(&P::Token::WITH);
727
728 expect!(p, &P::Token::LPAREN);
729 let obj = p.allow_in_expr(|p| p.parse_expr())?;
730 expect!(p, &P::Token::RPAREN);
731
732 let body = p
733 .do_inside_of_context(Context::InFunction, |p| {
734 p.do_outside_of_context(Context::TopLevel, parse_stmt)
735 })
736 .map(Box::new)?;
737
738 let span = p.span(start);
739 Ok(WithStmt { span, obj, body }.into())
740}
741
742fn parse_while_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
743 let start = p.cur_pos();
744
745 p.assert_and_bump(&P::Token::WHILE);
746
747 expect!(p, &P::Token::LPAREN);
748 let test = p.allow_in_expr(|p| p.parse_expr())?;
749 expect!(p, &P::Token::RPAREN);
750
751 let body = p
752 .do_inside_of_context(
753 Context::IsBreakAllowed.union(Context::IsContinueAllowed),
754 |p| p.do_outside_of_context(Context::TopLevel, parse_stmt),
755 )
756 .map(Box::new)?;
757
758 let span = p.span(start);
759 Ok(WhileStmt { span, test, body }.into())
760}
761
762fn parse_catch_param<'a, P: Parser<'a>>(p: &mut P) -> PResult<Option<Pat>> {
764 if p.input_mut().eat(&P::Token::LPAREN) {
765 let mut pat = parse_binding_pat_or_ident(p, false)?;
766
767 let type_ann_start = p.cur_pos();
768
769 if p.syntax().typescript() && p.input_mut().eat(&P::Token::COLON) {
770 let ty = p.do_inside_of_context(Context::InType, parse_ts_type)?;
771 match &mut pat {
774 Pat::Ident(BindingIdent { type_ann, .. })
775 | Pat::Array(ArrayPat { type_ann, .. })
776 | Pat::Rest(RestPat { type_ann, .. })
777 | Pat::Object(ObjectPat { type_ann, .. }) => {
778 *type_ann = Some(Box::new(TsTypeAnn {
779 span: p.span(type_ann_start),
780 type_ann: ty,
781 }));
782 }
783 Pat::Assign(..) => {}
784 Pat::Invalid(_) => {}
785 Pat::Expr(_) => {}
786 }
787 }
788 expect!(p, &P::Token::RPAREN);
789 Ok(Some(pat))
790 } else {
791 Ok(None)
792 }
793}
794
795fn parse_do_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
796 let start = p.cur_pos();
797
798 p.assert_and_bump(&P::Token::DO);
799
800 let body = p
801 .do_inside_of_context(
802 Context::IsBreakAllowed.union(Context::IsContinueAllowed),
803 |p| p.do_outside_of_context(Context::TopLevel, parse_stmt),
804 )
805 .map(Box::new)?;
806
807 expect!(p, &P::Token::WHILE);
808 expect!(p, &P::Token::LPAREN);
809
810 let test = p.allow_in_expr(|p| p.parse_expr())?;
811
812 expect!(p, &P::Token::RPAREN);
813
814 let _ = p.eat_general_semi();
816
817 let span = p.span(start);
818
819 Ok(DoWhileStmt { span, test, body }.into())
820}
821
822fn parse_labelled_stmt<'a, P: Parser<'a>>(p: &mut P, l: Ident) -> PResult<Stmt> {
823 p.do_inside_of_context(Context::IsBreakAllowed, |p| {
824 p.do_outside_of_context(Context::AllowUsingDecl, |p| {
825 let start = l.span.lo();
826
827 let mut errors = Vec::new();
828 for lb in &p.state().labels {
829 if l.sym == *lb {
830 errors.push(Error::new(
831 l.span,
832 SyntaxError::DuplicateLabel(l.sym.clone()),
833 ));
834 }
835 }
836 p.state_mut().labels.push(l.sym.clone());
837
838 let body = Box::new(if p.input().is(&P::Token::FUNCTION) {
839 let f = parse_fn_decl(p, Vec::new())?;
840 if let Decl::Fn(FnDecl { function, .. }) = &f {
841 if p.ctx().contains(Context::Strict) {
842 p.emit_err(function.span, SyntaxError::LabelledFunctionInStrict)
843 }
844 if function.is_generator || function.is_async {
845 p.emit_err(function.span, SyntaxError::LabelledGeneratorOrAsync)
846 }
847 }
848
849 f.into()
850 } else {
851 p.do_outside_of_context(Context::TopLevel, parse_stmt)?
852 });
853
854 for err in errors {
855 p.emit_error(err);
856 }
857
858 {
859 let pos = p.state().labels.iter().position(|v| v == &l.sym);
860 if let Some(pos) = pos {
861 p.state_mut().labels.remove(pos);
862 }
863 }
864
865 Ok(LabeledStmt {
866 span: p.span(start),
867 label: l,
868 body,
869 }
870 .into())
871 })
872 })
873}
874
875pub fn parse_block<'a, P: Parser<'a>>(p: &mut P, allow_directives: bool) -> PResult<BlockStmt> {
876 let start = p.cur_pos();
877
878 expect!(p, &P::Token::LBRACE);
879
880 let stmts = p.do_outside_of_context(Context::TopLevel, |p| {
881 parse_stmt_block_body(p, allow_directives, Some(&P::Token::RBRACE))
882 })?;
883
884 let span = p.span(start);
885 Ok(BlockStmt {
886 span,
887 stmts,
888 ctxt: Default::default(),
889 })
890}
891
892fn parse_finally_block<'a, P: Parser<'a>>(p: &mut P) -> PResult<Option<BlockStmt>> {
893 Ok(if p.input_mut().eat(&P::Token::FINALLY) {
894 parse_block(p, false).map(Some)?
895 } else {
896 None
897 })
898}
899
900fn parse_catch_clause<'a, P: Parser<'a>>(p: &mut P) -> PResult<Option<CatchClause>> {
901 let start = p.cur_pos();
902 Ok(if p.input_mut().eat(&P::Token::CATCH) {
903 let param = parse_catch_param(p)?;
904 parse_block(p, false)
905 .map(|body| CatchClause {
906 span: p.span(start),
907 param,
908 body,
909 })
910 .map(Some)?
911 } else {
912 None
913 })
914}
915
916fn parse_try_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
917 let start = p.cur_pos();
918 p.assert_and_bump(&P::Token::TRY);
919
920 let block = parse_block(p, false)?;
921
922 let catch_start = p.cur_pos();
923 let handler = parse_catch_clause(p)?;
924 let finalizer = parse_finally_block(p)?;
925
926 if handler.is_none() && finalizer.is_none() {
927 p.emit_err(
928 Span::new_with_checked(catch_start, catch_start),
929 SyntaxError::TS1005,
930 );
931 }
932
933 let span = p.span(start);
934 Ok(TryStmt {
935 span,
936 block,
937 handler,
938 finalizer,
939 }
940 .into())
941}
942
943fn parse_switch_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult<Stmt> {
944 let switch_start = p.cur_pos();
945
946 p.assert_and_bump(&P::Token::SWITCH);
947
948 expect!(p, &P::Token::LPAREN);
949 let discriminant = p.allow_in_expr(|p| p.parse_expr())?;
950 expect!(p, &P::Token::RPAREN);
951
952 let mut cases = Vec::new();
953 let mut span_of_previous_default = None;
954
955 expect!(p, &P::Token::LBRACE);
956
957 p.do_inside_of_context(Context::IsBreakAllowed, |p| {
958 while {
959 let cur = p.input().cur();
960 cur.is_case() || cur.is_default()
961 } {
962 let mut cons = Vec::new();
963 let is_case = p.input().is(&P::Token::CASE);
964 let case_start = p.cur_pos();
965 p.bump();
966 let test = if is_case {
967 p.allow_in_expr(|p| p.parse_expr()).map(Some)?
968 } else {
969 if let Some(previous) = span_of_previous_default {
970 syntax_error!(p, SyntaxError::MultipleDefault { previous });
971 }
972 span_of_previous_default = Some(p.span(case_start));
973
974 None
975 };
976 expect!(p, &P::Token::COLON);
977
978 while {
979 let cur = p.input().cur();
980 !(cur.is_case() || cur.is_default() || cur.is_rbrace())
981 } {
982 cons.push(p.do_outside_of_context(Context::TopLevel, parse_stmt_list_item)?);
983 }
984
985 cases.push(SwitchCase {
986 span: Span::new_with_checked(case_start, p.input().prev_span().hi),
987 test,
988 cons,
989 });
990 }
991
992 Ok(())
993 })?;
994
995 expect!(p, &P::Token::RBRACE);
997
998 Ok(SwitchStmt {
999 span: p.span(switch_start),
1000 discriminant,
1001 cases,
1002 }
1003 .into())
1004}
1005
1006pub fn parse_stmt_list_item<'a>(p: &mut impl Parser<'a>) -> PResult<Stmt> {
1008 trace_cur!(p, parse_stmt_list_item);
1009 parse_stmt_like(p, true, handle_import_export)
1010}
1011
1012pub fn parse_stmt_like<'a, P: Parser<'a>, Type: IsDirective + From<Stmt>>(
1014 p: &mut P,
1015 include_decl: bool,
1016 handle_import_export: impl Fn(&mut P, Vec<Decorator>) -> PResult<Type>,
1017) -> PResult<Type> {
1018 trace_cur!(p, parse_stmt_like);
1019
1020 debug_tracing!(p, "parse_stmt_like");
1021
1022 let start = p.cur_pos();
1023 let decorators = if p.input().get_cur().token() == &P::Token::AT {
1024 parse_decorators(p, true)?
1025 } else {
1026 vec![]
1027 };
1028
1029 let cur = p.input().cur();
1030 if cur.is_import() || cur.is_export() {
1031 return handle_import_export(p, decorators);
1032 }
1033
1034 p.do_outside_of_context(Context::WillExpectColonForCond, |p| {
1035 p.do_inside_of_context(Context::AllowUsingDecl, |p| {
1036 parse_stmt_internal(p, start, include_decl, decorators)
1037 })
1038 })
1039 .map(From::from)
1040}
1041
1042fn handle_import_export<'a, P: Parser<'a>>(p: &mut P, _: Vec<Decorator>) -> PResult<Stmt> {
1043 let start = p.cur_pos();
1044 if p.input().is(&P::Token::IMPORT) && peek!(p).is_some_and(|peek| peek.is_lparen()) {
1045 let expr = p.parse_expr()?;
1046
1047 p.eat_general_semi();
1048
1049 return Ok(ExprStmt {
1050 span: p.span(start),
1051 expr,
1052 }
1053 .into());
1054 }
1055
1056 if p.input().is(&P::Token::IMPORT) && peek!(p).is_some_and(|peek| peek.is_dot()) {
1057 let expr = p.parse_expr()?;
1058
1059 p.eat_general_semi();
1060
1061 return Ok(ExprStmt {
1062 span: p.span(start),
1063 expr,
1064 }
1065 .into());
1066 }
1067
1068 syntax_error!(p, SyntaxError::ImportExportInScript);
1069}
1070
1071fn parse_stmt_internal<'a, P: Parser<'a>>(
1073 p: &mut P,
1074 start: BytePos,
1075 include_decl: bool,
1076 decorators: Vec<Decorator>,
1077) -> PResult<Stmt> {
1078 trace_cur!(p, parse_stmt_internal);
1079
1080 let is_typescript = p.input().syntax().typescript();
1081
1082 if is_typescript
1083 && p.input().is(&P::Token::CONST)
1084 && peek!(p).is_some_and(|peek| peek.is_enum())
1085 {
1086 p.assert_and_bump(&P::Token::CONST);
1087 p.assert_and_bump(&P::Token::ENUM);
1088 return parse_ts_enum_decl(p, start, true)
1089 .map(Decl::from)
1090 .map(Stmt::from);
1091 }
1092
1093 let top_level = p.ctx().contains(Context::TopLevel);
1094
1095 let cur = p.input().cur().clone();
1096
1097 if cur.is_await() && (include_decl || top_level) {
1098 if top_level {
1099 p.mark_found_module_item();
1100 if !p.ctx().contains(Context::CanBeModule) {
1101 p.emit_err(p.input().cur_span(), SyntaxError::TopLevelAwaitInScript);
1102 }
1103 }
1104
1105 if peek!(p).is_some_and(|peek| peek.is_using()) {
1106 let eaten_await = Some(p.input().cur_pos());
1107 p.assert_and_bump(&P::Token::AWAIT);
1108 let v = parse_using_decl(p, start, true)?;
1109 if let Some(v) = v {
1110 return Ok(v.into());
1111 }
1112
1113 let expr = parse_await_expr(p, eaten_await)?;
1114 let expr = p.allow_in_expr(|p| parse_bin_op_recursively(p, expr, 0))?;
1115 p.eat_general_semi();
1116
1117 let span = p.span(start);
1118 return Ok(ExprStmt { span, expr }.into());
1119 }
1120 } else if cur.is_break() || cur.is_continue() {
1121 let is_break = p.input().is(&P::Token::BREAK);
1122 p.bump();
1123 let label = if p.eat_general_semi() {
1124 None
1125 } else {
1126 let i = parse_label_ident(p).map(Some)?;
1127 p.expect_general_semi()?;
1128 i
1129 };
1130 let span = p.span(start);
1131 if is_break {
1132 if label.is_some() && !p.state().labels.contains(&label.as_ref().unwrap().sym) {
1133 p.emit_err(span, SyntaxError::TS1116);
1134 } else if !p.ctx().contains(Context::IsBreakAllowed) {
1135 p.emit_err(span, SyntaxError::TS1105);
1136 }
1137 } else if !p.ctx().contains(Context::IsContinueAllowed) {
1138 p.emit_err(span, SyntaxError::TS1115);
1139 } else if label.is_some() && !p.state().labels.contains(&label.as_ref().unwrap().sym) {
1140 p.emit_err(span, SyntaxError::TS1107);
1141 }
1142 return Ok(if is_break {
1143 BreakStmt { span, label }.into()
1144 } else {
1145 ContinueStmt { span, label }.into()
1146 });
1147 } else if cur.is_debugger() {
1148 p.bump();
1149 p.expect_general_semi()?;
1150 return Ok(DebuggerStmt {
1151 span: p.span(start),
1152 }
1153 .into());
1154 } else if cur.is_do() {
1155 return parse_do_stmt(p);
1156 } else if cur.is_for() {
1157 return parse_for_stmt(p);
1158 } else if cur.is_function() {
1159 if !include_decl {
1160 p.emit_err(p.input().cur_span(), SyntaxError::DeclNotAllowed);
1161 }
1162 return parse_fn_decl(p, decorators).map(Stmt::from);
1163 } else if cur.is_class() {
1164 if !include_decl {
1165 p.emit_err(p.input().cur_span(), SyntaxError::DeclNotAllowed);
1166 }
1167 return parse_class_decl(p, start, start, decorators, false).map(Stmt::from);
1168 } else if cur.is_if() {
1169 return parse_if_stmt(p).map(Stmt::If);
1170 } else if cur.is_return() {
1171 return parse_return_stmt(p);
1172 } else if cur.is_switch() {
1173 return parse_switch_stmt(p);
1174 } else if cur.is_throw() {
1175 return parse_throw_stmt(p);
1176 } else if cur.is_catch() {
1177 let span = p.input().cur_span();
1179 p.emit_err(span, SyntaxError::TS1005);
1180
1181 let _ = parse_catch_clause(p);
1182 let _ = parse_finally_block(p);
1183
1184 return Ok(ExprStmt {
1185 span,
1186 expr: Invalid { span }.into(),
1187 }
1188 .into());
1189 } else if cur.is_finally() {
1190 let span = p.input().cur_span();
1192 p.emit_err(span, SyntaxError::TS1005);
1193
1194 let _ = parse_finally_block(p);
1195
1196 return Ok(ExprStmt {
1197 span,
1198 expr: Invalid { span }.into(),
1199 }
1200 .into());
1201 } else if cur.is_try() {
1202 return parse_try_stmt(p);
1203 } else if cur.is_with() {
1204 return parse_with_stmt(p);
1205 } else if cur.is_while() {
1206 return parse_while_stmt(p);
1207 } else if cur.is_var() || (cur.is_const() && include_decl) {
1208 let v = parse_var_stmt(p, false)?;
1209 return Ok(v.into());
1210 } else if cur.is_let() && include_decl {
1211 let is_keyword = match peek!(p) {
1213 Some(t) => t.follows_keyword_let(),
1214 _ => false,
1215 };
1216
1217 if is_keyword {
1218 let v = parse_var_stmt(p, false)?;
1219 return Ok(v.into());
1220 }
1221 } else if cur.is_using() && include_decl {
1222 let v = parse_using_decl(p, start, false)?;
1223 if let Some(v) = v {
1224 return Ok(v.into());
1225 }
1226 } else if cur.is_interface()
1227 && is_typescript
1228 && peek!(p).is_some_and(|peek| peek.is_word())
1229 && !p.input_mut().has_linebreak_between_cur_and_peeked()
1230 {
1231 let start = p.input().cur_pos();
1232 p.bump();
1233 return Ok(parse_ts_interface_decl(p, start)?.into());
1234 } else if cur.is_type()
1235 && is_typescript
1236 && peek!(p).is_some_and(|peek| peek.is_word())
1237 && !p.input_mut().has_linebreak_between_cur_and_peeked()
1238 {
1239 let start = p.input().cur_pos();
1240 p.bump();
1241 return Ok(parse_ts_type_alias_decl(p, start)?.into());
1242 } else if cur.is_enum()
1243 && is_typescript
1244 && peek!(p).is_some_and(|peek| peek.is_word())
1245 && !p.input_mut().has_linebreak_between_cur_and_peeked()
1246 {
1247 let start = p.input().cur_pos();
1248 p.bump();
1249 return Ok(parse_ts_enum_decl(p, start, false)?.into());
1250 } else if cur.is_lbrace() {
1251 return p
1252 .do_inside_of_context(Context::AllowUsingDecl, |p| parse_block(p, false))
1253 .map(Stmt::Block);
1254 } else if cur.is_semi() {
1255 p.bump();
1256 return Ok(EmptyStmt {
1257 span: p.span(start),
1258 }
1259 .into());
1260 }
1261
1262 if p.input().is(&P::Token::ASYNC)
1264 && peek!(p).is_some_and(|peek| peek.is_function())
1265 && !p.input_mut().has_linebreak_between_cur_and_peeked()
1266 {
1267 return parse_async_fn_decl(p, decorators).map(From::from);
1268 }
1269
1270 let expr = p.allow_in_expr(|p| p.parse_expr())?;
1276
1277 let expr = match *expr {
1278 Expr::Ident(ident) => {
1279 if p.input_mut().eat(&P::Token::COLON) {
1280 return parse_labelled_stmt(p, ident);
1281 }
1282 ident.into()
1283 }
1284 _ => p.verify_expr(expr)?,
1285 };
1286 if let Expr::Ident(ref ident) = *expr {
1287 if &*ident.sym == "interface" && p.input().had_line_break_before_cur() {
1288 p.emit_strict_mode_err(
1289 ident.span,
1290 SyntaxError::InvalidIdentInStrict(ident.sym.clone()),
1291 );
1292
1293 p.eat_general_semi();
1294
1295 return Ok(ExprStmt {
1296 span: p.span(start),
1297 expr,
1298 }
1299 .into());
1300 }
1301
1302 if p.input().syntax().typescript() {
1303 if let Some(decl) = parse_ts_expr_stmt(p, decorators, ident.clone())? {
1304 return Ok(decl.into());
1305 }
1306 }
1307 }
1308
1309 if p.syntax().typescript() {
1310 if let Expr::Ident(ref i) = *expr {
1311 match &*i.sym {
1312 "public" | "static" | "abstract" => {
1313 if p.input_mut().eat(&P::Token::INTERFACE) {
1314 p.emit_err(i.span, SyntaxError::TS2427);
1315 return parse_ts_interface_decl(p, start)
1316 .map(Decl::from)
1317 .map(Stmt::from);
1318 }
1319 }
1320 _ => {}
1321 }
1322 }
1323 }
1324
1325 if p.eat_general_semi() {
1326 Ok(ExprStmt {
1327 span: p.span(start),
1328 expr,
1329 }
1330 .into())
1331 } else {
1332 let cur = p.input().cur();
1333 if cur.is_bin_op() {
1334 p.emit_err(p.input().cur_span(), SyntaxError::TS1005);
1335 let expr = parse_bin_op_recursively(p, expr, 0)?;
1336 return Ok(ExprStmt {
1337 span: p.span(start),
1338 expr,
1339 }
1340 .into());
1341 }
1342
1343 syntax_error!(
1344 p,
1345 SyntaxError::ExpectedSemiForExprStmt { expr: expr.span() }
1346 );
1347 }
1348}
1349
1350pub fn parse_stmt_block_body<'a, P: Parser<'a>>(
1351 p: &mut P,
1352 allow_directives: bool,
1353 end: Option<&P::Token>,
1354) -> PResult<Vec<Stmt>> {
1355 parse_block_body(p, allow_directives, end, handle_import_export)
1356}
1357
1358pub(super) fn parse_block_body<'a, P: Parser<'a>, Type: IsDirective + From<Stmt>>(
1359 p: &mut P,
1360 allow_directives: bool,
1361 end: Option<&P::Token>,
1362 handle_import_export: impl Fn(&mut P, Vec<Decorator>) -> PResult<Type>,
1363) -> PResult<Vec<Type>> {
1364 trace_cur!(p, parse_block_body);
1365
1366 let mut stmts = Vec::with_capacity(8);
1367
1368 let has_strict_directive = allow_directives
1369 && (p
1370 .input()
1371 .cur()
1372 .is_str_raw_content("\"use strict\"", p.input())
1373 || p.input()
1374 .cur()
1375 .is_str_raw_content("'use strict'", p.input()));
1376
1377 let parse_stmts = |p: &mut P, stmts: &mut Vec<Type>| -> PResult<()> {
1378 let is_stmt_start = |p: &mut P| {
1379 let cur = p.input().cur();
1380 match end {
1381 Some(end) => {
1382 if cur.is_eof() {
1383 let eof_text = p.input_mut().dump_cur();
1384 p.emit_err(
1385 p.input().cur_span(),
1386 SyntaxError::Expected(format!("{end:?}"), eof_text),
1387 );
1388 false
1389 } else {
1390 cur != end
1391 }
1392 }
1393 None => !cur.is_eof(),
1394 }
1395 };
1396 while is_stmt_start(p) {
1397 let stmt = parse_stmt_like(p, true, &handle_import_export)?;
1398 stmts.push(stmt);
1399 }
1400 Ok(())
1401 };
1402
1403 if has_strict_directive {
1404 p.do_inside_of_context(Context::Strict, |p| parse_stmts(p, &mut stmts))?;
1405 } else {
1406 parse_stmts(p, &mut stmts)?;
1407 };
1408
1409 if !p.input().cur().is_eof() && end.is_some() {
1410 p.bump();
1411 }
1412
1413 Ok(stmts)
1414}