1use super::class_or_object::ParseClassBodyResult;
2use super::class_or_object::ParseClassOrObjectMemberResult;
3use super::literal::normalise_literal_bigint;
4use super::literal::normalise_literal_string_or_template_inner;
5use super::pattern::is_valid_pattern_identifier;
6use super::pattern::ParsePatternRules;
7use super::ParseCtx;
8use super::Parser;
9use crate::ast::ArrayElement;
10use crate::ast::ArrayPatternElement;
11use crate::ast::ClassOrObjectMemberKey;
12use crate::ast::ClassOrObjectMemberValue;
13use crate::ast::LiteralTemplatePart;
14use crate::ast::Node;
15use crate::ast::ObjectMemberType;
16use crate::ast::Syntax;
17use crate::error::SyntaxErrorType;
18use crate::error::SyntaxResult;
19use crate::lex::lex_template_string_continue;
20use crate::lex::LexMode;
21use crate::lex::KEYWORDS_MAPPING;
22use crate::operator::Associativity;
23use crate::operator::OperatorName;
24use crate::operator::OPERATORS;
25use crate::parse::literal::normalise_literal_number;
26use crate::parse::literal::normalise_literal_string;
27use crate::parse::operator::MULTARY_OPERATOR_MAPPING;
28use crate::parse::operator::UNARY_OPERATOR_MAPPING;
29use crate::token::TokenType;
30
31pub struct Asi {
32 pub can_end_with_asi: bool,
33 pub did_end_with_asi: bool,
34}
35
36impl Asi {
37 pub fn can() -> Asi {
38 Asi {
39 can_end_with_asi: true,
40 did_end_with_asi: false,
41 }
42 }
43
44 pub fn no() -> Asi {
45 Asi {
46 can_end_with_asi: false,
47 did_end_with_asi: false,
48 }
49 }
50}
51
52fn is_chevron_right_or_slash(typ: TokenType) -> bool {
53 typ == TokenType::ChevronRight || typ == TokenType::Slash
54}
55
56fn jsx_tag_names_are_equal(a: Option<&Syntax>, b: Option<&Syntax>) -> bool {
57 let (Some(a), Some(b)) = (a, b) else {
58 return a.is_none() && b.is_none();
59 };
60 match (a, b) {
61 (
62 Syntax::JsxMemberExpression {
63 base: a_base,
64 path: a_path,
65 },
66 Syntax::JsxMemberExpression {
67 base: b_base,
68 path: b_path,
69 },
70 ) => a_base.as_ident() == b_base.as_ident() && a_path == b_path,
71 (
72 Syntax::JsxName {
73 name: a_name,
74 namespace: a_ns,
75 },
76 Syntax::JsxName {
77 name: b_name,
78 namespace: b_ns,
79 },
80 ) => a_ns == b_ns && a_name == b_name,
81 (Syntax::IdentifierExpr { name: a_name }, Syntax::IdentifierExpr { name: b_name }) => {
82 a_name == b_name
83 }
84 _ => false,
85 }
86}
87
88impl<'a> Parser<'a> {
89 fn transform_literal_expr_to_destructuring_pattern(
91 &self,
92 ctx: ParseCtx,
93 node: Node,
94 ) -> SyntaxResult<Node> {
95 let loc = node.loc;
96 match *node.stx {
97 Syntax::LiteralArrayExpr { elements } => {
98 let mut pat_elements = Vec::<Option<ArrayPatternElement>>::new();
99 let mut rest = None;
100 for element in elements {
101 if rest.is_some() {
102 return Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None));
103 };
104 match element {
105 ArrayElement::Single(elem) => {
106 match *elem.stx {
107 Syntax::BinaryExpr {
108 parenthesised,
109 operator,
110 left,
111 right,
112 } => {
113 if parenthesised || operator != OperatorName::Assignment {
114 return Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None));
115 };
116 pat_elements.push(Some(ArrayPatternElement {
117 target: self.transform_literal_expr_to_destructuring_pattern(ctx, left)?,
118 default_value: Some(right),
119 }));
120 }
121 _ => pat_elements.push(Some(ArrayPatternElement {
122 target: self.transform_literal_expr_to_destructuring_pattern(ctx, elem)?,
123 default_value: None,
124 })),
125 };
126 }
127 ArrayElement::Rest(expr) => {
128 rest = Some(self.transform_literal_expr_to_destructuring_pattern(ctx, expr)?);
129 }
130 ArrayElement::Empty => pat_elements.push(None),
131 };
132 }
133 Ok(Node::new(loc, Syntax::ArrayPattern {
134 elements: pat_elements,
135 rest,
136 }))
137 }
138 Syntax::LiteralObjectExpr { members } => {
139 let mut properties = Vec::new();
140 let mut rest = None;
141 for member in members {
142 if rest.is_some() {
143 return Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None));
144 };
145 match *member.stx {
146 Syntax::ObjectMember { typ } => match typ {
147 ObjectMemberType::Valued { key, value } => {
148 let (target, default_value) = match value {
149 ClassOrObjectMemberValue::Property {
150 initializer: Some(initializer),
151 } => match *initializer.stx {
152 Syntax::BinaryExpr {
153 parenthesised,
154 operator,
155 left,
156 right,
157 } => {
158 if parenthesised || operator != OperatorName::Assignment {
159 return Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None));
160 };
161 (
162 self.transform_literal_expr_to_destructuring_pattern(ctx, left)?,
163 Some(right),
164 )
165 }
166 _ => (
167 self.transform_literal_expr_to_destructuring_pattern(ctx, initializer)?,
168 None,
169 ),
170 },
171 _ => return Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None)),
172 };
173 properties.push(Node::new(loc, Syntax::ObjectPatternProperty {
174 key,
175 target,
176 default_value,
177 shorthand: true,
178 }));
179 }
180 ObjectMemberType::Shorthand { identifier } => {
181 properties.push(Node::new(loc, Syntax::ObjectPatternProperty {
182 key: ClassOrObjectMemberKey::Direct(self.string(identifier.loc)),
183 target: Node::new(loc, Syntax::IdentifierPattern {
184 name: self.string(identifier.loc),
185 }),
186 default_value: None,
187 shorthand: true,
188 }));
189 }
190 ObjectMemberType::Rest { value } => {
191 rest = Some(self.transform_literal_expr_to_destructuring_pattern(ctx, value)?);
192 }
193 },
194 _ => unreachable!(),
195 };
196 }
197 Ok(Node::new(loc, Syntax::ObjectPattern { properties, rest }))
198 }
199 Syntax::IdentifierExpr { name } | Syntax::IdentifierPattern { name } => {
201 Ok(Node::new(loc, Syntax::IdentifierPattern {
202 name: name.clone(),
203 }))
204 }
205 _ => Err(loc.error(SyntaxErrorType::InvalidAssigmentTarget, None)),
206 }
207 }
208
209 fn convert_assignment_lhs_to_target(
213 &self,
214 ctx: ParseCtx,
215 lhs: Node,
216 operator_name: OperatorName,
217 ) -> SyntaxResult<Node> {
218 match lhs.stx.as_ref() {
219 e @ (Syntax::LiteralArrayExpr { .. }
220 | Syntax::LiteralObjectExpr { .. }
221 | Syntax::IdentifierExpr { .. }) => {
222 if operator_name != OperatorName::Assignment
223 && match e {
224 Syntax::IdentifierExpr { .. } => false,
225 _ => true,
226 }
227 {
228 return Err(lhs.error(SyntaxErrorType::InvalidAssigmentTarget));
229 }
230 let root = self.transform_literal_expr_to_destructuring_pattern(ctx, lhs)?;
232 Ok(root)
233 }
234 Syntax::ComputedMemberExpr {
235 optional_chaining, ..
236 }
237 | Syntax::MemberExpr {
238 optional_chaining, ..
239 } if !optional_chaining => {
240 Ok(lhs)
243 }
244 _ => Err(lhs.error(SyntaxErrorType::InvalidAssigmentTarget)),
245 }
246 }
247
248 pub fn parse_jsx_name(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
249 let start = self.require_with_mode(TokenType::Identifier, LexMode::JsxTag)?;
250 Ok(if self.consume_if(TokenType::Colon)?.is_match() {
251 let name = self.require_with_mode(TokenType::Identifier, LexMode::JsxTag)?;
252 Node::new(start.loc + name.loc, Syntax::JsxName {
253 namespace: Some(self.string(start.loc)),
254 name: self.string(name.loc),
255 })
256 } else {
257 Node::new(start.loc, Syntax::JsxName {
258 namespace: None,
259 name: self.string(start.loc),
260 })
261 })
262 }
263
264 pub fn parse_jsx_tag_name(&mut self, ctx: ParseCtx) -> SyntaxResult<Option<Node>> {
265 Ok(
266 match self
267 .maybe_with_mode(TokenType::Identifier, LexMode::JsxTag)?
268 .match_loc()
269 {
270 None => None,
272 Some(start) => Some({
273 if self.consume_if(TokenType::Colon)?.is_match() {
274 let name = self.require_with_mode(TokenType::Identifier, LexMode::JsxTag)?;
276 Node::new(start + name.loc, Syntax::JsxName {
277 namespace: Some(self.string(start)),
278 name: self.string(name.loc),
279 })
280 } else if self.peek()?.typ == TokenType::Dot && !self.str(start).contains('-') {
281 let mut path = Vec::new();
283 let mut loc = start;
284 while self.consume_if(TokenType::Dot)?.is_match() {
285 let l = self.require(TokenType::Identifier)?.loc;
286 path.push(self.string(l));
287 loc += l;
288 }
289 Node::new(loc, Syntax::JsxMemberExpression {
290 base: Node::new(start, Syntax::IdentifierExpr {
291 name: self.string(start),
292 }),
293 path,
294 })
295 } else if !self.bytes(start)[0].is_ascii_lowercase() {
296 Node::new(start, Syntax::IdentifierExpr {
298 name: self.string(start),
299 })
300 } else {
301 Node::new(start, Syntax::JsxName {
303 namespace: None,
304 name: self.string(start),
305 })
306 }
307 }),
308 },
309 )
310 }
311
312 pub fn parse_jsx_element(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
314 let tag_start = self.require(TokenType::ChevronLeft)?;
315 let tag_name = self.parse_jsx_tag_name(ctx)?;
316
317 let mut attributes = Vec::new();
319 if tag_name.is_some() {
320 loop {
321 if is_chevron_right_or_slash(self.peek()?.typ) {
322 break;
323 }
324 if self.consume_if(TokenType::BraceOpen)?.is_match() {
325 let start = self.require(TokenType::DotDotDot)?;
326 let value = self.parse_expr(ctx, TokenType::BraceClose)?;
327 let end = self.require(TokenType::BraceClose)?;
328 attributes.push(Node::new(start.loc + end.loc, Syntax::JsxSpreadAttribute {
329 value,
330 }));
331 continue;
332 }
333
334 let name = self.parse_jsx_name(ctx)?;
335 let value = if !self.consume_if(TokenType::Equals)?.is_match() {
336 None
337 } else {
338 Some(if self.consume_if(TokenType::BraceOpen)?.is_match() {
341 let value = self.parse_expr(ctx, TokenType::BraceClose)?;
342 let expr = Node::new(value.loc, Syntax::JsxExpressionContainer { value });
343 self.require(TokenType::BraceClose)?;
344 expr
345 } else {
346 let value = self.require(TokenType::LiteralString)?;
347 Node::new(value.loc, Syntax::JsxText {
348 value: self.string(value.loc),
349 })
350 })
351 };
352 attributes.push(Node::new(
353 name.loc.add_option(value.as_ref().map(|n| n.loc)),
354 Syntax::JsxAttribute { name, value },
355 ))
356 }
357 }
358
359 Ok(if self.consume_if(TokenType::Slash)?.is_match() {
360 let end = self.require(TokenType::ChevronRight)?;
362 Node::new(tag_start.loc + end.loc, Syntax::JsxElement {
363 name: tag_name,
364 attributes,
365 children: Vec::new(),
366 })
367 } else {
368 self.require(TokenType::ChevronRight)?;
369
370 let mut children = Vec::new();
372 let close_start = loop {
373 match self.peek()? {
374 t if t.typ == TokenType::ChevronLeftSlash => {
375 break self.consume_peeked();
376 }
377 t if t.typ == TokenType::EOF => {
378 return Err(t.error(SyntaxErrorType::UnexpectedEnd));
379 }
380 _ => {}
381 };
382 let text = self.require_with_mode(TokenType::JsxTextContent, LexMode::JsxTextContent)?;
383 if !text.loc.is_empty() {
384 children.push(Node::new(text.loc, Syntax::JsxText {
385 value: self.string(text.loc),
386 }));
387 };
388 if self.peek()?.typ == TokenType::ChevronLeft {
389 children.push(self.parse_jsx_element(ctx)?);
390 };
391 if self.consume_if(TokenType::BraceOpen)?.is_match() {
392 let value = self.parse_expr(ctx, TokenType::BraceClose)?;
394 children.push(Node::new(value.loc, Syntax::JsxExpressionContainer {
395 value,
396 }));
397 self.require(TokenType::BraceClose)?;
398 };
399 };
400 let end_name = self.parse_jsx_tag_name(ctx)?;
401 if !jsx_tag_names_are_equal(
402 tag_name.as_ref().map(|n| n.stx.as_ref()),
403 end_name.as_ref().map(|n| n.stx.as_ref()),
404 ) {
405 return Err(close_start.error(SyntaxErrorType::JsxClosingTagMismatch));
406 };
407 let end = self.require(TokenType::ChevronRight)?;
408 Node::new(tag_start.loc + end.loc, Syntax::JsxElement {
409 name: tag_name,
410 attributes,
411 children,
412 })
413 })
414 }
415
416 pub fn parse_call_args(&mut self, ctx: ParseCtx) -> SyntaxResult<Vec<Node>> {
417 let mut args = Vec::new();
418 loop {
419 if self.peek()?.typ == TokenType::ParenthesisClose {
420 break;
421 };
422 let spread = self.consume_if(TokenType::DotDotDot)?.is_match();
423 let value =
424 self.parse_expr_until_either(ctx, TokenType::Comma, TokenType::ParenthesisClose)?;
425 args.push(Node::new(value.loc, Syntax::CallArg { spread, value }));
426 if !self.consume_if(TokenType::Comma)?.is_match() {
427 break;
428 };
429 }
430 Ok(args)
431 }
432
433 pub fn parse_expr(&mut self, ctx: ParseCtx, terminator: TokenType) -> SyntaxResult<Node> {
434 self.parse_expr_with_min_prec(ctx, 1, terminator, TokenType::_Dummy, false, &mut Asi::no())
435 }
436
437 pub fn parse_expr_with_asi(
438 &mut self,
439 ctx: ParseCtx,
440 terminator: TokenType,
441 asi: &mut Asi,
442 ) -> SyntaxResult<Node> {
443 self.parse_expr_with_min_prec(ctx, 1, terminator, TokenType::_Dummy, false, asi)
444 }
445
446 pub fn parse_expr_until_either(
447 &mut self,
448 ctx: ParseCtx,
449 terminator_a: TokenType,
450 terminator_b: TokenType,
451 ) -> SyntaxResult<Node> {
452 self.parse_expr_with_min_prec(ctx, 1, terminator_a, terminator_b, false, &mut Asi::no())
453 }
454
455 pub fn parse_expr_until_either_with_asi(
456 &mut self,
457 ctx: ParseCtx,
458 terminator_a: TokenType,
459 terminator_b: TokenType,
460 asi: &mut Asi,
461 ) -> SyntaxResult<Node> {
462 self.parse_expr_with_min_prec(ctx, 1, terminator_a, terminator_b, false, asi)
463 }
464
465 pub fn parse_grouping(&mut self, ctx: ParseCtx, asi: &mut Asi) -> SyntaxResult<Node> {
466 self.require(TokenType::ParenthesisOpen)?;
467 let expr = self.parse_expr_with_min_prec(
468 ctx,
469 1,
470 TokenType::ParenthesisClose,
471 TokenType::_Dummy,
472 true,
473 asi,
474 )?;
475 self.require(TokenType::ParenthesisClose)?;
476 Ok(expr)
477 }
478
479 pub fn parse_expr_array(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
480 let loc_start = self.require(TokenType::BracketOpen)?.loc;
481 let mut elements = Vec::<ArrayElement>::new();
482 loop {
483 if self.consume_if(TokenType::Comma)?.is_match() {
484 elements.push(ArrayElement::Empty);
485 continue;
486 };
487 if self.peek()?.typ == TokenType::BracketClose {
488 break;
489 };
490 let rest = self.consume_if(TokenType::DotDotDot)?.is_match();
491 let value = self.parse_expr_until_either(ctx, TokenType::Comma, TokenType::BracketClose)?;
492 elements.push(if rest {
493 ArrayElement::Rest(value)
494 } else {
495 ArrayElement::Single(value)
496 });
497 if self.peek()?.typ == TokenType::BracketClose {
498 break;
499 };
500 self.require(TokenType::Comma)?;
501 }
502 let loc_end = self.require(TokenType::BracketClose)?.loc;
503 Ok(Node::new(loc_start + loc_end, Syntax::LiteralArrayExpr {
504 elements,
505 }))
506 }
507
508 pub fn parse_expr_object(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
509 let loc_start = self.require(TokenType::BraceOpen)?.loc;
510 let mut members = Vec::<Node>::new();
511 loop {
512 if self.peek()?.typ == TokenType::BraceClose {
513 break;
514 };
515 let rest = self.consume_if(TokenType::DotDotDot)?.is_match();
516 if rest {
517 let value = self.parse_expr_until_either(ctx, TokenType::Comma, TokenType::BraceClose)?;
518 let loc = value.loc;
519 members.push(Node::new(loc, Syntax::ObjectMember {
520 typ: ObjectMemberType::Rest { value },
521 }));
522 } else {
523 let loc_checkpoint = self.checkpoint();
524 let ParseClassOrObjectMemberResult {
525 key,
526 key_loc,
527 value,
528 ..
529 } = self.parse_class_or_object_member(
530 ctx,
531 TokenType::Colon,
532 TokenType::Comma,
533 &mut Asi::no(),
534 )?;
535 members.push(Node::new(
536 self.since_checkpoint(loc_checkpoint),
537 Syntax::ObjectMember {
538 typ: match value {
539 ClassOrObjectMemberValue::Property { initializer: None } => {
540 ObjectMemberType::Shorthand {
541 identifier: match key {
542 ClassOrObjectMemberKey::Direct(key) => {
543 Node::new(key_loc, Syntax::IdentifierExpr { name: key })
544 }
545 _ => unreachable!(),
546 },
547 }
548 }
549 _ => ObjectMemberType::Valued { key, value },
550 },
551 },
552 ));
553 }
554 if self.peek()?.typ == TokenType::BraceClose {
555 break;
556 };
557 self.require(TokenType::Comma)?;
558 }
559 let loc_end = self.require(TokenType::BraceClose)?.loc;
560 Ok(Node::new(loc_start + loc_end, Syntax::LiteralObjectExpr {
561 members,
562 }))
563 }
564
565 pub fn parse_expr_arrow_function(
566 &mut self,
567 ctx: ParseCtx,
568 terminator_a: TokenType,
569 terminator_b: TokenType,
570 ) -> SyntaxResult<Node> {
571 let is_async = self.consume_if(TokenType::KeywordAsync)?.is_match();
572
573 let (parameters, arrow) = if !is_async
574 && is_valid_pattern_identifier(self.peek()?.typ, ParsePatternRules {
575 await_allowed: false,
576 yield_allowed: ctx.rules.yield_allowed,
577 }) {
578 let param_name = self.next()?.loc;
581 let arrow = self.require(TokenType::EqualsChevronRight)?;
582 let pattern = Node::new(param_name, Syntax::IdentifierPattern {
583 name: self.string(param_name),
584 });
585 let param = Node::new(param_name, Syntax::ParamDecl {
586 rest: false,
587 pattern,
588 default_value: None,
589 });
590 (vec![param], arrow)
591 } else {
592 let params = self.parse_function_parameters(ctx)?;
593 let arrow = self.require(TokenType::EqualsChevronRight)?;
594 (params, arrow)
595 };
596
597 if arrow.preceded_by_line_terminator {
598 return Err(arrow.error(SyntaxErrorType::LineTerminatorAfterArrowFunctionParameters));
600 }
601 let fn_body_ctx = ctx.with_rules(ParsePatternRules {
602 await_allowed: !is_async && ctx.rules.await_allowed,
603 ..ctx.rules
604 });
605 let body = match self.peek()?.typ {
606 TokenType::BraceOpen => self.parse_function_body(fn_body_ctx)?,
607 _ => self.parse_expr_until_either_with_asi(
608 fn_body_ctx,
609 terminator_a,
610 terminator_b,
611 &mut Asi::can(),
612 )?,
613 };
614 Ok(Node::new(body.loc, Syntax::ArrowFunctionExpr {
615 parenthesised: false,
616 function: Node::new(body.loc, Syntax::Function {
617 arrow: true,
618 async_: is_async,
619 generator: false,
620 parameters,
621 body,
622 }),
623 }))
624 }
625
626 pub fn parse_expr_arrow_function_or_grouping(
627 &mut self,
628 ctx: ParseCtx,
629 terminator_a: TokenType,
630 terminator_b: TokenType,
631 asi: &mut Asi,
632 ) -> SyntaxResult<Node> {
633 let cp = self.checkpoint();
644
645 match self.parse_expr_arrow_function(ctx, terminator_a, terminator_b) {
646 Ok(expr) => Ok(expr),
647 Err(err) if err.typ == SyntaxErrorType::LineTerminatorAfterArrowFunctionParameters => {
648 Err(err)
649 }
650 Err(_) => {
651 self.restore_checkpoint(cp);
652 self.parse_grouping(ctx, asi)
653 }
654 }
655 }
656
657 pub fn parse_expr_import(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
658 let start = self.require(TokenType::KeywordImport)?;
659 if self.consume_if(TokenType::Dot)?.is_match() {
660 let prop = self.require(TokenType::Identifier)?;
662 if self.str(prop.loc) != "meta" {
663 return Err(prop.error(SyntaxErrorType::ExpectedSyntax("`meta` property")));
664 };
665 return Ok(Node::new(start.loc + prop.loc, Syntax::ImportMeta {}));
666 }
667 self.require(TokenType::ParenthesisOpen)?;
668 let module = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
669 let end = self.require(TokenType::ParenthesisClose)?;
670 Ok(Node::new(start.loc + end.loc, Syntax::ImportExpr {
671 module,
672 }))
673 }
674
675 pub fn parse_expr_function(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
676 let is_async = self.consume_if(TokenType::KeywordAsync)?.is_match();
677 let start = self.require(TokenType::KeywordFunction)?.loc;
678 let generator = self.consume_if(TokenType::Asterisk)?.is_match();
679 let name = match self.peek()? {
680 t if is_valid_pattern_identifier(t.typ, ctx.rules) => {
681 self.consume_peeked();
682 Some(Node::new(t.loc, Syntax::ClassOrFunctionName {
683 name: self.string(t.loc),
684 }))
685 }
686 _ => None,
687 };
688 let parameters = self.parse_function_parameters(ctx)?;
689 let fn_body_ctx = ctx.with_rules(ParsePatternRules {
690 await_allowed: !is_async && ctx.rules.await_allowed,
691 yield_allowed: !generator && ctx.rules.yield_allowed,
692 });
693 let body = self.parse_function_body(fn_body_ctx)?;
694 Ok(Node::new(start + body.loc, Syntax::FunctionExpr {
695 parenthesised: false,
696 name,
697 function: Node::new(start + body.loc, Syntax::Function {
698 arrow: false,
699 async_: is_async,
700 generator,
701 parameters,
702 body,
703 }),
704 }))
705 }
706
707 pub fn parse_expr_class(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
708 let start = self.require(TokenType::KeywordClass)?.loc;
709 let name = match self.peek()? {
710 t if is_valid_pattern_identifier(t.typ, ctx.rules) => {
711 self.consume_peeked();
712 let name_node = Node::new(t.loc, Syntax::ClassOrFunctionName {
713 name: self.string(t.loc),
714 });
715 Some(name_node)
716 }
717 _ => None,
718 };
719 let extends = if self.consume_if(TokenType::KeywordExtends)?.is_match() {
720 Some(self.parse_expr(ctx, TokenType::BraceOpen)?)
721 } else {
722 None
723 };
724 let ParseClassBodyResult { end, members } = self.parse_class_body(ctx)?;
725 Ok(Node::new(start + end, Syntax::ClassExpr {
726 parenthesised: false,
727 name,
728 extends,
729 members,
730 }))
731 }
732
733 fn parse_expr_literal_template_parts(
735 &mut self,
736 ctx: ParseCtx,
737 ) -> SyntaxResult<Vec<LiteralTemplatePart>> {
738 let t = self.next().unwrap();
739 let is_end = match t.typ {
740 TokenType::LiteralTemplatePartString => false,
741 TokenType::LiteralTemplatePartStringEnd => true,
742 _ => unreachable!(),
743 };
744
745 let mut loc = t.loc;
746 let mut parts = Vec::new();
747 parts.push(LiteralTemplatePart::String(
748 normalise_literal_string_or_template_inner(self.bytes(t.loc))
749 .ok_or_else(|| t.loc.error(SyntaxErrorType::InvalidCharacterEscape, None))?,
750 ));
751 if !is_end {
752 loop {
753 let substitution = self.parse_expr(ctx, TokenType::BraceClose)?;
754 self.require(TokenType::BraceClose)?;
755 parts.push(LiteralTemplatePart::Substitution(substitution));
756 let string = lex_template_string_continue(self.lexer_mut(), false)?;
757 loc.extend(string.loc);
758 parts.push(LiteralTemplatePart::String(
759 normalise_literal_string_or_template_inner(self.bytes(string.loc)).ok_or_else(|| {
760 string
761 .loc
762 .error(SyntaxErrorType::InvalidCharacterEscape, None)
763 })?,
764 ));
765 self.clear_buffered();
766 match string.typ {
767 TokenType::LiteralTemplatePartStringEnd => break,
768 _ => {}
769 };
770 }
771 };
772
773 Ok(parts)
774 }
775
776 fn parse_expr_operand(
777 &mut self,
778 ctx: ParseCtx,
779 terminator_a: TokenType,
780 terminator_b: TokenType,
781 asi: &mut Asi,
782 ) -> SyntaxResult<Node> {
783 let cp = self.checkpoint();
784 let t = self.next_with_mode(LexMode::SlashIsRegex)?;
785 let operand = match UNARY_OPERATOR_MAPPING.get(&t.typ) {
786 Some(operator)
787 if (
788 (operator.name != OperatorName::Await && operator.name != OperatorName::Yield)
790 || (operator.name == OperatorName::Await && !ctx.rules.await_allowed)
791 || (operator.name == OperatorName::Yield && !ctx.rules.yield_allowed)
792 ) =>
793 {
794 let operator = if operator.name == OperatorName::Yield
795 && self.consume_if(TokenType::Asterisk)?.is_match()
796 {
797 &OPERATORS[&OperatorName::YieldDelegated]
798 } else {
799 *operator
800 };
801 let next_min_prec =
802 operator.precedence + (operator.associativity == Associativity::Left) as u8;
803 let operand = self.parse_expr_with_min_prec(
804 ctx,
805 next_min_prec,
806 terminator_a,
807 terminator_b,
808 false,
809 asi,
810 )?;
811 Node::new(t.loc + operand.loc, Syntax::UnaryExpr {
812 parenthesised: false,
813 operator: operator.name,
814 argument: operand,
815 })
816 }
817 _ => {
818 match t.typ {
819 TokenType::BracketOpen => {
820 self.restore_checkpoint(cp);
821 self.parse_expr_array(ctx)?
822 }
823 TokenType::BraceOpen => {
824 self.restore_checkpoint(cp);
825 self.parse_expr_object(ctx)?
826 }
827 TokenType::ChevronLeft => {
828 self.restore_checkpoint(cp);
829 self.parse_jsx_element(ctx)?
830 }
831 TokenType::KeywordAsync => {
833 match self.peek()?.typ {
834 TokenType::ParenthesisOpen => {
835 self.restore_checkpoint(cp);
836 self.parse_expr_arrow_function(ctx, terminator_a, terminator_b)?
837 }
838 TokenType::KeywordFunction => {
839 self.restore_checkpoint(cp);
840 self.parse_expr_function(ctx)?
841 }
842 _ => {
843 Node::new(t.loc, Syntax::IdentifierExpr {
845 name: self.string(t.loc),
846 })
847 }
848 }
849 }
850 typ if is_valid_pattern_identifier(typ, ctx.rules) => {
851 if self.peek()?.typ == TokenType::EqualsChevronRight {
852 self.restore_checkpoint(cp);
855 self.parse_expr_arrow_function(ctx, terminator_a, terminator_b)?
856 } else {
857 Node::new(t.loc, Syntax::IdentifierExpr {
858 name: self.string(t.loc),
859 })
860 }
861 }
862 TokenType::KeywordClass => {
863 self.restore_checkpoint(cp);
864 self.parse_expr_class(ctx)?
865 }
866 TokenType::KeywordFunction => {
867 self.restore_checkpoint(cp);
868 self.parse_expr_function(ctx)?
869 }
870 TokenType::KeywordImport => {
871 self.restore_checkpoint(cp);
872 self.parse_expr_import(ctx)?
873 }
874 TokenType::KeywordSuper => Node::new(t.loc, Syntax::SuperExpr {}),
875 TokenType::KeywordThis => Node::new(t.loc, Syntax::ThisExpr {}),
876 TokenType::LiteralBigInt => Node::new(t.loc, Syntax::LiteralBigIntExpr {
877 value: normalise_literal_bigint(self.str(t.loc))
878 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteralBigInt, None))?,
879 }),
880 TokenType::LiteralTrue | TokenType::LiteralFalse => {
881 Node::new(t.loc, Syntax::LiteralBooleanExpr {
882 value: t.typ == TokenType::LiteralTrue,
883 })
884 }
885 TokenType::LiteralNull => Node::new(t.loc, Syntax::LiteralNull {}),
886 TokenType::LiteralNumber => Node::new(t.loc, Syntax::LiteralNumberExpr {
887 value: normalise_literal_number(self.str(t.loc))
888 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteralNumber, None))?,
889 }),
890 TokenType::LiteralRegex => Node::new(t.loc, Syntax::LiteralRegexExpr {
891 value: self.string(t.loc),
892 }),
893 TokenType::LiteralString => Node::new(t.loc, Syntax::LiteralStringExpr {
894 value: normalise_literal_string(self.str(t.loc))
895 .ok_or_else(|| t.loc.error(SyntaxErrorType::InvalidCharacterEscape, None))?,
896 }),
897 TokenType::LiteralTemplatePartString | TokenType::LiteralTemplatePartStringEnd => {
898 self.restore_checkpoint(cp);
899 let parts = self.parse_expr_literal_template_parts(ctx)?;
900 Node::new(t.loc, Syntax::LiteralTemplateExpr { parts })
901 }
902 TokenType::ParenthesisOpen => {
903 self.restore_checkpoint(cp);
904 self.parse_expr_arrow_function_or_grouping(ctx, terminator_a, terminator_b, asi)?
905 }
906 _ => return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operand"))),
907 }
908 }
909 };
910 Ok(operand)
911 }
912
913 pub fn parse_expr_with_min_prec(
914 &mut self,
915 ctx: ParseCtx,
916 min_prec: u8,
917 terminator_a: TokenType,
918 terminator_b: TokenType,
919 parenthesised: bool,
920 asi: &mut Asi,
921 ) -> SyntaxResult<Node> {
922 let mut left = self.parse_expr_operand(ctx, terminator_a, terminator_b, asi)?;
923
924 loop {
925 let cp = self.checkpoint();
926 let t = self.next()?;
927
928 if t.typ == terminator_a || t.typ == terminator_b {
929 self.restore_checkpoint(cp);
930 break;
931 };
932
933 match t.typ {
934 TokenType::PlusPlus | TokenType::HyphenHyphen if !t.preceded_by_line_terminator => {
936 let operator_name = match t.typ {
937 TokenType::PlusPlus => OperatorName::PostfixIncrement,
938 TokenType::HyphenHyphen => OperatorName::PostfixDecrement,
939 _ => unreachable!(),
940 };
941 let operator = &OPERATORS[&operator_name];
942 if operator.precedence < min_prec {
943 self.restore_checkpoint(cp);
944 break;
945 };
946 left = Node::new(left.loc + t.loc, Syntax::UnaryPostfixExpr {
947 parenthesised: false,
948 operator: operator_name,
949 argument: left,
950 });
951 continue;
952 }
953 TokenType::LiteralTemplatePartString | TokenType::LiteralTemplatePartStringEnd
955 if !t.preceded_by_line_terminator =>
956 {
957 let loc = t.loc;
958 self.restore_checkpoint(cp);
959 let parts = self.parse_expr_literal_template_parts(ctx)?;
960 left = Node::new(left.loc + loc, Syntax::TaggedTemplateExpr {
961 function: left,
962 parts,
963 });
964 continue;
965 }
966 _ => {}
967 };
968
969 match MULTARY_OPERATOR_MAPPING.get(&t.typ) {
970 None => {
971 if asi.can_end_with_asi
972 && (t.preceded_by_line_terminator
973 || t.typ == TokenType::BraceClose
974 || t.typ == TokenType::EOF)
975 {
976 self.restore_checkpoint(cp);
979 asi.did_end_with_asi = true;
980 break;
981 };
982 return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operator")));
983 }
984 Some(operator) => {
985 if operator.precedence < min_prec {
986 self.restore_checkpoint(cp);
987 break;
988 };
989
990 let next_min_prec =
991 operator.precedence + (operator.associativity == Associativity::Left) as u8;
992
993 left = match operator.name {
994 OperatorName::Call | OperatorName::OptionalChainingCall => {
995 let arguments = self.parse_call_args(ctx)?;
996 let end = self.require(TokenType::ParenthesisClose)?;
997 Node::new(left.loc + end.loc, Syntax::CallExpr {
998 parenthesised: false,
999 optional_chaining: match operator.name {
1000 OperatorName::OptionalChainingCall => true,
1001 _ => false,
1002 },
1003 arguments,
1004 callee: left,
1005 })
1006 }
1007 OperatorName::ComputedMemberAccess
1008 | OperatorName::OptionalChainingComputedMemberAccess => {
1009 let member = self.parse_expr(ctx, TokenType::BracketClose)?;
1010 let end = self.require(TokenType::BracketClose)?;
1011 Node::new(left.loc + end.loc, Syntax::ComputedMemberExpr {
1012 optional_chaining: match operator.name {
1013 OperatorName::OptionalChainingComputedMemberAccess => true,
1014 _ => false,
1015 },
1016 object: left,
1017 member,
1018 })
1019 }
1020 OperatorName::Conditional => {
1021 let consequent = self.parse_expr(ctx, TokenType::Colon)?;
1022 self.require(TokenType::Colon)?;
1023 let alternate = self.parse_expr_with_min_prec(
1024 ctx,
1025 OPERATORS[&OperatorName::ConditionalAlternate].precedence,
1026 terminator_a,
1027 terminator_b,
1028 false,
1029 asi,
1030 )?;
1031 Node::new(left.loc + alternate.loc, Syntax::ConditionalExpr {
1032 parenthesised: false,
1033 test: left,
1034 consequent,
1035 alternate,
1036 })
1037 }
1038 OperatorName::MemberAccess | OperatorName::OptionalChainingMemberAccess => {
1039 let right_tok = self.next()?;
1040 match right_tok.typ {
1041 TokenType::Identifier => {}
1042 TokenType::PrivateMember => {}
1043 t if KEYWORDS_MAPPING.contains_key(&t) => {}
1044 _ => {
1045 return Err(
1046 right_tok.error(SyntaxErrorType::ExpectedSyntax("member access property")),
1047 )
1048 }
1049 };
1050 let right = right_tok.loc;
1051 Node::new(left.loc + right, Syntax::MemberExpr {
1052 parenthesised: false,
1053 optional_chaining: match operator.name {
1054 OperatorName::OptionalChainingMemberAccess => true,
1055 _ => false,
1056 },
1057 left,
1058 right: self.string(right),
1059 })
1060 }
1061 _ => {
1062 if operator.name.is_assignment() {
1063 left = self.convert_assignment_lhs_to_target(ctx, left, operator.name)?;
1064 };
1065 let right = self.parse_expr_with_min_prec(
1066 ctx,
1067 next_min_prec,
1068 terminator_a,
1069 terminator_b,
1070 false,
1071 asi,
1072 )?;
1073 Node::new(left.loc + right.loc, Syntax::BinaryExpr {
1074 parenthesised: false,
1075 operator: operator.name,
1076 left,
1077 right,
1078 })
1079 }
1080 };
1081 }
1082 };
1083 }
1084
1085 if parenthesised {
1086 match left.stx.as_mut() {
1087 Syntax::ArrowFunctionExpr { parenthesised, .. }
1088 | Syntax::BinaryExpr { parenthesised, .. }
1089 | Syntax::CallExpr { parenthesised, .. }
1090 | Syntax::ConditionalExpr { parenthesised, .. }
1091 | Syntax::FunctionExpr { parenthesised, .. }
1092 | Syntax::MemberExpr { parenthesised, .. }
1093 | Syntax::UnaryExpr { parenthesised, .. } => {
1094 *parenthesised = true;
1095 }
1096 _ => {}
1097 };
1098 };
1099
1100 Ok(left)
1101 }
1102}