1use either::Either;
2use swc_atoms::atom;
3use swc_common::{ast_node, source_map::SmallPos, util::take::Take, BytePos, Span, Spanned};
4
5use super::*;
6use crate::{
7 error::SyntaxError,
8 parser::{pat::PatType, util::IsSimpleParameterList, Parser},
9};
10
11#[ast_node]
12pub(crate) enum AssignTargetOrSpread {
13 #[tag("ExprOrSpread")]
14 ExprOrSpread(ExprOrSpread),
15 #[tag("*")]
16 Pat(Pat),
17}
18
19impl<I: Tokens> Parser<I> {
20 pub fn parse_expr(&mut self) -> PResult<Box<Expr>> {
21 trace_cur!(self, parse_expr);
22 debug_tracing!(self, "parse_expr");
23 let expr = self.parse_assignment_expr()?;
24 let start = expr.span_lo();
25
26 if self.input_mut().is(Token::Comma) {
27 let mut exprs = vec![expr];
28
29 while self.input_mut().eat(Token::Comma) {
30 exprs.push(self.parse_assignment_expr()?);
31 }
32
33 return Ok(SeqExpr {
34 span: self.span(start),
35 exprs,
36 }
37 .into());
38 }
39
40 Ok(expr)
41 }
42
43 fn parse_expr_or_spread(&mut self) -> PResult<ExprOrSpread> {
46 trace_cur!(self, parse_expr_or_spread);
47 let start = self.input().cur_pos();
48 if self.input_mut().eat(Token::DotDotDot) {
49 let spread_span = self.span(start);
50 let spread = Some(spread_span);
51 self.allow_in_expr(Self::parse_assignment_expr)
52 .map_err(|err| {
53 Error::new(
54 err.span(),
55 SyntaxError::WithLabel {
56 inner: Box::new(err),
57 span: spread_span,
58 note: "An expression should follow '...'",
59 },
60 )
61 })
62 .map(|expr| ExprOrSpread { spread, expr })
63 } else {
64 self.parse_assignment_expr()
65 .map(|expr| ExprOrSpread { spread: None, expr })
66 }
67 }
68
69 #[cfg_attr(
71 feature = "tracing-spans",
72 tracing::instrument(level = "debug", skip_all)
73 )]
74 pub(crate) fn parse_assignment_expr(&mut self) -> PResult<Box<Expr>> {
75 trace_cur!(self, parse_assignment_expr);
76
77 if self.input().syntax().typescript() && self.input().is(Token::JSXTagStart) {
78 let res = self.try_parse_ts(|p| p.parse_assignment_expr_base().map(Some));
81 if let Some(res) = res {
82 return Ok(res);
83 }
84 }
85
86 self.parse_assignment_expr_base()
87 }
88
89 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
94 fn parse_assignment_expr_base(&mut self) -> PResult<Box<Expr>> {
95 trace_cur!(self, parse_assignment_expr_base);
96 let start = self.input().cur_span();
97
98 if self.input().syntax().typescript()
99 && (self.input().cur() == Token::Lt || self.input().cur() == Token::JSXTagStart)
100 && (peek!(self).is_some_and(|peek| peek.is_word() || peek == Token::JSXName))
101 {
102 let res = self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
103 p.try_parse_ts(|p| {
104 let type_parameters = p.parse_ts_type_params(false, true)?;
105 let mut arrow = p.parse_assignment_expr_base()?;
106 match *arrow {
107 Expr::Arrow(ArrowExpr {
108 ref mut span,
109 ref mut type_params,
110 ..
111 }) => {
112 *span = Span::new_with_checked(type_parameters.span.lo, span.hi);
113 *type_params = Some(type_parameters);
114 }
115 _ => unexpected!(p, "("),
116 }
117 Ok(Some(arrow))
118 })
119 });
120 if let Some(res) = res {
121 if self.input().syntax().disallow_ambiguous_jsx_like() {
122 self.emit_err(start, SyntaxError::ReservedArrowTypeParam);
123 }
124 return Ok(res);
125 }
126 }
127
128 if self.ctx().contains(Context::InGenerator) && self.input().is(Token::Yield) {
129 return self.parse_yield_expr();
130 }
131
132 let cur = self.input().cur();
133
134 if cur == Token::Error {
135 let err = self.input_mut().expect_error_token_and_bump();
136 return Err(err);
137 }
138
139 self.state_mut().potential_arrow_start =
140 if cur.is_known_ident() || matches!(cur, Token::Ident | Token::Yield | Token::LParen) {
141 Some(self.cur_pos())
142 } else {
143 None
144 };
145
146 let start = self.cur_pos();
147
148 let cond = self.parse_cond_expr()?;
150
151 return_if_arrow!(self, cond);
152
153 match *cond {
154 Expr::Cond(..) | Expr::Bin(..) | Expr::Unary(..) | Expr::Update(..) => return Ok(cond),
157 _ => {}
158 }
159
160 self.finish_assignment_expr(start, cond)
161 }
162
163 #[allow(dead_code)]
164 pub(crate) fn parse_member_expr(&mut self) -> PResult<Box<Expr>> {
165 self.parse_member_expr_or_new_expr(false)
166 }
167
168 pub(super) fn parse_unary_expr(&mut self) -> PResult<Box<Expr>> {
169 trace_cur!(self, parse_unary_expr);
170
171 let token_and_span = self.input().get_cur();
172 let start = token_and_span.span.lo;
173 let cur = token_and_span.token;
174
175 if cur == Token::Lt && self.input().syntax().typescript() && !self.input().syntax().jsx() {
176 self.bump(); return if self.input_mut().eat(Token::Const) {
178 self.expect(Token::Gt)?;
179 let expr = self.parse_unary_expr()?;
180 Ok(TsConstAssertion {
181 span: self.span(start),
182 expr,
183 }
184 .into())
185 } else {
186 self.parse_ts_type_assertion(start)
187 .map(Expr::from)
188 .map(Box::new)
189 };
190 } else if cur == Token::Lt
191 && self.input().syntax().jsx()
192 && self.input_mut().peek().is_some_and(|peek| {
193 peek.is_word() || peek == Token::Gt || peek.should_rescan_into_gt_in_jsx()
194 })
195 {
196 fn into_expr(e: Either<JSXFragment, JSXElement>) -> Box<Expr> {
197 match e {
198 Either::Left(l) => l.into(),
199 Either::Right(r) => r.into(),
200 }
201 }
202 return self.parse_jsx_element(true).map(into_expr);
203 } else if matches!(cur, Token::PlusPlus | Token::MinusMinus) {
204 let op = if cur == Token::PlusPlus {
206 op!("++")
207 } else {
208 op!("--")
209 };
210 self.bump();
211
212 let arg = self.parse_unary_expr()?;
213 let span = Span::new_with_checked(start, arg.span_hi());
214 self.check_assign_target(&arg, false);
215
216 return Ok(UpdateExpr {
217 span,
218 prefix: true,
219 op,
220 arg,
221 }
222 .into());
223 } else if cur == Token::Delete
224 || cur == Token::Void
225 || cur == Token::TypeOf
226 || cur == Token::Plus
227 || cur == Token::Minus
228 || cur == Token::Tilde
229 || cur == Token::Bang
230 {
231 let op = if cur == Token::Delete {
233 op!("delete")
234 } else if cur == Token::Void {
235 op!("void")
236 } else if cur == Token::TypeOf {
237 op!("typeof")
238 } else if cur == Token::Plus {
239 op!(unary, "+")
240 } else if cur == Token::Minus {
241 op!(unary, "-")
242 } else if cur == Token::Tilde {
243 op!("~")
244 } else {
245 debug_assert!(cur == Token::Bang);
246 op!("!")
247 };
248 self.bump();
249 let arg_start = self.cur_pos() - BytePos(1);
250 let arg = match self.parse_unary_expr() {
251 Ok(expr) => expr,
252 Err(err) => {
253 self.emit_error(err);
254 Invalid {
255 span: Span::new_with_checked(arg_start, arg_start),
256 }
257 .into()
258 }
259 };
260
261 if op == op!("delete") {
262 if let Expr::Ident(ref i) = *arg {
263 self.emit_strict_mode_err(i.span, SyntaxError::TS1102)
264 }
265 }
266
267 return Ok(UnaryExpr {
268 span: Span::new_with_checked(start, arg.span_hi()),
269 op,
270 arg,
271 }
272 .into());
273 } else if cur == Token::Await {
274 return self.parse_await_expr(None);
275 }
276
277 let expr = self.parse_lhs_expr()?;
279 if let Expr::Arrow { .. } = *expr {
280 return Ok(expr);
281 }
282
283 if self.input_mut().had_line_break_before_cur() {
285 return Ok(expr);
286 }
287
288 let cur = self.input().cur();
289 if cur == Token::PlusPlus || cur == Token::MinusMinus {
290 let op = if cur == Token::PlusPlus {
291 op!("++")
292 } else {
293 op!("--")
294 };
295
296 self.check_assign_target(&expr, false);
297 self.bump();
298
299 return Ok(UpdateExpr {
300 span: self.span(expr.span_lo()),
301 prefix: false,
302 op,
303 arg: expr,
304 }
305 .into());
306 }
307 Ok(expr)
308 }
309
310 #[inline(always)]
311 pub(super) fn parse_primary_expr(&mut self) -> PResult<Box<Expr>> {
312 trace_cur!(self, parse_primary_expr);
313 let start = self.input().cur_pos();
314 let can_be_arrow = self
315 .state
316 .potential_arrow_start
317 .map(|s| s == start)
318 .unwrap_or(false);
319 let tok = self.input.cur();
320 match tok {
321 Token::This => return self.parse_this_expr(start),
322 Token::Async => {
323 if let Some(res) = self.try_parse_async_start(can_be_arrow) {
324 return res;
325 }
326 }
327 Token::LBracket => {
328 return self
329 .do_outside_of_context(Context::WillExpectColonForCond, Self::parse_array_lit)
330 }
331 Token::LBrace => {
332 return self.parse_object_expr().map(Box::new);
333 }
334 Token::Function => {
336 return self.parse_fn_expr();
337 }
338 Token::Null | Token::True | Token::False | Token::Num | Token::BigInt | Token::Str => {
340 return self.parse_lit().map(|lit| lit.into());
341 }
342 Token::Slash | Token::DivEq => {
344 if let Some(res) = self.try_parse_regexp(start) {
345 return Ok(res);
346 }
347 }
348 Token::LParen => return self.parse_paren_expr_or_arrow_fn(can_be_arrow, None),
349 Token::NoSubstitutionTemplateLiteral => {
350 return Ok(self.parse_no_substitution_template_literal(false)?.into())
351 }
352 Token::TemplateHead => {
353 return Ok(self
355 .do_outside_of_context(Context::WillExpectColonForCond, |p| p.parse_tpl(false))?
356 .into());
357 }
358 _ => {}
359 }
360
361 self.parse_primary_expr_rest(start, can_be_arrow)
362 }
363
364 #[cfg_attr(
366 feature = "tracing-spans",
367 tracing::instrument(level = "debug", skip_all)
368 )]
369 pub(crate) fn parse_lhs_expr(&mut self) -> PResult<Box<Expr>> {
370 trace_cur!(self, parse_lhs_expr);
371
372 let token_and_span = self.input().get_cur();
373 let start = token_and_span.span.lo;
374 let cur = token_and_span.token;
375
376 if cur == Token::Super {
378 self.bump(); let obj = Callee::Super(Super {
380 span: self.span(start),
381 });
382 return self.parse_subscripts(obj, false, false);
383 } else if cur == Token::Import {
384 self.bump(); return self.parse_dynamic_import_or_import_meta(start, false);
386 }
387
388 let callee = self.parse_new_expr()?;
389 return_if_arrow!(self, callee);
390
391 let type_args = if self.input().syntax().typescript() && {
392 let cur = self.input().cur();
393 cur == Token::Lt || cur == Token::LShift
394 } {
395 self.try_parse_ts(|p| {
396 let type_args = p.parse_ts_type_args()?;
397 p.assert_and_bump(Token::Gt);
398 if p.input().is(Token::LParen) {
399 Ok(Some(type_args))
400 } else {
401 Ok(None)
402 }
403 })
404 } else {
405 None
406 };
407
408 if let Expr::New(ne @ NewExpr { args: None, .. }) = *callee {
409 if type_args.is_some() {
412 expect!(self, Token::LParen);
414 }
415 debug_assert!(
416 self.input().cur() != Token::LParen,
417 "parse_new_expr() should eat paren if it exists"
418 );
419 return Ok(NewExpr { type_args, ..ne }.into());
420 }
421 if self.input().is(Token::LParen) {
425 let (callee, is_import) = match callee {
428 _ if callee.is_ident_ref_to("import") => (
429 Callee::Import(Import {
430 span: callee.span(),
431 phase: Default::default(),
432 }),
433 true,
434 ),
435 _ => (Callee::Expr(callee), false),
436 };
437 let args = self.parse_args(is_import)?;
438
439 let call_expr = match callee {
440 Callee::Expr(e) if unwrap_ts_non_null(&e).is_opt_chain() => OptChainExpr {
441 span: self.span(start),
442 base: Box::new(OptChainBase::Call(OptCall {
443 span: self.span(start),
444 callee: e,
445 args,
446 type_args,
447 ..Default::default()
448 })),
449 optional: false,
450 }
451 .into(),
452 _ => CallExpr {
453 span: self.span(start),
454
455 callee,
456 args,
457 type_args,
458 ..Default::default()
459 }
460 .into(),
461 };
462
463 return self.parse_subscripts(Callee::Expr(call_expr), false, false);
464 }
465 if type_args.is_some() {
466 expect!(self, Token::LParen);
468 }
469
470 Ok(callee)
473 }
474
475 #[cfg_attr(
476 feature = "tracing-spans",
477 tracing::instrument(level = "debug", skip_all)
478 )]
479 fn parse_array_lit(&mut self) -> PResult<Box<Expr>> {
480 trace_cur!(self, parse_array_lit);
481
482 let start = self.input().cur_pos();
483
484 self.assert_and_bump(Token::LBracket);
485
486 let mut elems = Vec::with_capacity(8);
487
488 while !self.input().is(Token::RBracket) {
489 if self.input().is(Token::Comma) {
490 expect!(self, Token::Comma);
491 elems.push(None);
492 continue;
493 }
494
495 elems.push(self.allow_in_expr(|p| p.parse_expr_or_spread()).map(Some)?);
496
497 if !self.input().is(Token::RBracket) {
498 expect!(self, Token::Comma);
499 if self.input().is(Token::RBracket) {
500 let prev_span = self.input().prev_span();
501 self.state_mut().trailing_commas.insert(start, prev_span);
502 }
503 }
504 }
505
506 expect!(self, Token::RBracket);
507
508 let span = self.span(start);
509 Ok(ArrayLit { span, elems }.into())
510 }
511
512 fn at_possible_async(&mut self, expr: &Expr) -> bool {
513 self.state().potential_arrow_start == Some(expr.span_lo()) && expr.is_ident_ref_to("async")
515 }
516
517 fn parse_yield_expr(&mut self) -> PResult<Box<Expr>> {
518 let start = self.input().cur_pos();
519 self.assert_and_bump(Token::Yield);
520 debug_assert!(self.ctx().contains(Context::InGenerator));
521
522 if self.ctx().contains(Context::InParameters) && !self.ctx().contains(Context::InFunction) {
527 syntax_error!(self, self.input().prev_span(), SyntaxError::YieldParamInGen)
528 }
529
530 let parse_with_arg = |p: &mut Self| {
531 let has_star = p.input_mut().eat(Token::Asterisk);
532 let err_span = p.span(start);
533 let arg = p.parse_assignment_expr().map_err(|err| {
534 Error::new(
535 err.span(),
536 SyntaxError::WithLabel {
537 inner: Box::new(err),
538 span: err_span,
539 note: "Tried to parse an argument of yield",
540 },
541 )
542 })?;
543 Ok(YieldExpr {
544 span: p.span(start),
545 arg: Some(arg),
546 delegate: has_star,
547 }
548 .into())
549 };
550
551 if self.is_general_semi() || {
552 let cur = self.input().cur();
553 cur != Token::Lt
554 && cur != Token::Asterisk
555 && cur != Token::Slash
556 && cur != Token::DivEq
557 && !cur.starts_expr()
558 } {
559 Ok(YieldExpr {
560 span: self.span(start),
561 arg: None,
562 delegate: false,
563 }
564 .into())
565 } else {
566 parse_with_arg(self)
567 }
568 }
569
570 fn parse_tpl_elements(
571 &mut self,
572 is_tagged_tpl: bool,
573 ) -> PResult<(Vec<Box<Expr>>, Vec<TplElement>)> {
574 trace_cur!(self, parse_tpl_elements);
575
576 let mut exprs = Vec::new();
577 let cur_elem = self.parse_template_head(is_tagged_tpl)?;
578 let mut is_tail = cur_elem.tail;
579 let mut quasis = vec![cur_elem];
580
581 while !is_tail {
582 exprs.push(self.allow_in_expr(|p| p.parse_expr())?);
583 let elem = self.parse_tpl_element(is_tagged_tpl)?;
584 is_tail = elem.tail;
585 quasis.push(elem);
586 }
587 Ok((exprs, quasis))
588 }
589
590 fn parse_tagged_tpl(
591 &mut self,
592 tag: Box<Expr>,
593 type_params: Option<Box<TsTypeParamInstantiation>>,
594 ) -> PResult<TaggedTpl> {
595 let tagged_tpl_start = tag.span_lo();
596 trace_cur!(self, parse_tagged_tpl);
597
598 let tpl = Box::new(
599 if self.input_mut().is(Token::NoSubstitutionTemplateLiteral) {
600 self.input_mut().rescan_template_token(true);
601 self.parse_no_substitution_template_literal(true)?
602 } else {
603 self.parse_tpl(true)?
604 },
605 );
606
607 let span = self.span(tagged_tpl_start);
608
609 if tag.is_opt_chain() {
610 self.emit_err(span, SyntaxError::TaggedTplInOptChain);
611 }
612
613 Ok(TaggedTpl {
614 span,
615 tag,
616 type_params,
617 tpl,
618 ..Default::default()
619 })
620 }
621
622 pub(super) fn parse_no_substitution_template_literal(
623 &mut self,
624 is_tagged_tpl: bool,
625 ) -> PResult<Tpl> {
626 let start = self.input.cur_pos();
627 let cur = self.input.cur();
628 debug_assert!(matches!(cur, Token::NoSubstitutionTemplateLiteral));
629
630 let (cooked, raw) = cur.take_template(self.input_mut());
631 let (raw, cooked) = match cooked {
632 Ok(cooked) => (raw, Some(cooked)),
633 Err(err) => {
634 if is_tagged_tpl {
635 (raw, None)
636 } else {
637 return Err(err);
638 }
639 }
640 };
641 self.bump();
642 let pos = self.input.prev_span().hi;
643 debug_assert!(start <= pos);
644 let span = Span::new_with_checked(start, pos);
645 Ok(Tpl {
646 span,
647 exprs: vec![],
648 quasis: vec![TplElement {
649 span: {
650 debug_assert!(start.0 <= pos.0 - 2);
651 Span::new_with_checked(
655 BytePos::from_u32(start.0 + 1),
656 BytePos::from_u32(pos.0 - 1),
657 )
658 },
659 tail: true,
660 raw,
661 cooked,
662 }],
663 })
664 }
665
666 fn parse_template_head(&mut self, is_tagged_tpl: bool) -> PResult<TplElement> {
667 let start = self.cur_pos();
668 let cur = self.input().cur();
669 debug_assert!(matches!(cur, Token::TemplateHead));
670
671 let (cooked, raw) = cur.take_template(self.input_mut());
672 let (raw, cooked) = match cooked {
673 Ok(cooked) => (raw, Some(cooked)),
674 Err(err) => {
675 if is_tagged_tpl {
676 (raw, None)
677 } else {
678 return Err(err);
679 }
680 }
681 };
682
683 self.bump();
684
685 let pos = self.input.prev_span().hi;
686 debug_assert!(start.0 <= pos.0 - 3);
690 let span =
691 Span::new_with_checked(BytePos::from_u32(start.0 + 1), BytePos::from_u32(pos.0 - 2));
692 Ok(TplElement {
693 span,
694 raw,
695 tail: false,
696 cooked,
697 })
698 }
699
700 pub(super) fn parse_tpl(&mut self, is_tagged_tpl: bool) -> PResult<Tpl> {
701 trace_cur!(self, parse_tpl);
702 debug_assert!(matches!(self.input.cur(), Token::TemplateHead));
703
704 let start = self.cur_pos();
705
706 let (exprs, quasis) = self.parse_tpl_elements(is_tagged_tpl)?;
707
708 Ok(Tpl {
709 span: self.span(start),
710 exprs,
711 quasis,
712 })
713 }
714
715 pub(crate) fn parse_tpl_element(&mut self, is_tagged_tpl: bool) -> PResult<TplElement> {
716 if self.input_mut().is(Token::RBrace) {
717 self.input_mut().rescan_template_token(false);
718 }
719 let start = self.cur_pos();
720 let cur = self.input_mut().cur();
721 let (raw, cooked, tail, span) = match cur {
722 Token::TemplateMiddle => {
723 let (cooked, raw) = cur.take_template(self.input_mut());
724 self.bump();
725 let pos = self.input.prev_span().hi;
726 debug_assert!(start.0 <= pos.0 - 2);
727 let span = Span::new_with_checked(start, BytePos::from_u32(pos.0 - 2));
730 match cooked {
731 Ok(cooked) => (raw, Some(cooked), false, span),
732 Err(err) => {
733 if is_tagged_tpl {
734 (raw, None, false, span)
735 } else {
736 return Err(err);
737 }
738 }
739 }
740 }
741 Token::TemplateTail => {
742 let (cooked, raw) = cur.take_template(self.input_mut());
743 self.bump();
744 let pos = self.input.prev_span().hi;
745 debug_assert!(start.0 < pos.0);
746 let span = Span::new_with_checked(start, BytePos::from_u32(pos.0 - 1));
749 match cooked {
750 Ok(cooked) => (raw, Some(cooked), true, span),
751 Err(err) => {
752 if is_tagged_tpl {
753 (raw, None, true, span)
754 } else {
755 return Err(err);
756 }
757 }
758 }
759 }
760 Token::Error => {
761 let err = cur.take_error(self.input_mut());
762 self.input_mut().bump();
763 return Err(err);
764 }
765 _ => {
766 unexpected!(self, "`}`")
767 }
768 };
769
770 Ok(TplElement {
771 span,
772 raw,
773 tail,
774 cooked,
775 })
776 }
777
778 fn parse_tpl_ty_elements(&mut self) -> PResult<(Vec<Box<TsType>>, Vec<TplElement>)> {
779 trace_cur!(self, parse_tpl_elements);
780
781 let mut tys = Vec::new();
782 let cur_elem = self.parse_template_head(false)?;
783 let mut is_tail = cur_elem.tail;
784 let mut quasis = vec![cur_elem];
785
786 while !is_tail {
787 tys.push(self.parse_ts_type()?);
788 let elem = self.parse_tpl_element(false)?;
789 is_tail = elem.tail;
790 quasis.push(elem);
791 }
792 Ok((tys, quasis))
793 }
794
795 fn parse_no_substitution_template_ty(&mut self) -> PResult<TsTplLitType> {
796 let start = self.input.cur_pos();
797 let cur = self.input.cur();
798 debug_assert!(matches!(cur, Token::NoSubstitutionTemplateLiteral));
799
800 let (cooked, raw) = cur.take_template(self.input_mut());
801 let (raw, cooked) = match cooked {
802 Ok(cooked) => (raw, Some(cooked)),
803 Err(_) => (raw, None),
804 };
805 self.bump();
806 let pos = self.input.prev_span().hi;
807 debug_assert!(start.0 <= pos.0);
808 let span = Span::new_with_checked(start, pos);
809 Ok(TsTplLitType {
810 span,
811 types: vec![],
812 quasis: vec![TplElement {
813 span: {
814 debug_assert!(start.0 <= pos.0 - 2);
815 Span::new_with_checked(
819 BytePos::from_u32(start.0 + 1),
820 BytePos::from_u32(pos.0 - 1),
821 )
822 },
823 tail: true,
824 raw,
825 cooked,
826 }],
827 })
828 }
829
830 fn parse_tpl_ty(&mut self) -> PResult<TsTplLitType> {
831 trace_cur!(self, parse_tpl_ty);
832 debug_assert!(matches!(self.input.cur(), Token::TemplateHead));
833
834 let start = self.cur_pos();
835
836 let (types, quasis) = self.parse_tpl_ty_elements()?;
837
838 let _ = self.input.cur();
839
840 Ok(TsTplLitType {
841 span: self.span(start),
842 types,
843 quasis,
844 })
845 }
846
847 pub(super) fn parse_tagged_tpl_ty(&mut self) -> PResult<TsLitType> {
848 let start = self.cur_pos();
849 debug_assert!(self.input().syntax().typescript());
850 trace_cur!(self, parse_tagged_tpl);
851 let tpl_ty = if self.input_mut().is(Token::NoSubstitutionTemplateLiteral) {
852 self.parse_no_substitution_template_ty()
853 } else {
854 self.parse_tpl_ty()
855 };
856 tpl_ty.map(|tpl_ty| {
857 let lit = TsLit::Tpl(tpl_ty);
858 TsLitType {
859 span: self.span(start),
860 lit,
861 }
862 })
863 }
864
865 pub(crate) fn parse_str_lit(&mut self) -> swc_ecma_ast::Str {
866 debug_assert!(self.input().cur() == Token::Str);
867 let token_and_span = self.input().get_cur();
868 let start = token_and_span.span.lo;
869 let (value, raw) = self.input_mut().expect_string_token_and_bump();
870 swc_ecma_ast::Str {
871 span: self.span(start),
872 value,
873 raw: Some(raw),
874 }
875 }
876
877 pub(crate) fn parse_lit(&mut self) -> PResult<Lit> {
878 let token_and_span = self.input().get_cur();
879 let start = token_and_span.span.lo;
880 let cur = token_and_span.token;
881 let v = if cur == Token::Null {
882 self.bump();
883 let span = self.span(start);
884 Lit::Null(swc_ecma_ast::Null { span })
885 } else if cur == Token::True || cur == Token::False {
886 let value = cur == Token::True;
887 self.bump();
888 let span = self.span(start);
889 Lit::Bool(swc_ecma_ast::Bool { span, value })
890 } else if cur == Token::Str {
891 Lit::Str(self.parse_str_lit())
892 } else if cur == Token::Num {
893 let (value, raw) = self.input_mut().expect_number_token_and_bump();
894 Lit::Num(swc_ecma_ast::Number {
895 span: self.span(start),
896 value,
897 raw: Some(raw),
898 })
899 } else if cur == Token::BigInt {
900 let (value, raw) = self.input_mut().expect_bigint_token_and_bump();
901 Lit::BigInt(swc_ecma_ast::BigInt {
902 span: self.span(start),
903 value,
904 raw: Some(raw),
905 })
906 } else if cur == Token::Error {
907 let err = self.input_mut().expect_error_token_and_bump();
908 return Err(err);
909 } else if cur == Token::Eof {
910 return Err(self.eof_error());
911 } else {
912 unreachable!("parse_lit should not be called for {:?}", cur)
913 };
914 Ok(v)
915 }
916
917 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
919 pub(crate) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult<Vec<ExprOrSpread>> {
920 trace_cur!(self, parse_args);
921
922 self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
923 let start = p.cur_pos();
924 expect!(p, Token::LParen);
925
926 let mut first = true;
927 let mut expr_or_spreads = Vec::with_capacity(2);
928
929 while !p.input().is(Token::RParen) {
930 if first {
931 first = false;
932 } else {
933 expect!(p, Token::Comma);
934 if p.input().is(Token::RParen) {
936 if is_dynamic_import && !p.input().syntax().import_attributes() {
937 syntax_error!(p, p.span(start), SyntaxError::TrailingCommaInsideImport)
938 }
939
940 break;
941 }
942 }
943
944 expr_or_spreads.push(p.allow_in_expr(|p| p.parse_expr_or_spread())?);
945 }
946
947 expect!(p, Token::RParen);
948 Ok(expr_or_spreads)
949 })
950 }
951
952 fn finish_assignment_expr(&mut self, start: BytePos, cond: Box<Expr>) -> PResult<Box<Expr>> {
953 trace_cur!(self, finish_assignment_expr);
954
955 if let Some(op) = self.input().cur().as_assign_op() {
956 let left = if op == AssignOp::Assign {
957 match AssignTarget::try_from(self.reparse_expr_as_pat(PatType::AssignPat, cond)?) {
958 Ok(pat) => pat,
959 Err(expr) => {
960 syntax_error!(self, expr.span(), SyntaxError::InvalidAssignTarget)
961 }
962 }
963 } else {
964 if !cond.is_valid_simple_assignment_target(self.ctx().contains(Context::Strict)) {
967 if self.input().syntax().typescript() {
968 self.emit_err(cond.span(), SyntaxError::TS2406);
969 } else {
970 self.emit_err(cond.span(), SyntaxError::NotSimpleAssign)
971 }
972 }
973 if self.input().syntax().typescript()
974 && cond
975 .as_ident()
976 .map(|i| i.is_reserved_in_strict_bind())
977 .unwrap_or(false)
978 {
979 self.emit_strict_mode_err(cond.span(), SyntaxError::TS1100);
980 }
981
982 match AssignTarget::try_from(cond) {
984 Ok(v) => v,
985 Err(v) => {
986 syntax_error!(self, v.span(), SyntaxError::InvalidAssignTarget);
987 }
988 }
989 };
990
991 self.bump();
992 let right = self.parse_assignment_expr()?;
993 Ok(AssignExpr {
994 span: self.span(start),
995 op,
996 left,
998 right,
999 }
1000 .into())
1001 } else {
1002 Ok(cond)
1003 }
1004 }
1005
1006 #[cfg_attr(
1008 feature = "tracing-spans",
1009 tracing::instrument(level = "debug", skip_all)
1010 )]
1011 fn parse_cond_expr(&mut self) -> PResult<Box<Expr>> {
1012 trace_cur!(self, parse_cond_expr);
1013
1014 let start = self.cur_pos();
1015
1016 let test = self.parse_bin_expr()?;
1017 return_if_arrow!(self, test);
1018
1019 if self.input_mut().eat(Token::QuestionMark) {
1020 let cons = self.do_inside_of_context(
1021 Context::InCondExpr
1022 .union(Context::WillExpectColonForCond)
1023 .union(Context::IncludeInExpr),
1024 Self::parse_assignment_expr,
1025 )?;
1026
1027 expect!(self, Token::Colon);
1028
1029 let alt = self.do_inside_of_context(Context::InCondExpr, |p| {
1030 p.do_outside_of_context(
1031 Context::WillExpectColonForCond,
1032 Self::parse_assignment_expr,
1033 )
1034 })?;
1035
1036 let span = Span::new_with_checked(start, alt.span_hi());
1037 Ok(CondExpr {
1038 span,
1039 test,
1040 cons,
1041 alt,
1042 }
1043 .into())
1044 } else {
1045 Ok(test)
1046 }
1047 }
1048
1049 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1050 pub(crate) fn parse_subscripts(
1051 &mut self,
1052 obj: Callee,
1053 no_call: bool,
1054 no_computed_member: bool,
1055 ) -> PResult<Box<Expr>> {
1056 let start = obj.span().lo;
1057 let mut expr = match obj {
1058 Callee::Import(import) => self.parse_subscript_import_call(start, import)?,
1059 Callee::Super(s) => self.parse_subscript_super(start, s, no_call)?,
1060 Callee::Expr(expr) => expr,
1061 #[cfg(swc_ast_unknown)]
1062 _ => unreachable!(),
1063 };
1064
1065 loop {
1066 expr = match self.parse_subscript(start, expr, no_call, no_computed_member)? {
1067 (expr, false) => return Ok(expr),
1068 (expr, true) => expr,
1069 }
1070 }
1071 }
1072
1073 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1075 fn parse_subscript(
1076 &mut self,
1077 start: BytePos,
1078 mut callee: Box<Expr>,
1079 no_call: bool,
1080 no_computed_member: bool,
1081 ) -> PResult<(Box<Expr>, bool)> {
1082 trace_cur!(self, parse_subscript);
1083
1084 if self.input().syntax().typescript() {
1085 if !self.input().had_line_break_before_cur() && self.input().is(Token::Bang) {
1086 self.input_mut().set_expr_allowed(false);
1087 self.assert_and_bump(Token::Bang);
1088
1089 let expr = Box::new(Expr::TsNonNull(TsNonNullExpr {
1090 span: self.span(start),
1091 expr: callee,
1092 }));
1093
1094 return Ok((expr, true));
1095 }
1096
1097 if self.input().is(Token::Lt) {
1098 let result = self.do_inside_of_context(Context::ShouldNotLexLtOrGtAsType, |p| {
1104 p.try_parse_ts(|p| {
1105 if !no_call && p.at_possible_async(&callee) {
1106 let async_arrow_fn = p.try_parse_ts_generic_async_arrow_fn(start)?;
1110 if let Some(async_arrow_fn) = async_arrow_fn {
1111 return Ok(Some((async_arrow_fn.into(), true)));
1112 }
1113 }
1114
1115 let type_args = p.parse_ts_type_args()?;
1116 p.assert_and_bump(Token::Gt);
1117 let cur = p.input().cur();
1118
1119 if !no_call && cur == Token::LParen {
1120 let args = p.parse_args(false)?;
1123
1124 let expr = if callee.is_opt_chain() {
1125 Expr::OptChain(OptChainExpr {
1126 span: p.span(start),
1127 base: Box::new(OptChainBase::Call(OptCall {
1128 span: p.span(start),
1129 callee: callee.take(),
1130 type_args: Some(type_args),
1131 args,
1132 ..Default::default()
1133 })),
1134 optional: false,
1135 })
1136 } else {
1137 Expr::Call(CallExpr {
1138 span: p.span(start),
1139 callee: Callee::Expr(callee.take()),
1140 type_args: Some(type_args),
1141 args,
1142 ..Default::default()
1143 })
1144 };
1145
1146 Ok(Some((Box::new(expr), true)))
1147 } else if matches!(
1148 cur,
1149 Token::NoSubstitutionTemplateLiteral
1150 | Token::TemplateHead
1151 | Token::BackQuote
1152 ) {
1153 p.parse_tagged_tpl(callee.take(), Some(type_args))
1154 .map(|expr| (expr.into(), true))
1155 .map(Some)
1156 } else if matches!(cur, Token::Eq | Token::As | Token::Satisfies) {
1157 let expr = Expr::TsInstantiation(TsInstantiation {
1158 span: p.span(start),
1159 expr: callee.take(),
1160 type_args,
1161 });
1162 Ok(Some((Box::new(expr), false)))
1163 } else if no_call {
1164 unexpected!(p, "`")
1165 } else {
1166 unexpected!(p, "( or `")
1167 }
1168 })
1169 });
1170
1171 if let Some(expr) = result {
1172 return Ok(expr);
1173 }
1174 }
1175 }
1176
1177 let ts_instantiation = if self.syntax().typescript() && self.input().is(Token::Lt) {
1178 self.try_parse_ts_type_args()
1179 } else {
1180 None
1181 };
1182
1183 let question_dot_token = if self.input().is(Token::QuestionMark)
1184 && peek!(self).is_some_and(|peek| peek == Token::Dot)
1185 {
1186 let start = self.cur_pos();
1187 self.bump();
1188
1189 let span = Some(self.span(start));
1190 self.bump();
1191
1192 span
1193 } else {
1194 None
1195 };
1196
1197 let question_dot = question_dot_token.is_some();
1199
1200 if !no_computed_member && self.input_mut().eat(Token::LBracket) {
1202 let bracket_lo = self.input().prev_span().lo;
1203 let prop = self.allow_in_expr(|p| p.parse_expr())?;
1204 expect!(self, Token::RBracket);
1205 let span = Span::new_with_checked(callee.span_lo(), self.input().last_pos());
1206 debug_assert_eq!(callee.span_lo(), span.lo());
1207 let prop = ComputedPropName {
1208 span: Span::new_with_checked(bracket_lo, self.input().last_pos()),
1209 expr: prop,
1210 };
1211
1212 let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1213 self.try_parse_ts_type_args()
1214 } else {
1215 None
1216 };
1217
1218 let is_opt_chain = unwrap_ts_non_null(&callee).is_opt_chain();
1219 let expr = MemberExpr {
1220 span,
1221 obj: callee,
1222 prop: MemberProp::Computed(prop),
1223 };
1224 let expr = if is_opt_chain || question_dot {
1225 OptChainExpr {
1226 span,
1227 optional: question_dot,
1228 base: Box::new(OptChainBase::Member(expr)),
1229 }
1230 .into()
1231 } else {
1232 expr.into()
1233 };
1234
1235 let expr = if let Some(type_args) = type_args {
1236 Expr::TsInstantiation(TsInstantiation {
1237 expr: Box::new(expr),
1238 type_args,
1239 span: self.span(start),
1240 })
1241 } else {
1242 expr
1243 };
1244 return Ok((Box::new(expr), true));
1245 }
1246
1247 let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) && question_dot
1248 {
1249 let ret = self.parse_ts_type_args()?;
1250 self.assert_and_bump(Token::Gt);
1251 Some(ret)
1252 } else {
1253 None
1254 };
1255
1256 if (self.input.is(Token::LParen) && (!no_call || question_dot)) || type_args.is_some() {
1257 let args = self.parse_args(false)?;
1258 let span = self.span(start);
1259 return if question_dot || unwrap_ts_non_null(&callee).is_opt_chain() {
1260 let expr = OptChainExpr {
1261 span,
1262 optional: question_dot,
1263 base: Box::new(OptChainBase::Call(OptCall {
1264 span: self.span(start),
1265 callee,
1266 args,
1267 type_args,
1268 ..Default::default()
1269 })),
1270 };
1271 Ok((Box::new(Expr::OptChain(expr)), true))
1272 } else {
1273 let expr = CallExpr {
1274 span: self.span(start),
1275 callee: Callee::Expr(callee),
1276 args,
1277 ..Default::default()
1278 };
1279 Ok((Box::new(Expr::Call(expr)), true))
1280 };
1281 }
1282
1283 if question_dot || self.input_mut().eat(Token::Dot) {
1286 let prop = self.parse_maybe_private_name().map(|e| match e {
1287 Either::Left(p) => MemberProp::PrivateName(p),
1288 Either::Right(i) => MemberProp::Ident(i),
1289 })?;
1290 let span = self.span(callee.span_lo());
1291 debug_assert_eq!(callee.span_lo(), span.lo());
1292 debug_assert_eq!(prop.span_hi(), span.hi());
1293
1294 let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1295 self.try_parse_ts_type_args()
1296 } else {
1297 None
1298 };
1299
1300 let expr = MemberExpr {
1301 span,
1302 obj: callee,
1303 prop,
1304 };
1305 let expr = if unwrap_ts_non_null(&expr.obj).is_opt_chain() || question_dot {
1306 OptChainExpr {
1307 span: self.span(start),
1308 optional: question_dot,
1309 base: Box::new(OptChainBase::Member(expr)),
1310 }
1311 .into()
1312 } else {
1313 expr.into()
1314 };
1315
1316 let expr = if let Some(type_args) = type_args {
1317 Expr::TsInstantiation(TsInstantiation {
1318 expr: Box::new(expr),
1319 type_args,
1320 span: self.span(start),
1321 })
1322 } else {
1323 expr
1324 };
1325
1326 return Ok((Box::new(expr), true));
1327 }
1328
1329 let expr = if let Some(type_args) = ts_instantiation {
1330 TsInstantiation {
1331 expr: callee,
1332 type_args,
1333 span: self.span(start),
1334 }
1335 .into()
1336 } else {
1337 callee
1338 };
1339
1340 let cur = self.input().cur();
1342 if matches!(
1343 cur,
1344 Token::TemplateHead | Token::NoSubstitutionTemplateLiteral | Token::BackQuote
1345 ) {
1346 let tpl = self.do_outside_of_context(Context::WillExpectColonForCond, |p| {
1347 p.parse_tagged_tpl(expr, None)
1348 })?;
1349 return Ok((tpl.into(), true));
1350 }
1351
1352 Ok((expr, false))
1353 }
1354
1355 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1357 fn parse_subscript_super(
1358 &mut self,
1359 start: BytePos,
1360 lhs: Super,
1361 no_call: bool,
1362 ) -> PResult<Box<Expr>> {
1363 trace_cur!(self, parse_subscript_super);
1364 match self.input().cur() {
1365 Token::LBracket => {
1366 self.bump();
1367 let bracket_lo = self.input().prev_span().lo;
1368 let prop = self.allow_in_expr(|p| p.parse_expr())?;
1369 expect!(self, Token::RBracket);
1370 let span = Span::new_with_checked(lhs.span_lo(), self.input().last_pos());
1371 debug_assert_eq!(lhs.span_lo(), span.lo());
1372 let prop = ComputedPropName {
1373 span: Span::new_with_checked(bracket_lo, self.input().last_pos()),
1374 expr: prop,
1375 };
1376
1377 if !self.ctx().contains(Context::AllowDirectSuper)
1378 && !self.input().syntax().allow_super_outside_method()
1379 {
1380 syntax_error!(self, lhs.span, SyntaxError::InvalidSuper)
1381 } else {
1382 Ok(Box::new(Expr::SuperProp(SuperPropExpr {
1383 span,
1384 obj: lhs,
1385 prop: SuperProp::Computed(prop),
1386 })))
1387 }
1388 }
1389 Token::LParen if !no_call => {
1390 let args = self.parse_args(false)?;
1391 Ok(Box::new(Expr::Call(CallExpr {
1392 span: self.span(start),
1393 callee: Callee::Super(lhs),
1394 args,
1395 ..Default::default()
1396 })))
1397 }
1398 Token::Dot => {
1399 self.bump();
1400 let prop = self.parse_maybe_private_name().map(|e| match e {
1401 Either::Left(p) => MemberProp::PrivateName(p),
1402 Either::Right(i) => MemberProp::Ident(i),
1403 })?;
1404 let span = self.span(lhs.span_lo());
1405 debug_assert_eq!(lhs.span_lo(), span.lo());
1406 debug_assert_eq!(prop.span_hi(), span.hi());
1407
1408 if !self.ctx().contains(Context::AllowDirectSuper)
1409 && !self.input().syntax().allow_super_outside_method()
1410 {
1411 syntax_error!(self, lhs.span, SyntaxError::InvalidSuper);
1412 } else {
1413 let expr = match prop {
1414 MemberProp::Ident(ident) => SuperPropExpr {
1415 span,
1416 obj: lhs,
1417 prop: SuperProp::Ident(ident),
1418 },
1419 MemberProp::PrivateName(..) => {
1420 syntax_error!(
1421 self,
1422 self.input().cur_span(),
1423 SyntaxError::InvalidSuperCall
1424 )
1425 }
1426 MemberProp::Computed(..) => unreachable!(),
1427 #[cfg(swc_ast_unknown)]
1428 _ => unreachable!(),
1429 };
1430
1431 Ok(Box::new(Expr::SuperProp(expr)))
1432 }
1433 }
1434 _ => {
1435 if no_call {
1436 syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidSuperCall)
1437 } else {
1438 syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidSuper)
1439 }
1440 }
1441 }
1442 }
1443
1444 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1446 fn parse_subscript_import_call(&mut self, start: BytePos, lhs: Import) -> PResult<Box<Expr>> {
1447 trace_cur!(self, parse_subscript_import);
1448
1449 if self.input().is(Token::LParen) {
1450 let args = self.parse_args(true)?;
1451 let expr = Box::new(Expr::Call(CallExpr {
1452 span: self.span(start),
1453 callee: Callee::Import(lhs),
1454 args,
1455 ..Default::default()
1456 }));
1457 return Ok(expr);
1458 }
1459
1460 syntax_error!(self, self.input().cur_span(), SyntaxError::InvalidImport);
1461 }
1462
1463 fn parse_dynamic_import_or_import_meta(
1464 &mut self,
1465 start: BytePos,
1466 no_call: bool,
1467 ) -> PResult<Box<Expr>> {
1468 if self.input_mut().eat(Token::Dot) {
1469 self.mark_found_module_item();
1470
1471 let ident = self.parse_ident_name()?;
1472
1473 match &*ident.sym {
1474 "meta" => {
1475 let span = self.span(start);
1476 if !self.ctx().contains(Context::CanBeModule) {
1477 self.emit_err(span, SyntaxError::ImportMetaInScript);
1478 }
1479 let expr = MetaPropExpr {
1480 span,
1481 kind: MetaPropKind::ImportMeta,
1482 };
1483 self.parse_subscripts(Callee::Expr(expr.into()), no_call, false)
1484 }
1485 "defer" => self.parse_dynamic_import_call(start, ImportPhase::Defer),
1486 "source" => self.parse_dynamic_import_call(start, ImportPhase::Source),
1487 _ => unexpected!(self, "meta"),
1488 }
1489 } else {
1490 self.parse_dynamic_import_call(start, ImportPhase::Evaluation)
1491 }
1492 }
1493
1494 fn parse_dynamic_import_call(
1495 &mut self,
1496 start: BytePos,
1497 phase: ImportPhase,
1498 ) -> PResult<Box<Expr>> {
1499 let import = Callee::Import(Import {
1500 span: self.span(start),
1501 phase,
1502 });
1503 self.parse_subscripts(import, false, false)
1504 }
1505
1506 #[cfg_attr(
1508 feature = "tracing-spans",
1509 tracing::instrument(level = "debug", skip_all)
1510 )]
1511 fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult<Box<Expr>> {
1512 self.do_inside_of_context(Context::ShouldNotLexLtOrGtAsType, |p| {
1513 p.parse_member_expr_or_new_expr_inner(is_new_expr)
1514 })
1515 }
1516
1517 fn parse_member_expr_or_new_expr_inner(&mut self, is_new_expr: bool) -> PResult<Box<Expr>> {
1518 trace_cur!(self, parse_member_expr_or_new_expr);
1519
1520 let start = self.cur_pos();
1521 if self.input_mut().eat(Token::New) {
1522 if self.input_mut().eat(Token::Dot) {
1523 if self.input_mut().eat(Token::Target) {
1524 let span = self.span(start);
1525 let expr = MetaPropExpr {
1526 span,
1527 kind: MetaPropKind::NewTarget,
1528 }
1529 .into();
1530
1531 let ctx = self.ctx();
1532 if !ctx.contains(Context::InsideNonArrowFunctionScope)
1533 && !ctx.contains(Context::InParameters)
1534 && !ctx.contains(Context::InClass)
1535 {
1536 self.emit_err(span, SyntaxError::InvalidNewTarget);
1537 }
1538
1539 return self.parse_subscripts(Callee::Expr(expr), true, false);
1540 }
1541
1542 unexpected!(self, "target")
1543 }
1544
1545 let callee = self.parse_member_expr_or_new_expr(is_new_expr)?;
1547 return_if_arrow!(self, callee);
1548
1549 if is_new_expr {
1550 match *callee {
1551 Expr::OptChain(OptChainExpr {
1552 span,
1553 optional: true,
1554 ..
1555 }) => {
1556 syntax_error!(self, span, SyntaxError::OptChainCannotFollowConstructorCall)
1557 }
1558 Expr::Member(MemberExpr { ref obj, .. }) => {
1559 if let Expr::OptChain(OptChainExpr {
1560 span,
1561 optional: true,
1562 ..
1563 }) = **obj
1564 {
1565 syntax_error!(
1566 self,
1567 span,
1568 SyntaxError::OptChainCannotFollowConstructorCall
1569 )
1570 }
1571 }
1572 _ => {}
1573 }
1574 }
1575
1576 let type_args = if self.input().syntax().typescript() && {
1577 let cur = self.input().cur();
1578 cur == Token::Lt || cur == Token::LShift
1579 } {
1580 self.try_parse_ts(|p| {
1581 let args = p.do_outside_of_context(
1582 Context::ShouldNotLexLtOrGtAsType,
1583 Self::parse_ts_type_args,
1584 )?;
1585 p.assert_and_bump(Token::Gt);
1586 if !p.input().is(Token::LParen) {
1587 let span = p.input().cur_span();
1588 let cur = p.input_mut().dump_cur();
1589 syntax_error!(p, span, SyntaxError::Expected('('.to_string(), cur))
1590 }
1591 Ok(Some(args))
1592 })
1593 } else {
1594 None
1595 };
1596
1597 if !is_new_expr || self.input().is(Token::LParen) {
1598 let args = self.parse_args(false).map(Some)?;
1600
1601 let new_expr = Callee::Expr(
1602 NewExpr {
1603 span: self.span(start),
1604 callee,
1605 args,
1606 type_args,
1607 ..Default::default()
1608 }
1609 .into(),
1610 );
1611
1612 return self.parse_subscripts(new_expr, true, false);
1615 }
1616
1617 return Ok(NewExpr {
1620 span: self.span(start),
1621 callee,
1622 args: None,
1623 type_args,
1624 ..Default::default()
1625 }
1626 .into());
1627 }
1628
1629 if self.input_mut().eat(Token::Super) {
1630 let base = Callee::Super(Super {
1631 span: self.span(start),
1632 });
1633 return self.parse_subscripts(base, true, false);
1634 } else if self.input_mut().eat(Token::Import) {
1635 return self.parse_dynamic_import_or_import_meta(start, true);
1636 }
1637 let obj = self.parse_primary_expr()?;
1638 return_if_arrow!(self, obj);
1639
1640 let type_args = if self.syntax().typescript() && self.input().is(Token::Lt) {
1641 self.try_parse_ts_type_args()
1642 } else {
1643 None
1644 };
1645 let obj = if let Some(type_args) = type_args {
1646 trace_cur!(self, parse_member_expr_or_new_expr__with_type_args);
1647 TsInstantiation {
1648 expr: obj,
1649 type_args,
1650 span: self.span(start),
1651 }
1652 .into()
1653 } else {
1654 obj
1655 };
1656
1657 self.parse_subscripts(Callee::Expr(obj), true, false)
1658 }
1659
1660 #[cfg_attr(feature = "tracing-spans", tracing::instrument(skip_all))]
1663 pub(crate) fn parse_new_expr(&mut self) -> PResult<Box<Expr>> {
1664 trace_cur!(self, parse_new_expr);
1665 self.parse_member_expr_or_new_expr(true)
1666 }
1667
1668 pub(crate) fn parse_bin_expr(&mut self) -> PResult<Box<Expr>> {
1670 trace_cur!(self, parse_bin_expr);
1671
1672 let left = match self.parse_unary_expr() {
1673 Ok(v) => v,
1674 Err(err) => {
1675 trace_cur!(self, parse_bin_expr__recovery_unary_err);
1676
1677 let cur = self.input().cur();
1678 if cur == Token::Error {
1679 let err = self.input_mut().expect_error_token_and_bump();
1680 return Err(err);
1681 } else if (cur == Token::In && self.ctx().contains(Context::IncludeInExpr))
1682 || cur == Token::InstanceOf
1683 || cur.is_bin_op()
1684 {
1685 self.emit_err(self.input().cur_span(), SyntaxError::TS1109);
1686 Invalid { span: err.span() }.into()
1687 } else {
1688 return Err(err);
1689 }
1690 }
1691 };
1692
1693 return_if_arrow!(self, left);
1694 self.parse_bin_op_recursively(left, 0)
1695 }
1696
1697 pub(crate) fn parse_bin_op_recursively(
1705 &mut self,
1706 mut left: Box<Expr>,
1707 mut min_prec: u8,
1708 ) -> PResult<Box<Expr>> {
1709 loop {
1710 let (next_left, next_prec) = self.parse_bin_op_recursively_inner(left, min_prec)?;
1711
1712 match &*next_left {
1713 Expr::Bin(BinExpr {
1714 span,
1715 left,
1716 op: op!("&&"),
1717 ..
1718 })
1719 | Expr::Bin(BinExpr {
1720 span,
1721 left,
1722 op: op!("||"),
1723 ..
1724 }) => {
1725 if let Expr::Bin(BinExpr { op: op!("??"), .. }) = &**left {
1726 self.emit_err(*span, SyntaxError::NullishCoalescingWithLogicalOp);
1727 }
1728 }
1729 _ => {}
1730 }
1731
1732 min_prec = match next_prec {
1733 Some(v) => v,
1734 None => return Ok(next_left),
1735 };
1736
1737 left = next_left;
1738 }
1739 }
1740
1741 fn parse_bin_op_recursively_inner(
1743 &mut self,
1744 left: Box<Expr>,
1745 min_prec: u8,
1746 ) -> PResult<(Box<Expr>, Option<u8>)> {
1747 const PREC_OF_IN: u8 = 7;
1748
1749 if self.input().syntax().typescript() && !self.input().had_line_break_before_cur() {
1750 if PREC_OF_IN > min_prec && self.input().is(Token::As) {
1751 let start = left.span_lo();
1752 let expr = left;
1753 let node = if peek!(self).is_some_and(|cur| cur == Token::Const) {
1754 self.bump(); self.bump(); TsConstAssertion {
1757 span: self.span(start),
1758 expr,
1759 }
1760 .into()
1761 } else {
1762 let type_ann = self.next_then_parse_ts_type()?;
1763 TsAsExpr {
1764 span: self.span(start),
1765 expr,
1766 type_ann,
1767 }
1768 .into()
1769 };
1770
1771 return self.parse_bin_op_recursively_inner(node, min_prec);
1772 } else if self.input().is(Token::Satisfies) {
1773 let start = left.span_lo();
1774 let expr = left;
1775 let node = {
1776 let type_ann = self.next_then_parse_ts_type()?;
1777 TsSatisfiesExpr {
1778 span: self.span(start),
1779 expr,
1780 type_ann,
1781 }
1782 .into()
1783 };
1784
1785 return self.parse_bin_op_recursively_inner(node, min_prec);
1786 }
1787 }
1788
1789 let cur = self.input().cur();
1791 let op = if cur == Token::In && self.ctx().contains(Context::IncludeInExpr) {
1792 op!("in")
1793 } else if cur == Token::InstanceOf {
1794 op!("instanceof")
1795 } else if let Some(op) = cur.as_bin_op() {
1796 op
1797 } else {
1798 return Ok((left, None));
1799 };
1800
1801 if op.precedence() <= min_prec {
1802 if cfg!(feature = "debug") {
1803 tracing::trace!(
1804 "returning {:?} without parsing {:?} because min_prec={}, prec={}",
1805 left,
1806 op,
1807 min_prec,
1808 op.precedence()
1809 );
1810 }
1811
1812 return Ok((left, None));
1813 }
1814 self.bump();
1815 if cfg!(feature = "debug") {
1816 tracing::trace!(
1817 "parsing binary op {:?} min_prec={}, prec={}",
1818 op,
1819 min_prec,
1820 op.precedence()
1821 );
1822 }
1823 match *left {
1824 Expr::Unary { .. } | Expr::Await(..) if op == op!("**") => {
1826 syntax_error!(
1831 self,
1832 SyntaxError::UnaryInExp {
1833 left: format!("{left:?}"),
1835 left_span: left.span(),
1836 }
1837 )
1838 }
1839 _ => {}
1840 }
1841
1842 let right = {
1843 let left_of_right = self.parse_unary_expr()?;
1844 self.parse_bin_op_recursively(
1845 left_of_right,
1846 if op == op!("**") {
1847 op.precedence() - 1
1849 } else {
1850 op.precedence()
1851 },
1852 )?
1853 };
1854 if op == op!("??") {
1867 match *left {
1868 Expr::Bin(BinExpr { span, op, .. }) if op == op!("&&") || op == op!("||") => {
1869 self.emit_err(span, SyntaxError::NullishCoalescingWithLogicalOp);
1870 }
1871 _ => {}
1872 }
1873
1874 match *right {
1875 Expr::Bin(BinExpr { span, op, .. }) if op == op!("&&") || op == op!("||") => {
1876 self.emit_err(span, SyntaxError::NullishCoalescingWithLogicalOp);
1877 }
1878 _ => {}
1879 }
1880 }
1881
1882 let node = BinExpr {
1883 span: Span::new_with_checked(left.span_lo(), right.span_hi()),
1884 op,
1885 left,
1886 right,
1887 }
1888 .into();
1889
1890 Ok((node, Some(min_prec)))
1891 }
1892
1893 pub(crate) fn parse_await_expr(
1894 &mut self,
1895 start_of_await_token: Option<BytePos>,
1896 ) -> PResult<Box<Expr>> {
1897 let start = start_of_await_token.unwrap_or_else(|| self.cur_pos());
1898
1899 if start_of_await_token.is_none() {
1900 self.assert_and_bump(Token::Await);
1901 }
1902
1903 let await_token = self.span(start);
1904
1905 if self.input().is(Token::Asterisk) {
1906 syntax_error!(self, SyntaxError::AwaitStar);
1907 }
1908
1909 let ctx = self.ctx();
1910
1911 let span = self.span(start);
1912
1913 if !ctx.contains(Context::InAsync)
1914 && (self.is_general_semi() || {
1915 let cur = self.input().cur();
1916 matches!(cur, Token::RParen | Token::RBracket | Token::Comma)
1917 })
1918 {
1919 if ctx.contains(Context::Module) {
1920 self.emit_err(span, SyntaxError::InvalidIdentInAsync);
1921 }
1922
1923 return Ok(Ident::new_no_ctxt(atom!("await"), span).into());
1924 }
1925
1926 if start_of_await_token.is_none() && ctx.contains(Context::TopLevel) {
1928 self.mark_found_module_item();
1929 if !ctx.contains(Context::CanBeModule) {
1930 self.emit_err(await_token, SyntaxError::TopLevelAwaitInScript);
1931 }
1932 }
1933
1934 if ctx.contains(Context::InFunction) && !ctx.contains(Context::InAsync) {
1935 self.emit_err(await_token, SyntaxError::AwaitInFunction);
1936 }
1937
1938 if ctx.contains(Context::InParameters) && !ctx.contains(Context::InFunction) {
1939 self.emit_err(span, SyntaxError::AwaitParamInAsync);
1940 }
1941
1942 let arg = self.parse_unary_expr()?;
1943 Ok(AwaitExpr {
1944 span: self.span(start),
1945 arg,
1946 }
1947 .into())
1948 }
1949
1950 pub(crate) fn parse_for_head_prefix(&mut self) -> PResult<Box<Expr>> {
1951 self.parse_expr()
1952 }
1953
1954 #[cfg_attr(
1956 feature = "tracing-spans",
1957 tracing::instrument(level = "debug", skip_all)
1958 )]
1959 fn parse_args_or_pats(&mut self) -> PResult<(Vec<AssignTargetOrSpread>, Option<Span>)> {
1960 self.do_outside_of_context(
1961 Context::WillExpectColonForCond,
1962 Self::parse_args_or_pats_inner,
1963 )
1964 }
1965
1966 fn parse_args_or_pats_inner(&mut self) -> PResult<(Vec<AssignTargetOrSpread>, Option<Span>)> {
1967 trace_cur!(self, parse_args_or_pats);
1968
1969 expect!(self, Token::LParen);
1970
1971 let mut items = Vec::new();
1972 let mut trailing_comma = None;
1973
1974 while !self.input().is(Token::RParen) {
1977 let is_async = self.input().is(Token::Async)
1979 && peek!(self)
1980 .is_some_and(|t| t == Token::LParen || t == Token::Function || t.is_word());
1981
1982 let start = self.cur_pos();
1983 self.state_mut().potential_arrow_start = Some(start);
1984 let modifier_start = start;
1985
1986 let has_modifier = self.eat_any_ts_modifier()?;
1987 let pat_start = self.cur_pos();
1988
1989 let mut arg = {
1990 if self.input().syntax().typescript()
1991 && (self.is_ident_ref()
1992 || (self.input().is(Token::DotDotDot) && self.peek_is_ident_ref()))
1993 {
1994 let spread = if self.input_mut().eat(Token::DotDotDot) {
1995 Some(self.input().prev_span())
1996 } else {
1997 None
1998 };
1999
2000 let expr = if spread.is_some() {
2003 self.parse_bin_expr()?
2004 } else {
2005 let mut expr = self.parse_bin_expr()?;
2006
2007 if self.input().cur().is_assign_op() {
2008 expr = self.finish_assignment_expr(start, expr)?
2009 }
2010
2011 expr
2012 };
2013
2014 ExprOrSpread { spread, expr }
2015 } else {
2016 self.allow_in_expr(|p| p.parse_expr_or_spread())?
2017 }
2018 };
2019
2020 let optional = if self.input().syntax().typescript() {
2021 if self.input().is(Token::QuestionMark) {
2022 if peek!(self).is_some_and(|peek| {
2023 matches!(
2024 peek,
2025 Token::Comma | Token::Eq | Token::RParen | Token::Colon
2026 )
2027 }) {
2028 self.assert_and_bump(Token::QuestionMark);
2029 if arg.spread.is_some() {
2030 self.emit_err(self.input().prev_span(), SyntaxError::TS1047);
2031 }
2032 match *arg.expr {
2033 Expr::Ident(..) => {}
2034 _ => {
2035 syntax_error!(
2036 self,
2037 arg.span(),
2038 SyntaxError::TsBindingPatCannotBeOptional
2039 )
2040 }
2041 }
2042 true
2043 } else if matches!(arg, ExprOrSpread { spread: None, .. }) {
2044 expect!(self, Token::QuestionMark);
2045 let test = arg.expr;
2046
2047 let cons = self.do_inside_of_context(
2048 Context::InCondExpr
2049 .union(Context::WillExpectColonForCond)
2050 .union(Context::IncludeInExpr),
2051 Self::parse_assignment_expr,
2052 )?;
2053 expect!(self, Token::Colon);
2054
2055 let alt = self.do_inside_of_context(Context::InCondExpr, |p| {
2056 p.do_outside_of_context(
2057 Context::WillExpectColonForCond,
2058 Self::parse_assignment_expr,
2059 )
2060 })?;
2061
2062 arg = ExprOrSpread {
2063 spread: None,
2064 expr: CondExpr {
2065 span: Span::new_with_checked(start, alt.span_hi()),
2066 test,
2067 cons,
2068 alt,
2069 }
2070 .into(),
2071 };
2072
2073 false
2074 } else {
2075 false
2076 }
2077 } else {
2078 false
2079 }
2080 } else {
2081 false
2082 };
2083
2084 if optional || (self.input().syntax().typescript() && self.input().is(Token::Colon)) {
2085 let mut pat = self.reparse_expr_as_pat(PatType::BindingPat, arg.expr)?;
2092 if optional {
2093 match pat {
2094 Pat::Ident(ref mut i) => i.optional = true,
2095 _ => unreachable!(),
2096 }
2097 }
2098 if let Some(span) = arg.spread {
2099 pat = RestPat {
2100 span: self.span(pat_start),
2101 dot3_token: span,
2102 arg: Box::new(pat),
2103 type_ann: None,
2104 }
2105 .into();
2106 }
2107 match pat {
2108 Pat::Ident(BindingIdent {
2109 id: Ident { ref mut span, .. },
2110 ref mut type_ann,
2111 ..
2112 })
2113 | Pat::Array(ArrayPat {
2114 ref mut type_ann,
2115 ref mut span,
2116 ..
2117 })
2118 | Pat::Object(ObjectPat {
2119 ref mut type_ann,
2120 ref mut span,
2121 ..
2122 })
2123 | Pat::Rest(RestPat {
2124 ref mut type_ann,
2125 ref mut span,
2126 ..
2127 }) => {
2128 let new_type_ann = self.try_parse_ts_type_ann()?;
2129 if new_type_ann.is_some() {
2130 *span = Span::new_with_checked(pat_start, self.input().prev_span().hi);
2131 }
2132 *type_ann = new_type_ann;
2133 }
2134 Pat::Expr(ref expr) => unreachable!("invalid pattern: Expr({:?})", expr),
2135 Pat::Assign(..) | Pat::Invalid(..) => {
2136 }
2143 #[cfg(swc_ast_unknown)]
2144 _ => unreachable!(),
2145 }
2146
2147 if self.input_mut().eat(Token::Eq) {
2148 let right = self.parse_assignment_expr()?;
2149 pat = AssignPat {
2150 span: self.span(pat_start),
2151 left: Box::new(pat),
2152 right,
2153 }
2154 .into();
2155 }
2156
2157 if has_modifier {
2158 self.emit_err(self.span(modifier_start), SyntaxError::TS2369);
2159 }
2160
2161 items.push(AssignTargetOrSpread::Pat(pat))
2162 } else {
2163 if has_modifier {
2164 self.emit_err(self.span(modifier_start), SyntaxError::TS2369);
2165 }
2166
2167 items.push(AssignTargetOrSpread::ExprOrSpread(arg));
2168 }
2169
2170 if self.input_mut().eat(Token::Arrow) && {
2172 debug_assert_eq!(items.len(), 1);
2173 match items[0] {
2174 AssignTargetOrSpread::ExprOrSpread(ExprOrSpread { ref expr, .. })
2175 | AssignTargetOrSpread::Pat(Pat::Expr(ref expr)) => {
2176 matches!(**expr, Expr::Ident(..))
2177 }
2178 AssignTargetOrSpread::Pat(Pat::Ident(..)) => true,
2179 _ => false,
2180 }
2181 } {
2182 let params: Vec<Pat> = self.parse_paren_items_as_params(items.clone(), None)?;
2183
2184 let body: Box<BlockStmtOrExpr> = self.parse_fn_block_or_expr_body(
2185 false,
2186 false,
2187 true,
2188 params.is_simple_parameter_list(),
2189 )?;
2190 let span = self.span(start);
2191
2192 items.push(AssignTargetOrSpread::ExprOrSpread(ExprOrSpread {
2193 expr: Box::new(
2194 ArrowExpr {
2195 span,
2196 body,
2197 is_async,
2198 is_generator: false,
2199 params,
2200 ..Default::default()
2201 }
2202 .into(),
2203 ),
2204 spread: None,
2205 }));
2206 }
2207
2208 if !self.input().is(Token::RParen) {
2209 expect!(self, Token::Comma);
2210 if self.input().is(Token::RParen) {
2211 trailing_comma = Some(self.input().prev_span());
2212 }
2213 }
2214 }
2215
2216 expect!(self, Token::RParen);
2217 Ok((items, trailing_comma))
2218 }
2219
2220 #[cfg_attr(
2221 feature = "tracing-spans",
2222 tracing::instrument(level = "debug", skip_all)
2223 )]
2224 fn parse_paren_expr_or_arrow_fn(
2225 &mut self,
2226 can_be_arrow: bool,
2227 async_span: Option<Span>,
2228 ) -> PResult<Box<Expr>> {
2229 trace_cur!(self, parse_paren_expr_or_arrow_fn);
2230
2231 let expr_start = async_span.map(|x| x.lo()).unwrap_or_else(|| self.cur_pos());
2232
2233 let (paren_items, trailing_comma) = self
2239 .do_outside_of_context(Context::WillExpectColonForCond, |p| {
2240 p.allow_in_expr(Self::parse_args_or_pats)
2241 })?;
2242
2243 let has_pattern = paren_items
2244 .iter()
2245 .any(|item| matches!(item, AssignTargetOrSpread::Pat(..)));
2246
2247 let will_expect_colon_for_cond = self.ctx().contains(Context::WillExpectColonForCond);
2248 if self.syntax().typescript()
2250 && self.ctx().contains(Context::InCondExpr)
2251 && self.input().is(Token::Colon)
2252 {
2253 let items_ref = &paren_items;
2255 if let Some(expr) = self.try_parse_ts(|p| {
2256 let return_type = p.parse_ts_type_or_type_predicate_ann(Token::Colon)?;
2257
2258 expect!(p, Token::Arrow);
2259
2260 let params: Vec<Pat> =
2261 p.parse_paren_items_as_params(items_ref.clone(), trailing_comma)?;
2262
2263 let body: Box<BlockStmtOrExpr> = p.parse_fn_block_or_expr_body(
2264 async_span.is_some(),
2265 false,
2266 true,
2267 params.is_simple_parameter_list(),
2268 )?;
2269
2270 if will_expect_colon_for_cond && !p.input().is(Token::Colon) {
2271 trace_cur!(p, parse_arrow_in_cond__fail);
2272 unexpected!(p, "fail")
2273 }
2274
2275 Ok(Some(
2276 ArrowExpr {
2277 span: p.span(expr_start),
2278 is_async: async_span.is_some(),
2279 is_generator: false,
2280 params,
2281 body,
2282 return_type: Some(return_type),
2283 ..Default::default()
2284 }
2285 .into(),
2286 ))
2287 }) {
2288 return Ok(expr);
2289 }
2290 }
2291
2292 let return_type = if !self.ctx().contains(Context::WillExpectColonForCond)
2293 && self.input().syntax().typescript()
2294 && self.input().is(Token::Colon)
2295 {
2296 self.try_parse_ts(|p| {
2297 let return_type = p.parse_ts_type_or_type_predicate_ann(Token::Colon)?;
2298
2299 if !p.input().is(Token::Arrow) {
2300 unexpected!(p, "fail")
2301 }
2302
2303 Ok(Some(return_type))
2304 })
2305 } else {
2306 None
2307 };
2308
2309 if has_pattern || return_type.is_some() || self.input().is(Token::Arrow) {
2311 if self.input().had_line_break_before_cur() {
2312 syntax_error!(
2313 self,
2314 self.span(expr_start),
2315 SyntaxError::LineBreakBeforeArrow
2316 );
2317 }
2318
2319 if !can_be_arrow {
2320 syntax_error!(self, self.span(expr_start), SyntaxError::ArrowNotAllowed);
2321 }
2322 expect!(self, Token::Arrow);
2323
2324 let params: Vec<Pat> = self.parse_paren_items_as_params(paren_items, trailing_comma)?;
2325
2326 let body: Box<BlockStmtOrExpr> = self.parse_fn_block_or_expr_body(
2327 async_span.is_some(),
2328 false,
2329 true,
2330 params.is_simple_parameter_list(),
2331 )?;
2332 let arrow_expr = ArrowExpr {
2333 span: self.span(expr_start),
2334 is_async: async_span.is_some(),
2335 is_generator: false,
2336 params,
2337 body,
2338 return_type,
2339 ..Default::default()
2340 };
2341 if let BlockStmtOrExpr::BlockStmt(..) = &*arrow_expr.body {
2342 if self.input().cur().is_bin_op() {
2343 self.emit_err(self.input().cur_span(), SyntaxError::TS1005);
2345 let errorred_expr =
2346 self.parse_bin_op_recursively(Box::new(arrow_expr.into()), 0)?;
2347
2348 if !self.is_general_semi() {
2349 self.emit_err(self.input().cur_span(), SyntaxError::TS1005);
2351 }
2352
2353 return Ok(errorred_expr);
2354 }
2355 }
2356 return Ok(arrow_expr.into());
2357 } else {
2358 for expr_or_spread in paren_items.iter() {
2362 if let AssignTargetOrSpread::ExprOrSpread(e) = expr_or_spread {
2363 if let Expr::Object(o) = &*e.expr {
2364 for prop in o.props.iter() {
2365 if let PropOrSpread::Prop(prop) = prop {
2366 if let Prop::Assign(..) = **prop {
2367 self.emit_err(prop.span(), SyntaxError::AssignProperty);
2368 }
2369 }
2370 }
2371 }
2372 }
2373 }
2374 }
2375
2376 let expr_or_spreads = paren_items
2377 .into_iter()
2378 .map(|item| -> PResult<_> {
2379 match item {
2380 AssignTargetOrSpread::ExprOrSpread(e) => Ok(e),
2381 _ => syntax_error!(self, item.span(), SyntaxError::InvalidExpr),
2382 }
2383 })
2384 .collect::<Result<Vec<_>, _>>()?;
2385 if let Some(async_span) = async_span {
2386 return Ok(CallExpr {
2388 span: self.span(async_span.lo()),
2389 callee: Callee::Expr(Box::new(
2390 Ident::new_no_ctxt(atom!("async"), async_span).into(),
2391 )),
2392 args: expr_or_spreads,
2393 ..Default::default()
2394 }
2395 .into());
2396 }
2397
2398 if expr_or_spreads.is_empty() {
2401 syntax_error!(
2402 self,
2403 Span::new_with_checked(expr_start, self.last_pos()),
2404 SyntaxError::EmptyParenExpr
2405 );
2406 }
2407
2408 if expr_or_spreads.len() == 1 {
2412 let expr = match expr_or_spreads.into_iter().next().unwrap() {
2413 ExprOrSpread {
2414 spread: Some(..),
2415 ref expr,
2416 } => syntax_error!(self, expr.span(), SyntaxError::SpreadInParenExpr),
2417 ExprOrSpread { expr, .. } => expr,
2418 };
2419 Ok(ParenExpr {
2420 span: self.span(expr_start),
2421 expr,
2422 }
2423 .into())
2424 } else {
2425 debug_assert!(expr_or_spreads.len() >= 2);
2426
2427 let mut exprs = Vec::with_capacity(expr_or_spreads.len());
2428 for expr in expr_or_spreads {
2429 match expr {
2430 ExprOrSpread {
2431 spread: Some(..),
2432 ref expr,
2433 } => syntax_error!(self, expr.span(), SyntaxError::SpreadInParenExpr),
2434 ExprOrSpread { expr, .. } => exprs.push(expr),
2435 }
2436 }
2437 debug_assert!(exprs.len() >= 2);
2438
2439 let seq_expr = SeqExpr {
2441 span: Span::new_with_checked(
2442 exprs.first().unwrap().span_lo(),
2443 exprs.last().unwrap().span_hi(),
2444 ),
2445 exprs,
2446 }
2447 .into();
2448 Ok(ParenExpr {
2449 span: self.span(expr_start),
2450 expr: seq_expr,
2451 }
2452 .into())
2453 }
2454 }
2455
2456 fn parse_primary_expr_rest(
2457 &mut self,
2458 start: BytePos,
2459 can_be_arrow: bool,
2460 ) -> PResult<Box<Expr>> {
2461 let decorators = if self.input().is(Token::At) {
2462 Some(self.parse_decorators(false)?)
2463 } else {
2464 None
2465 };
2466
2467 let token_and_span = self.input().get_cur();
2468 let cur = token_and_span.token;
2469
2470 if cur == Token::Class {
2471 return self.parse_class_expr(start, decorators.unwrap_or_default());
2472 }
2473
2474 let try_parse_arrow_expr = |p: &mut Self, id: Ident, id_is_async| -> PResult<Box<Expr>> {
2475 if can_be_arrow && !p.input().had_line_break_before_cur() {
2476 if id_is_async && p.is_ident_ref() {
2477 let ctx = p.ctx();
2484 if ctx.contains(Context::ForLoopInit)
2485 && p.input().is(Token::Of)
2486 && !peek!(p).is_some_and(|peek| peek == Token::Arrow)
2487 {
2488 if !ctx.contains(Context::ForAwaitLoopInit) {
2494 p.emit_err(p.input().prev_span(), SyntaxError::TS1106);
2495 }
2496
2497 return Ok(id.into());
2498 }
2499
2500 let ident = p.parse_binding_ident(false)?;
2501 if p.input().syntax().typescript()
2502 && ident.sym == "as"
2503 && !p.input().is(Token::Arrow)
2504 {
2505 let type_ann = p.in_type(Self::parse_ts_type)?;
2507 return Ok(TsAsExpr {
2508 span: p.span(start),
2509 expr: Box::new(id.into()),
2510 type_ann,
2511 }
2512 .into());
2513 }
2514
2515 let arg = ident.into();
2517 let params = vec![arg];
2518 expect!(p, Token::Arrow);
2519 let body = p.parse_fn_block_or_expr_body(
2520 true,
2521 false,
2522 true,
2523 params.is_simple_parameter_list(),
2524 )?;
2525
2526 return Ok(ArrowExpr {
2527 span: p.span(start),
2528 body,
2529 params,
2530 is_async: true,
2531 is_generator: false,
2532 ..Default::default()
2533 }
2534 .into());
2535 } else if p.input_mut().eat(Token::Arrow) {
2536 if p.ctx().contains(Context::Strict) && id.is_reserved_in_strict_bind() {
2537 p.emit_strict_mode_err(id.span, SyntaxError::EvalAndArgumentsInStrict)
2538 }
2539 let params = vec![id.into()];
2540 let body = p.parse_fn_block_or_expr_body(
2541 false,
2542 false,
2543 true,
2544 params.is_simple_parameter_list(),
2545 )?;
2546
2547 return Ok(ArrowExpr {
2548 span: p.span(start),
2549 body,
2550 params,
2551 is_async: false,
2552 is_generator: false,
2553 ..Default::default()
2554 }
2555 .into());
2556 }
2557 }
2558
2559 Ok(id.into())
2560 };
2561
2562 let token_start = token_and_span.span.lo;
2563 if cur == Token::Let || (self.input().syntax().typescript() && cur == Token::Await) {
2564 let ctx = self.ctx();
2565 let id = self.parse_ident(
2566 !ctx.contains(Context::InGenerator),
2567 !ctx.contains(Context::InAsync),
2568 )?;
2569 try_parse_arrow_expr(self, id, false)
2570 } else if cur == Token::Hash {
2571 self.bump(); let id = self.parse_ident_name()?;
2573 Ok(PrivateName {
2574 span: self.span(start),
2575 name: id.sym,
2576 }
2577 .into())
2578 } else if cur == Token::Ident {
2579 let word = self.input_mut().expect_word_token_and_bump();
2580 if self.ctx().contains(Context::InClassField) && word == atom!("arguments") {
2581 self.emit_err(self.input().prev_span(), SyntaxError::ArgumentsInClassField)
2582 };
2583 let id = Ident::new_no_ctxt(word, self.span(token_start));
2584 try_parse_arrow_expr(self, id, false)
2585 } else if self.is_ident_ref() {
2586 let id_is_async = self.input().cur() == Token::Async;
2587 let word = self.input_mut().expect_word_token_and_bump();
2588 let id = Ident::new_no_ctxt(word, self.span(token_start));
2589 try_parse_arrow_expr(self, id, id_is_async)
2590 } else {
2591 syntax_error!(self, self.input().cur_span(), SyntaxError::TS1109)
2592 }
2593 }
2594
2595 fn try_parse_regexp(&mut self, start: BytePos) -> Option<Box<Expr>> {
2596 debug_assert!(self.input().cur() == Token::Slash || self.input().cur() == Token::DivEq);
2598
2599 self.input_mut().set_next_regexp(Some(start));
2600
2601 self.bump(); let cur = self.input().cur();
2604 if cur == Token::Regex {
2605 self.input_mut().set_next_regexp(None);
2606 let (exp, flags) = self.input_mut().expect_regex_token_and_bump();
2607 let span = self.span(start);
2608
2609 let mut flags_count =
2610 flags
2611 .chars()
2612 .fold(FxHashMap::<char, usize>::default(), |mut map, flag| {
2613 let key = match flag {
2614 'd' | 'g' | 'i' | 'm' | 's' | 'u' | 'v' | 'y' => flag,
2616 _ => '\u{0000}', };
2618 map.entry(key).and_modify(|count| *count += 1).or_insert(1);
2619 map
2620 });
2621
2622 if flags_count.remove(&'\u{0000}').is_some() {
2623 self.emit_err(span, SyntaxError::UnknownRegExpFlags);
2624 }
2625
2626 if let Some((flag, _)) = flags_count.iter().find(|(_, count)| **count > 1) {
2627 self.emit_err(span, SyntaxError::DuplicatedRegExpFlags(*flag));
2628 }
2629
2630 Some(Lit::Regex(Regex { span, exp, flags }).into())
2631 } else {
2632 None
2633 }
2634 }
2635
2636 fn try_parse_async_start(&mut self, can_be_arrow: bool) -> Option<PResult<Box<Expr>>> {
2637 if peek!(self).is_some_and(|peek| peek == Token::Function)
2638 && !self.input_mut().has_linebreak_between_cur_and_peeked()
2639 {
2640 return Some(self.parse_async_fn_expr());
2642 }
2643
2644 if can_be_arrow
2645 && self.input().syntax().typescript()
2646 && peek!(self).is_some_and(|peek| peek == Token::Lt)
2647 {
2648 if let Some(res) = self.try_parse_ts(|p| {
2650 let start = p.cur_pos();
2651 p.assert_and_bump(Token::Async);
2652 p.try_parse_ts_generic_async_arrow_fn(start)
2653 }) {
2654 return Some(Ok(res.into()));
2655 }
2656 }
2657
2658 if can_be_arrow
2659 && peek!(self).is_some_and(|peek| peek == Token::LParen)
2660 && !self.input_mut().has_linebreak_between_cur_and_peeked()
2661 {
2662 if let Err(e) = self.expect(Token::Async) {
2663 return Some(Err(e));
2664 }
2665 let async_span = self.input().prev_span();
2666 return Some(self.parse_paren_expr_or_arrow_fn(can_be_arrow, Some(async_span)));
2667 }
2668
2669 None
2670 }
2671
2672 fn parse_this_expr(&mut self, start: BytePos) -> PResult<Box<Expr>> {
2673 debug_assert!(self.input().cur() == Token::This);
2674 self.input_mut().bump();
2675 Ok(ThisExpr {
2676 span: self.span(start),
2677 }
2678 .into())
2679 }
2680
2681 pub(crate) fn is_start_of_left_hand_side_expr(&mut self) -> bool {
2682 let cur = self.input().cur();
2683 matches!(
2684 cur,
2685 Token::This
2686 | Token::Null
2687 | Token::Super
2688 | Token::True
2689 | Token::False
2690 | Token::Num
2691 | Token::BigInt
2692 | Token::Str
2693 | Token::NoSubstitutionTemplateLiteral
2694 | Token::TemplateHead
2695 | Token::LParen
2696 | Token::LBracket
2697 | Token::Function
2698 | Token::Class
2699 | Token::New
2700 | Token::Regex
2701 | Token::Import
2702 ) || cur.is_ident_ref(self.ctx())
2703 || cur == Token::BackQuote && {
2704 peek!(self)
2705 .is_some_and(|peek| matches!(peek, Token::LParen | Token::Lt | Token::Dot))
2706 }
2707 }
2708}
2709
2710fn unwrap_ts_non_null(mut expr: &Expr) -> &Expr {
2711 while let Expr::TsNonNull(ts_non_null) = expr {
2712 expr = &ts_non_null.expr;
2713 }
2714
2715 expr
2716}