1use crate::ast::*;
11use crate::lexer::{lex, Tok, Token};
12
13const KEYWORDS: &[&str] = &[
14 "var",
15 "let",
16 "const",
17 "function",
18 "return",
19 "if",
20 "else",
21 "while",
22 "do",
23 "for",
24 "of",
25 "in",
26 "switch",
27 "case",
28 "default",
29 "break",
30 "continue",
31 "true",
32 "false",
33 "null",
34 "this",
35 "new",
36 "typeof",
37 "void",
38 "delete",
39 "instanceof",
40 "throw",
41 "try",
42 "catch",
43 "finally",
44];
45
46fn is_keyword(s: &str) -> bool {
47 KEYWORDS.contains(&s)
48}
49
50struct Parser {
51 toks: Vec<Token>,
52 pos: usize,
53 in_generator: bool,
55 in_async: bool,
57 no_in: bool,
62}
63
64pub fn parse(src: &str) -> Result<Vec<Stmt>, String> {
67 let src = crate::rust_ffi::desugar(src);
68 let toks = lex(&src)?;
69 let mut p = Parser {
70 toks,
71 pos: 0,
72 in_generator: false,
73 in_async: false,
74 no_in: false,
75 };
76 let mut out = Vec::new();
77 while !p.at_eof() {
78 out.push(p.parse_stmt()?);
79 }
80 Ok(out)
81}
82
83impl Parser {
84 fn cur(&self) -> &Token {
86 &self.toks[self.pos]
87 }
88 fn tok(&self) -> &Tok {
89 &self.toks[self.pos].tok
90 }
91 fn line(&self) -> u32 {
92 self.toks[self.pos].line
93 }
94 fn at_eof(&self) -> bool {
95 matches!(self.tok(), Tok::Eof)
96 }
97 fn newline_before(&self) -> bool {
98 self.cur().newline_before
99 }
100 fn advance(&mut self) -> Tok {
101 let t = self.toks[self.pos].tok.clone();
102 if self.pos + 1 < self.toks.len() {
103 self.pos += 1;
104 }
105 t
106 }
107
108 fn is_punct(&self, s: &str) -> bool {
110 matches!(self.tok(), Tok::Punct(p) if p == s)
111 }
112 fn is_kw(&self, s: &str) -> bool {
114 matches!(self.tok(), Tok::Ident(i) if i == s)
115 }
116 fn eat_punct(&mut self, s: &str) -> bool {
118 if self.is_punct(s) {
119 self.advance();
120 true
121 } else {
122 false
123 }
124 }
125 fn eat_kw(&mut self, s: &str) -> bool {
126 if self.is_kw(s) {
127 self.advance();
128 true
129 } else {
130 false
131 }
132 }
133 fn expect_punct(&mut self, s: &str) -> Result<(), String> {
134 if self.eat_punct(s) {
135 Ok(())
136 } else {
137 Err(format!(
138 "SyntaxError: expected '{s}' but found {:?} (line {})",
139 self.tok(),
140 self.line()
141 ))
142 }
143 }
144
145 fn ident_name(&mut self) -> Result<String, String> {
148 match self.tok().clone() {
149 Tok::Ident(s) => {
150 self.advance();
151 Ok(s)
152 }
153 other => Err(format!(
154 "SyntaxError: expected identifier but found {other:?} (line {})",
155 self.line()
156 )),
157 }
158 }
159
160 fn semicolon(&mut self) -> Result<(), String> {
162 if self.eat_punct(";") {
163 return Ok(());
164 }
165 if self.newline_before() || self.is_punct("}") || self.at_eof() {
166 return Ok(());
167 }
168 Err(format!(
169 "SyntaxError: expected ';' but found {:?} (line {})",
170 self.tok(),
171 self.line()
172 ))
173 }
174
175 fn parse_stmt(&mut self) -> Result<Stmt, String> {
177 let line = self.line();
178 let kind = match self.tok().clone() {
179 Tok::Punct(p) if p == "{" => {
180 self.advance();
181 StmtKind::Block(self.parse_block_body()?)
182 }
183 Tok::Punct(p) if p == ";" => {
184 self.advance();
185 StmtKind::Empty
186 }
187 Tok::Ident(kw) if kw == "var" || kw == "let" || kw == "const" => {
188 let k = self.parse_decl_kind();
189 let decls = self.parse_declarators()?;
190 self.semicolon()?;
191 StmtKind::Decl { kind: k, decls }
192 }
193 Tok::Ident(kw) if kw == "function" => self.parse_func_decl(false)?,
194 Tok::Ident(kw)
197 if kw == "async" && self.peek_kw(1, "function") && !self.peek_newline(1) =>
198 {
199 self.advance(); self.parse_func_decl(true)?
201 }
202 Tok::Ident(kw) if kw == "class" => {
203 let node = self.parse_class(true)?;
204 StmtKind::ClassDecl(node)
205 }
206 Tok::Ident(kw) if kw == "if" => self.parse_if()?,
207 Tok::Ident(kw) if kw == "while" => self.parse_while()?,
208 Tok::Ident(kw) if kw == "do" => self.parse_do_while()?,
209 Tok::Ident(kw) if kw == "for" => self.parse_for()?,
210 Tok::Ident(kw) if kw == "switch" => self.parse_switch()?,
211 Tok::Ident(kw) if kw == "return" => {
212 self.advance();
213 let arg = if self.is_punct(";")
214 || self.is_punct("}")
215 || self.newline_before()
216 || self.at_eof()
217 {
218 None
219 } else {
220 Some(self.parse_expr()?)
221 };
222 self.semicolon()?;
223 StmtKind::Return(arg)
224 }
225 Tok::Ident(kw) if kw == "break" => {
226 self.advance();
227 let label = self.opt_label();
228 self.semicolon()?;
229 StmtKind::Break(label)
230 }
231 Tok::Ident(kw) if kw == "continue" => {
232 self.advance();
233 let label = self.opt_label();
234 self.semicolon()?;
235 StmtKind::Continue(label)
236 }
237 Tok::Ident(kw) if kw == "throw" => {
238 self.advance();
239 let e = self.parse_expr()?;
240 self.semicolon()?;
241 StmtKind::Throw(e)
242 }
243 Tok::Ident(kw) if kw == "try" => self.parse_try()?,
244 Tok::Ident(name) if matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":") =>
249 {
250 self.advance(); self.advance(); let body = Box::new(self.parse_stmt()?);
253 StmtKind::Labeled { label: name, body }
254 }
255 _ => {
256 let e = self.parse_expr()?;
257 self.semicolon()?;
258 StmtKind::Expr(e)
259 }
260 };
261 Ok(Stmt::new(kind, line))
262 }
263
264 fn peek_kw(&self, n: usize, kw: &str) -> bool {
266 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Ident(s)) if s == kw)
267 }
268 fn peek_newline(&self, n: usize) -> bool {
270 self.toks
271 .get(self.pos + n)
272 .map(|t| t.newline_before)
273 .unwrap_or(false)
274 }
275
276 fn parse_func_decl(&mut self, is_async: bool) -> Result<StmtKind, String> {
279 self.advance(); let is_generator = self.eat_punct("*");
281 let name = self.ident_name()?;
282 let params = self.parse_params()?;
283 self.expect_punct("{")?;
284 let body = self.parse_fn_body_block(is_generator, is_async)?;
285 Ok(StmtKind::FuncDecl {
286 name,
287 params,
288 body,
289 is_generator,
290 is_async,
291 })
292 }
293
294 fn parse_fn_body_block(
297 &mut self,
298 is_generator: bool,
299 is_async: bool,
300 ) -> Result<Vec<Stmt>, String> {
301 let (pg, pa) = (self.in_generator, self.in_async);
302 self.in_generator = is_generator;
303 self.in_async = is_async;
304 let body = self.parse_block_body();
305 self.in_generator = pg;
306 self.in_async = pa;
307 body
308 }
309
310 fn parse_function_expr(&mut self, is_async: bool) -> Result<Expr, String> {
313 self.advance(); let is_generator = self.eat_punct("*");
315 let name = if let Tok::Ident(n) = self.tok() {
316 if !is_keyword(n) {
317 let n = n.clone();
318 self.advance();
319 Some(n)
320 } else {
321 None
322 }
323 } else {
324 None
325 };
326 let params = self.parse_params()?;
327 self.expect_punct("{")?;
328 let body = self.parse_fn_body_block(is_generator, is_async)?;
329 Ok(Expr::Function {
330 params,
331 body: FnBody::Block(body),
332 is_arrow: false,
333 name,
334 is_generator,
335 is_async,
336 is_method: false,
337 })
338 }
339
340 fn parse_class(&mut self, _decl: bool) -> Result<ClassNode, String> {
344 self.advance(); let name = if let Tok::Ident(n) = self.tok() {
346 if !is_keyword(n) && n != "extends" {
347 let n = n.clone();
348 self.advance();
349 Some(n)
350 } else {
351 None
352 }
353 } else {
354 None
355 };
356 let parent = if self.eat_kw("extends") {
357 Some(Box::new(self.parse_call_member()?))
360 } else {
361 None
362 };
363 self.expect_punct("{")?;
364 let mut members = Vec::new();
365 while !self.is_punct("}") && !self.at_eof() {
366 if self.eat_punct(";") {
367 continue; }
369 members.push(self.parse_class_member()?);
370 }
371 self.expect_punct("}")?;
372 Ok(ClassNode {
373 name,
374 parent,
375 members,
376 })
377 }
378
379 fn parse_class_member(&mut self) -> Result<ClassMember, String> {
382 let is_static = self.is_kw("static") && !self.peek_is_member_punct(1) && {
383 self.advance();
384 true
385 };
386 if is_static && self.is_punct("{") {
391 self.advance();
392 let body = self.parse_fn_body_block(false, false)?;
395 return Ok(ClassMember {
396 key: Expr::Str(String::new()),
397 computed: false,
398 kind: MemberKind::StaticBlock,
399 is_static: true,
400 is_generator: false,
401 is_async: false,
402 params: Vec::new(),
403 body,
404 field_init: None,
405 });
406 }
407 let mut kind = MemberKind::Method;
410 let mut is_async = false;
411 let mut is_generator = false;
412 if self.is_kw("get") && !self.peek_is_member_punct(1) {
413 self.advance();
414 kind = MemberKind::Get;
415 } else if self.is_kw("set") && !self.peek_is_member_punct(1) {
416 self.advance();
417 kind = MemberKind::Set;
418 } else {
419 if self.is_kw("async") && !self.peek_is_member_punct(1) && !self.peek_newline(1) {
420 self.advance();
421 is_async = true;
422 }
423 if self.eat_punct("*") {
424 is_generator = true;
425 }
426 }
427 let (key, computed) = self.parse_property_key()?;
429 if kind == MemberKind::Method && !self.is_punct("(") {
431 let field_init = if self.eat_punct("=") {
432 Some(self.parse_assign()?)
433 } else {
434 None
435 };
436 self.semicolon()?;
437 return Ok(ClassMember {
438 key,
439 computed,
440 kind: MemberKind::Field,
441 is_static,
442 is_generator: false,
443 is_async: false,
444 params: Vec::new(),
445 body: Vec::new(),
446 field_init,
447 });
448 }
449 let is_ctor = !is_static
451 && !computed
452 && matches!(&key, Expr::Str(s) if s == "constructor")
453 && kind == MemberKind::Method;
454 let params = self.parse_params()?;
455 self.expect_punct("{")?;
456 let body = self.parse_fn_body_block(is_generator, is_async)?;
457 Ok(ClassMember {
458 key,
459 computed,
460 kind: if is_ctor {
461 MemberKind::Constructor
462 } else {
463 kind
464 },
465 is_static,
466 is_generator,
467 is_async,
468 params,
469 body,
470 field_init: None,
471 })
472 }
473
474 fn peek_is_member_punct(&self, n: usize) -> bool {
477 matches!(
478 self.toks.get(self.pos + n).map(|t| &t.tok),
479 Some(Tok::Punct(p)) if p == "(" || p == "=" || p == ";" || p == "}"
480 )
481 }
482
483 fn parse_property_key(&mut self) -> Result<(Expr, bool), String> {
486 if self.is_punct("[") {
487 self.advance();
488 let k = self.parse_assign()?;
489 self.expect_punct("]")?;
490 Ok((k, true))
491 } else {
492 match self.tok().clone() {
493 Tok::Str(s) => {
494 self.advance();
495 Ok((Expr::Str(s), false))
496 }
497 Tok::Num(n) => {
498 self.advance();
499 Ok((Expr::Str(crate::host::fmt_number(n)), false))
500 }
501 Tok::Ident(s) => {
502 self.advance();
503 Ok((Expr::Str(s), false))
504 }
505 other => Err(format!(
506 "SyntaxError: bad member key {other:?} (line {})",
507 self.line()
508 )),
509 }
510 }
511 }
512
513 fn opt_label(&mut self) -> Option<String> {
515 if self.newline_before() {
516 return None;
517 }
518 if let Tok::Ident(s) = self.tok() {
519 if !is_keyword(s) {
520 let s = s.clone();
521 self.advance();
522 return Some(s);
523 }
524 }
525 None
526 }
527
528 fn parse_block_body(&mut self) -> Result<Vec<Stmt>, String> {
530 let mut out = Vec::new();
531 while !self.is_punct("}") && !self.at_eof() {
532 out.push(self.parse_stmt()?);
533 }
534 self.expect_punct("}")?;
535 Ok(out)
536 }
537
538 fn parse_decl_kind(&mut self) -> DeclKind {
539 let k = match self.tok() {
540 Tok::Ident(s) if s == "let" => DeclKind::Let,
541 Tok::Ident(s) if s == "const" => DeclKind::Const,
542 _ => DeclKind::Var,
543 };
544 self.advance();
545 k
546 }
547
548 fn parse_declarators(&mut self) -> Result<Vec<Declarator>, String> {
549 let mut decls = Vec::new();
550 loop {
551 let target = self.parse_binding_target()?;
552 let init = if self.eat_punct("=") {
553 Some(self.parse_assign()?)
554 } else {
555 None
556 };
557 decls.push(Declarator { target, init });
558 if !self.eat_punct(",") {
559 break;
560 }
561 }
562 Ok(decls)
563 }
564
565 fn parse_binding_target(&mut self) -> Result<Expr, String> {
567 if self.is_punct("[") {
568 self.parse_array_literal()
569 } else if self.is_punct("{") {
570 self.parse_object_literal()
571 } else {
572 Ok(Expr::Ident(self.ident_name()?))
573 }
574 }
575
576 fn parse_if(&mut self) -> Result<StmtKind, String> {
577 self.advance(); self.expect_punct("(")?;
579 let test = self.parse_expr()?;
580 self.expect_punct(")")?;
581 let cons = Box::new(self.parse_stmt()?);
582 let alt = if self.eat_kw("else") {
583 Some(Box::new(self.parse_stmt()?))
584 } else {
585 None
586 };
587 Ok(StmtKind::If { test, cons, alt })
588 }
589
590 fn parse_while(&mut self) -> Result<StmtKind, String> {
591 self.advance();
592 self.expect_punct("(")?;
593 let test = self.parse_expr()?;
594 self.expect_punct(")")?;
595 let body = Box::new(self.parse_stmt()?);
596 Ok(StmtKind::While { test, body })
597 }
598
599 fn parse_do_while(&mut self) -> Result<StmtKind, String> {
600 self.advance();
601 let body = Box::new(self.parse_stmt()?);
602 if !self.eat_kw("while") {
603 return Err(format!(
604 "SyntaxError: expected 'while' (line {})",
605 self.line()
606 ));
607 }
608 self.expect_punct("(")?;
609 let test = self.parse_expr()?;
610 self.expect_punct(")")?;
611 self.semicolon()?;
612 Ok(StmtKind::DoWhile { body, test })
613 }
614
615 fn parse_for(&mut self) -> Result<StmtKind, String> {
616 self.advance();
617 let is_await = self.eat_kw("await");
619 self.expect_punct("(")?;
620 let decl_kind = match self.tok() {
622 Tok::Ident(s) if s == "var" || s == "let" || s == "const" => {
623 Some(self.parse_decl_kind())
624 }
625 _ => None,
626 };
627 if decl_kind.is_none() && self.is_punct(";") {
629 return self.parse_c_for(None);
630 }
631 let first_target = if decl_kind.is_some() {
633 self.parse_binding_target()?
634 } else {
635 self.parse_expr_no_in()?
636 };
637 if self.eat_kw("of") {
638 let iter = self.parse_assign()?;
639 self.expect_punct(")")?;
640 let body = Box::new(self.parse_stmt()?);
641 return Ok(StmtKind::ForOf {
642 decl_kind,
643 target: first_target,
644 iter,
645 body,
646 is_await,
647 });
648 }
649 if self.eat_kw("in") {
650 let object = self.parse_assign()?;
651 self.expect_punct(")")?;
652 let body = Box::new(self.parse_stmt()?);
653 return Ok(StmtKind::ForIn {
654 decl_kind,
655 target: first_target,
656 object,
657 body,
658 });
659 }
660 let init_stmt = if let Some(k) = decl_kind {
662 let init = if self.eat_punct("=") {
663 Some(self.parse_assign()?)
664 } else {
665 None
666 };
667 let mut decls = vec![Declarator {
668 target: first_target,
669 init,
670 }];
671 while self.eat_punct(",") {
672 let target = self.parse_binding_target()?;
673 let init = if self.eat_punct("=") {
674 Some(self.parse_assign()?)
675 } else {
676 None
677 };
678 decls.push(Declarator { target, init });
679 }
680 StmtKind::Decl { kind: k, decls }
681 } else {
682 let init = if self.is_punct(",") {
685 let mut items = vec![first_target];
686 while self.eat_punct(",") {
687 items.push(self.parse_expr_no_in()?);
688 }
689 Expr::Sequence(items)
690 } else {
691 first_target
692 };
693 StmtKind::Expr(init)
694 };
695 self.parse_c_for(Some(Stmt::from(init_stmt)))
696 }
697
698 fn parse_c_for(&mut self, init: Option<Stmt>) -> Result<StmtKind, String> {
699 self.expect_punct(";")?;
700 let test = if self.is_punct(";") {
701 None
702 } else {
703 Some(self.parse_expr()?)
704 };
705 self.expect_punct(";")?;
706 let update = if self.is_punct(")") {
707 None
708 } else {
709 Some(self.parse_expr()?)
710 };
711 self.expect_punct(")")?;
712 let body = Box::new(self.parse_stmt()?);
713 Ok(StmtKind::For {
714 init: init.map(Box::new),
715 test,
716 update,
717 body,
718 })
719 }
720
721 fn parse_switch(&mut self) -> Result<StmtKind, String> {
722 self.advance();
723 self.expect_punct("(")?;
724 let disc = self.parse_expr()?;
725 self.expect_punct(")")?;
726 self.expect_punct("{")?;
727 let mut cases = Vec::new();
728 while !self.is_punct("}") && !self.at_eof() {
729 let test = if self.eat_kw("case") {
730 let e = self.parse_expr()?;
731 Some(e)
732 } else if self.eat_kw("default") {
733 None
734 } else {
735 return Err(format!(
736 "SyntaxError: expected 'case' or 'default' (line {})",
737 self.line()
738 ));
739 };
740 self.expect_punct(":")?;
741 let mut body = Vec::new();
742 while !self.is_punct("}")
743 && !self.is_kw("case")
744 && !self.is_kw("default")
745 && !self.at_eof()
746 {
747 body.push(self.parse_stmt()?);
748 }
749 cases.push(SwitchCase { test, body });
750 }
751 self.expect_punct("}")?;
752 Ok(StmtKind::Switch { disc, cases })
753 }
754
755 fn parse_try(&mut self) -> Result<StmtKind, String> {
756 self.advance();
757 self.expect_punct("{")?;
758 let block = self.parse_block_body()?;
759 let handler = if self.eat_kw("catch") {
760 let param = if self.eat_punct("(") {
761 let p = self.parse_binding_target()?;
762 self.expect_punct(")")?;
763 Some(p)
764 } else {
765 None
766 };
767 self.expect_punct("{")?;
768 let body = self.parse_block_body()?;
769 Some((param, body))
770 } else {
771 None
772 };
773 let finalizer = if self.eat_kw("finally") {
774 self.expect_punct("{")?;
775 Some(self.parse_block_body()?)
776 } else {
777 None
778 };
779 Ok(StmtKind::Try {
780 block,
781 handler,
782 finalizer,
783 })
784 }
785
786 fn parse_expr(&mut self) -> Result<Expr, String> {
789 let first = self.parse_assign()?;
790 if self.is_punct(",") {
791 let mut items = vec![first];
792 while self.eat_punct(",") {
793 items.push(self.parse_assign()?);
794 }
795 Ok(Expr::Sequence(items))
796 } else {
797 Ok(first)
798 }
799 }
800
801 fn parse_expr_no_in(&mut self) -> Result<Expr, String> {
803 let saved = self.no_in;
806 self.no_in = true;
807 let r = self.parse_assign();
808 self.no_in = saved;
809 r
810 }
811
812 fn allow_in<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, String>) -> Result<T, String> {
815 let saved = self.no_in;
816 self.no_in = false;
817 let r = f(self);
818 self.no_in = saved;
819 r
820 }
821
822 fn parse_assign(&mut self) -> Result<Expr, String> {
823 if let Some(arrow) = self.try_parse_arrow()? {
825 return Ok(arrow);
826 }
827 let left = self.parse_conditional()?;
828 let op = match self.tok() {
830 Tok::Punct(p) => p.clone(),
831 _ => return Ok(left),
832 };
833 let compound = match op.as_str() {
834 "=" => None,
835 "+=" => Some(BinOp::Add),
836 "-=" => Some(BinOp::Sub),
837 "*=" => Some(BinOp::Mul),
838 "/=" => Some(BinOp::Div),
839 "%=" => Some(BinOp::Mod),
840 "**=" => Some(BinOp::Pow),
841 "&=" => Some(BinOp::BitAnd),
842 "|=" => Some(BinOp::BitOr),
843 "^=" => Some(BinOp::BitXor),
844 "<<=" => Some(BinOp::Shl),
845 ">>=" => Some(BinOp::Shr),
846 ">>>=" => Some(BinOp::UShr),
847 "&&=" | "||=" | "??=" => {
848 self.advance();
850 let value = self.parse_assign()?;
851 let lop = match op.as_str() {
852 "&&=" => LogicalOp::And,
853 "||=" => LogicalOp::Or,
854 _ => LogicalOp::Nullish,
855 };
856 return Ok(Expr::Assign {
857 target: Box::new(left.clone()),
858 value: Box::new(Expr::Logical(lop, Box::new(left), Box::new(value))),
859 });
860 }
861 _ => return Ok(left),
862 };
863 self.advance();
864 let value = self.parse_assign()?;
865 let value = match compound {
866 None => value,
867 Some(b) => Expr::Binary(b, Box::new(left.clone()), Box::new(value)),
868 };
869 Ok(Expr::Assign {
870 target: Box::new(left),
871 value: Box::new(value),
872 })
873 }
874
875 fn parse_conditional(&mut self) -> Result<Expr, String> {
876 let test = self.parse_binary(0)?;
877 if self.eat_punct("?") {
878 let cons = self.parse_assign()?;
879 self.expect_punct(":")?;
880 let alt = self.parse_assign()?;
881 Ok(Expr::Conditional {
882 test: Box::new(test),
883 cons: Box::new(cons),
884 alt: Box::new(alt),
885 })
886 } else {
887 Ok(test)
888 }
889 }
890
891 fn parse_binary(&mut self, min_prec: u8) -> Result<Expr, String> {
893 let mut left = self.parse_unary()?;
894 while let Some((prec, right_assoc, logical, bin)) = self.bin_info() {
895 if prec < min_prec {
896 break;
897 }
898 self.advance();
899 let next_min = if right_assoc { prec } else { prec + 1 };
900 let right = self.parse_binary(next_min)?;
901 left = if let Some(lop) = logical {
902 Expr::Logical(lop, Box::new(left), Box::new(right))
903 } else {
904 Expr::Binary(bin.unwrap(), Box::new(left), Box::new(right))
905 };
906 }
907 Ok(left)
908 }
909
910 fn bin_info(&self) -> Option<(u8, bool, Option<LogicalOp>, Option<BinOp>)> {
912 let p = match self.tok() {
913 Tok::Punct(p) => p.as_str(),
914 Tok::Ident(s) if s == "in" => {
917 if self.no_in {
918 return None;
919 }
920 "in"
921 }
922 Tok::Ident(s) if s == "instanceof" => "instanceof",
923 _ => return None,
924 };
925 let (prec, ra, log, bin) = match p {
926 "??" => (1, false, Some(LogicalOp::Nullish), None),
927 "||" => (2, false, Some(LogicalOp::Or), None),
928 "&&" => (3, false, Some(LogicalOp::And), None),
929 "|" => (4, false, None, Some(BinOp::BitOr)),
930 "^" => (5, false, None, Some(BinOp::BitXor)),
931 "&" => (6, false, None, Some(BinOp::BitAnd)),
932 "==" => (7, false, None, Some(BinOp::EqEq)),
933 "!=" => (7, false, None, Some(BinOp::NeEq)),
934 "===" => (7, false, None, Some(BinOp::EqEqEq)),
935 "!==" => (7, false, None, Some(BinOp::NeEqEq)),
936 "<" => (8, false, None, Some(BinOp::Lt)),
937 "<=" => (8, false, None, Some(BinOp::Le)),
938 ">" => (8, false, None, Some(BinOp::Gt)),
939 ">=" => (8, false, None, Some(BinOp::Ge)),
940 "in" => (8, false, None, Some(BinOp::In)),
941 "instanceof" => (8, false, None, Some(BinOp::InstanceOf)),
942 "<<" => (9, false, None, Some(BinOp::Shl)),
943 ">>" => (9, false, None, Some(BinOp::Shr)),
944 ">>>" => (9, false, None, Some(BinOp::UShr)),
945 "+" => (10, false, None, Some(BinOp::Add)),
946 "-" => (10, false, None, Some(BinOp::Sub)),
947 "*" => (11, false, None, Some(BinOp::Mul)),
948 "/" => (11, false, None, Some(BinOp::Div)),
949 "%" => (11, false, None, Some(BinOp::Mod)),
950 "**" => (12, true, None, Some(BinOp::Pow)),
951 _ => return None,
952 };
953 Some((prec, ra, log, bin))
954 }
955
956 fn reject_unary_before_pow(&mut self) -> Result<(), String> {
961 if self.is_punct("**") {
962 return Err(format!(
963 "SyntaxError: Unary operator used immediately before exponentiation \
964 expression. Parenthesis must be used to disambiguate operator \
965 precedence (line {})",
966 self.line()
967 ));
968 }
969 Ok(())
970 }
971
972 fn parse_unary(&mut self) -> Result<Expr, String> {
973 let op = match self.tok() {
974 Tok::Punct(p) if p == "!" => Some(UnOp::Not),
975 Tok::Punct(p) if p == "~" => Some(UnOp::BitNot),
976 Tok::Punct(p) if p == "+" => Some(UnOp::Pos),
977 Tok::Punct(p) if p == "-" => Some(UnOp::Neg),
978 Tok::Ident(s) if s == "typeof" => Some(UnOp::TypeOf),
979 Tok::Ident(s) if s == "void" => Some(UnOp::Void),
980 Tok::Ident(s) if s == "delete" => Some(UnOp::Delete),
981 _ => None,
982 };
983 if let Some(op) = op {
984 self.advance();
985 let e = self.parse_unary()?;
986 self.reject_unary_before_pow()?;
990 return Ok(Expr::Unary(op, Box::new(e)));
991 }
992 if self.is_punct("++") || self.is_punct("--") {
994 let op = if self.is_punct("++") {
995 UpdateOp::Inc
996 } else {
997 UpdateOp::Dec
998 };
999 self.advance();
1000 let e = self.parse_unary()?;
1001 return Ok(Expr::Update {
1002 op,
1003 prefix: true,
1004 target: Box::new(e),
1005 });
1006 }
1007 self.parse_postfix()
1008 }
1009
1010 fn parse_postfix(&mut self) -> Result<Expr, String> {
1011 let mut e = self.parse_call_member()?;
1012 if (self.is_punct("++") || self.is_punct("--")) && !self.newline_before() {
1014 let op = if self.is_punct("++") {
1015 UpdateOp::Inc
1016 } else {
1017 UpdateOp::Dec
1018 };
1019 self.advance();
1020 e = Expr::Update {
1021 op,
1022 prefix: false,
1023 target: Box::new(e),
1024 };
1025 }
1026 Ok(e)
1027 }
1028
1029 fn parse_call_member(&mut self) -> Result<Expr, String> {
1030 let mut e = if self.eat_kw("new") {
1031 if self.is_punct(".") {
1033 self.advance();
1034 let prop = self.ident_name()?;
1035 if prop != "target" {
1036 return Err(format!(
1037 "SyntaxError: expected 'target' (line {})",
1038 self.line()
1039 ));
1040 }
1041 Expr::NewTarget
1042 } else {
1043 let callee = self.parse_call_member_no_call()?;
1044 let args = if self.is_punct("(") {
1045 self.parse_args()?
1046 } else {
1047 Vec::new()
1048 };
1049 Expr::New {
1050 callee: Box::new(callee),
1051 args,
1052 }
1053 }
1054 } else {
1055 self.parse_primary()?
1056 };
1057 loop {
1058 if self.eat_punct(".") {
1059 let property = self.ident_name()?;
1060 e = Expr::Member {
1061 object: Box::new(e),
1062 property,
1063 optional: false,
1064 };
1065 } else if self.eat_punct("?.") {
1066 if self.is_punct("(") {
1067 let args = self.parse_args()?;
1068 e = Expr::Call {
1069 func: Box::new(e),
1070 args,
1071 optional: true,
1072 };
1073 } else if self.is_punct("[") {
1074 self.advance();
1075 let index = self.allow_in(|p| p.parse_expr())?;
1076 self.expect_punct("]")?;
1077 e = Expr::Index {
1078 object: Box::new(e),
1079 index: Box::new(index),
1080 optional: true,
1081 };
1082 } else {
1083 let property = self.ident_name()?;
1084 e = Expr::Member {
1085 object: Box::new(e),
1086 property,
1087 optional: true,
1088 };
1089 }
1090 } else if self.is_punct("[") {
1091 self.advance();
1092 let index = self.allow_in(|p| p.parse_expr())?;
1093 self.expect_punct("]")?;
1094 e = Expr::Index {
1095 object: Box::new(e),
1096 index: Box::new(index),
1097 optional: false,
1098 };
1099 } else if self.is_punct("(") {
1100 let args = self.parse_args()?;
1101 e = Expr::Call {
1102 func: Box::new(e),
1103 args,
1104 optional: false,
1105 };
1106 } else if matches!(self.tok(), Tok::Template { .. }) {
1107 e = self.parse_tagged_template(e)?;
1110 } else {
1111 break;
1112 }
1113 }
1114 Ok(e)
1115 }
1116
1117 fn parse_tagged_template(&mut self, tag: Expr) -> Result<Expr, String> {
1120 let (quasis, raws, exprs_src) = match self.tok().clone() {
1121 Tok::Template {
1122 quasis,
1123 raws,
1124 exprs,
1125 } => (quasis, raws, exprs),
1126 _ => unreachable!(),
1127 };
1128 self.advance();
1129 let mut exprs = Vec::new();
1130 for src in &exprs_src {
1131 exprs.push(parse_expr_source(src)?);
1132 }
1133 Ok(Expr::TaggedTemplate {
1134 tag: Box::new(tag),
1135 quasis,
1136 raws,
1137 exprs,
1138 })
1139 }
1140
1141 fn parse_call_member_no_call(&mut self) -> Result<Expr, String> {
1143 let mut e = self.parse_primary()?;
1144 loop {
1145 if self.eat_punct(".") {
1146 let property = self.ident_name()?;
1147 e = Expr::Member {
1148 object: Box::new(e),
1149 property,
1150 optional: false,
1151 };
1152 } else if self.is_punct("[") {
1153 self.advance();
1154 let index = self.allow_in(|p| p.parse_expr())?;
1155 self.expect_punct("]")?;
1156 e = Expr::Index {
1157 object: Box::new(e),
1158 index: Box::new(index),
1159 optional: false,
1160 };
1161 } else {
1162 break;
1163 }
1164 }
1165 Ok(e)
1166 }
1167
1168 fn parse_args(&mut self) -> Result<Vec<Expr>, String> {
1169 self.expect_punct("(")?;
1170 let args = self.allow_in(|p| {
1173 let mut args = Vec::new();
1174 while !p.is_punct(")") {
1175 if p.eat_punct("...") {
1176 let e = p.parse_assign()?;
1177 args.push(Expr::Spread(Box::new(e)));
1178 } else {
1179 args.push(p.parse_assign()?);
1180 }
1181 if !p.eat_punct(",") {
1182 break;
1183 }
1184 }
1185 Ok(args)
1186 })?;
1187 self.expect_punct(")")?;
1188 Ok(args)
1189 }
1190
1191 fn parse_primary(&mut self) -> Result<Expr, String> {
1192 match self.tok().clone() {
1193 Tok::Num(n) => {
1194 self.advance();
1195 Ok(Expr::Number(n))
1196 }
1197 Tok::BigInt(s) => {
1198 self.advance();
1199 Ok(Expr::BigInt(s))
1200 }
1201 Tok::Regex(pat, flags) => {
1202 self.advance();
1203 Ok(Expr::Regex(pat, flags))
1204 }
1205 Tok::Str(s) => {
1206 self.advance();
1207 Ok(Expr::Str(s))
1208 }
1209 Tok::Template {
1210 quasis,
1211 raws: _,
1212 exprs,
1213 } => {
1214 self.advance();
1215 let mut parsed = Vec::new();
1216 for src in &exprs {
1217 parsed.push(parse_expr_source(src)?);
1218 }
1219 Ok(Expr::Template {
1220 quasis,
1221 exprs: parsed,
1222 })
1223 }
1224 Tok::Punct(p) if p == "(" => {
1225 self.advance();
1226 let e = self.parse_expr()?;
1227 self.expect_punct(")")?;
1228 Ok(e)
1229 }
1230 Tok::Punct(p) if p == "[" => self.parse_array_literal(),
1231 Tok::Punct(p) if p == "{" => self.parse_object_literal(),
1232 Tok::Ident(s) => {
1233 match s.as_str() {
1234 "true" => {
1235 self.advance();
1236 Ok(Expr::True)
1237 }
1238 "false" => {
1239 self.advance();
1240 Ok(Expr::False)
1241 }
1242 "null" => {
1243 self.advance();
1244 Ok(Expr::Null)
1245 }
1246 "this" => {
1247 self.advance();
1248 Ok(Expr::This)
1249 }
1250 "super" => {
1251 self.advance();
1252 Ok(Expr::Super)
1253 }
1254 "class" => Ok(Expr::Class(Box::new(self.parse_class(false)?))),
1255 "function" => self.parse_function_expr(false),
1256 "async" if self.peek_kw(1, "function") && !self.peek_newline(1) => {
1257 self.advance(); self.parse_function_expr(true)
1259 }
1260 "yield" if self.in_generator => {
1261 self.advance();
1262 let delegate = self.eat_punct("*");
1263 let arg = if delegate
1266 || !(self.is_punct(")")
1267 || self.is_punct("]")
1268 || self.is_punct("}")
1269 || self.is_punct(",")
1270 || self.is_punct(";")
1271 || self.is_punct(":")
1272 || self.newline_before()
1273 || self.at_eof())
1274 {
1275 Some(Box::new(self.parse_assign()?))
1276 } else {
1277 None
1278 };
1279 Ok(Expr::Yield { arg, delegate })
1280 }
1281 "await" if self.in_async => {
1282 self.advance();
1283 let e = self.parse_unary()?;
1284 self.reject_unary_before_pow()?;
1287 Ok(Expr::Await(Box::new(e)))
1288 }
1289 _ if is_keyword(&s) => Err(format!(
1290 "SyntaxError: unexpected keyword '{s}' (line {})",
1291 self.line()
1292 )),
1293 _ => {
1294 self.advance();
1295 Ok(Expr::Ident(s))
1296 }
1297 }
1298 }
1299 other => Err(format!(
1300 "SyntaxError: unexpected token {other:?} (line {})",
1301 self.line()
1302 )),
1303 }
1304 }
1305
1306 fn parse_array_literal(&mut self) -> Result<Expr, String> {
1307 self.expect_punct("[")?;
1308 let mut items = Vec::new();
1309 while !self.is_punct("]") {
1310 if self.is_punct(",") {
1311 items.push(Expr::Hole);
1313 self.advance();
1314 continue;
1315 }
1316 if self.eat_punct("...") {
1317 let e = self.parse_assign()?;
1318 items.push(Expr::Spread(Box::new(e)));
1319 } else {
1320 items.push(self.parse_assign()?);
1321 }
1322 if !self.eat_punct(",") {
1323 break;
1324 }
1325 }
1326 self.expect_punct("]")?;
1327 Ok(Expr::Array(items))
1328 }
1329
1330 fn parse_object_literal(&mut self) -> Result<Expr, String> {
1331 self.expect_punct("{")?;
1332 let mut props = Vec::new();
1333 while !self.is_punct("}") {
1334 if self.eat_punct("...") {
1335 let e = self.parse_assign()?;
1336 props.push(Prop::Spread(e));
1337 if !self.eat_punct(",") {
1338 break;
1339 }
1340 continue;
1341 }
1342 if (self.is_kw("get") || self.is_kw("set"))
1345 && !self.peek_is_member_punct(1)
1346 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1347 {
1348 let is_getter = self.is_kw("get");
1349 self.advance();
1350 let (key, computed) = self.parse_property_key()?;
1351 let params = self.parse_params()?;
1352 self.expect_punct("{")?;
1353 let body = self.parse_block_body()?;
1354 let func = Expr::Function {
1355 params,
1356 body: FnBody::Block(body),
1357 is_arrow: false,
1358 name: None,
1359 is_generator: false,
1360 is_async: false,
1361 is_method: true,
1362 };
1363 props.push(Prop::Accessor {
1364 key,
1365 computed,
1366 is_getter,
1367 func,
1368 });
1369 if !self.eat_punct(",") {
1370 break;
1371 }
1372 continue;
1373 }
1374 let mut m_async = false;
1376 let mut m_gen = false;
1377 if self.is_kw("async")
1378 && !self.peek_is_member_punct(1)
1379 && !self.peek_newline(1)
1380 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1381 {
1382 self.advance();
1383 m_async = true;
1384 }
1385 if self.is_punct("*") {
1386 self.advance();
1387 m_gen = true;
1388 }
1389 let (key, computed) = self.parse_property_key()?;
1390 if self.is_punct("(") {
1392 let params = self.parse_params()?;
1393 self.expect_punct("{")?;
1394 let body = self.parse_fn_body_block(m_gen, m_async)?;
1395 let f = Expr::Function {
1396 params,
1397 body: FnBody::Block(body),
1398 is_arrow: false,
1399 name: None,
1400 is_generator: m_gen,
1401 is_async: m_async,
1402 is_method: true,
1403 };
1404 props.push(Prop::KeyValue {
1405 key,
1406 value: f,
1407 computed,
1408 });
1409 } else if self.eat_punct(":") {
1410 let value = self.parse_assign()?;
1411 props.push(Prop::KeyValue {
1412 key,
1413 value,
1414 computed,
1415 });
1416 } else {
1417 let name = match &key {
1420 Expr::Str(s) => s.clone(),
1421 _ => return Err(format!("SyntaxError: bad shorthand (line {})", self.line())),
1422 };
1423 let value = if self.eat_punct("=") {
1424 let d = self.parse_assign()?;
1426 Expr::Assign {
1427 target: Box::new(Expr::Ident(name.clone())),
1428 value: Box::new(d),
1429 }
1430 } else {
1431 Expr::Ident(name)
1432 };
1433 props.push(Prop::KeyValue {
1434 key,
1435 value,
1436 computed,
1437 });
1438 }
1439 if !self.eat_punct(",") {
1440 break;
1441 }
1442 }
1443 self.expect_punct("}")?;
1444 Ok(Expr::Object(props))
1445 }
1446
1447 fn parse_params(&mut self) -> Result<Vec<Param>, String> {
1449 self.expect_punct("(")?;
1450 let mut params = Vec::new();
1451 while !self.is_punct(")") {
1452 let rest = self.eat_punct("...");
1453 let pattern = self.parse_binding_target()?;
1454 let default = if !rest && self.eat_punct("=") {
1455 Some(self.parse_assign()?)
1456 } else {
1457 None
1458 };
1459 params.push(Param {
1460 pattern,
1461 default,
1462 rest,
1463 });
1464 if !self.eat_punct(",") {
1465 break;
1466 }
1467 }
1468 self.expect_punct(")")?;
1469 Ok(params)
1470 }
1471
1472 fn try_parse_arrow(&mut self) -> Result<Option<Expr>, String> {
1475 let mut is_async = false;
1478 let mut base = self.pos;
1479 if self.is_kw("async") && !self.peek_newline(1) {
1480 let next = self.toks.get(self.pos + 1).map(|t| &t.tok);
1481 let looks_async_arrow = matches!(next, Some(Tok::Punct(p)) if p == "(")
1482 || matches!(next, Some(Tok::Ident(n)) if !is_keyword(n) && self.peek_is_arrow_after(2));
1483 if looks_async_arrow {
1484 is_async = true;
1485 base += 1;
1486 }
1487 }
1488 if let Some(Tok::Ident(name)) = self.toks.get(base).map(|t| &t.tok) {
1490 if !is_keyword(name)
1491 && matches!(self.toks.get(base + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1492 {
1493 let name = name.clone();
1494 if is_async {
1495 self.advance(); }
1497 self.advance(); self.advance(); let body = self.parse_arrow_body(is_async)?;
1500 return Ok(Some(Expr::Function {
1501 params: vec![Param {
1502 pattern: Expr::Ident(name),
1503 default: None,
1504 rest: false,
1505 }],
1506 body,
1507 is_arrow: true,
1508 name: None,
1509 is_generator: false,
1510 is_async,
1511 is_method: false,
1512 }));
1513 }
1514 }
1515 if matches!(self.toks.get(base).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "(") {
1517 if let Some(close) = self.matching_paren(base) {
1518 let after = close + 1;
1519 if matches!(self.toks.get(after).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1520 {
1521 if is_async {
1522 self.advance(); }
1524 let params = self.parse_params()?;
1525 self.expect_punct("=>")?;
1526 let body = self.parse_arrow_body(is_async)?;
1527 return Ok(Some(Expr::Function {
1528 params,
1529 body,
1530 is_arrow: true,
1531 name: None,
1532 is_generator: false,
1533 is_async,
1534 is_method: false,
1535 }));
1536 }
1537 }
1538 }
1539 Ok(None)
1540 }
1541
1542 fn parse_arrow_body(&mut self, is_async: bool) -> Result<FnBody, String> {
1543 let (pg, pa) = (self.in_generator, self.in_async);
1544 self.in_generator = false;
1545 self.in_async = is_async;
1546 let r = if self.is_punct("{") {
1547 self.advance();
1548 self.parse_block_body().map(FnBody::Block)
1549 } else {
1550 self.parse_assign().map(|e| FnBody::Expr(Box::new(e)))
1551 };
1552 self.in_generator = pg;
1553 self.in_async = pa;
1554 r
1555 }
1556
1557 fn peek_is_arrow_after(&self, n: usize) -> bool {
1559 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1560 }
1561
1562 fn matching_paren(&self, open: usize) -> Option<usize> {
1564 let mut depth = 0i32;
1565 let mut i = open;
1566 while i < self.toks.len() {
1567 match &self.toks[i].tok {
1568 Tok::Punct(p) if p == "(" || p == "[" || p == "{" => depth += 1,
1569 Tok::Punct(p) if p == ")" || p == "]" || p == "}" => {
1570 depth -= 1;
1571 if depth == 0 {
1572 return Some(i);
1573 }
1574 }
1575 Tok::Eof => return None,
1576 _ => {}
1577 }
1578 i += 1;
1579 }
1580 None
1581 }
1582}
1583
1584fn parse_expr_source(src: &str) -> Result<Expr, String> {
1586 let toks = lex(src)?;
1587 let mut p = Parser {
1588 toks,
1589 pos: 0,
1590 in_generator: false,
1591 in_async: false,
1592 no_in: false,
1593 };
1594 let e = p.parse_expr()?;
1595 Ok(e)
1596}