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 })
337 }
338
339 fn parse_class(&mut self, _decl: bool) -> Result<ClassNode, String> {
343 self.advance(); let name = if let Tok::Ident(n) = self.tok() {
345 if !is_keyword(n) && n != "extends" {
346 let n = n.clone();
347 self.advance();
348 Some(n)
349 } else {
350 None
351 }
352 } else {
353 None
354 };
355 let parent = if self.eat_kw("extends") {
356 Some(Box::new(self.parse_call_member()?))
359 } else {
360 None
361 };
362 self.expect_punct("{")?;
363 let mut members = Vec::new();
364 while !self.is_punct("}") && !self.at_eof() {
365 if self.eat_punct(";") {
366 continue; }
368 members.push(self.parse_class_member()?);
369 }
370 self.expect_punct("}")?;
371 Ok(ClassNode {
372 name,
373 parent,
374 members,
375 })
376 }
377
378 fn parse_class_member(&mut self) -> Result<ClassMember, String> {
381 let is_static = self.is_kw("static") && !self.peek_is_member_punct(1) && {
382 self.advance();
383 true
384 };
385 let mut kind = MemberKind::Method;
388 let mut is_async = false;
389 let mut is_generator = false;
390 if self.is_kw("get") && !self.peek_is_member_punct(1) {
391 self.advance();
392 kind = MemberKind::Get;
393 } else if self.is_kw("set") && !self.peek_is_member_punct(1) {
394 self.advance();
395 kind = MemberKind::Set;
396 } else {
397 if self.is_kw("async") && !self.peek_is_member_punct(1) && !self.peek_newline(1) {
398 self.advance();
399 is_async = true;
400 }
401 if self.eat_punct("*") {
402 is_generator = true;
403 }
404 }
405 let (key, computed) = self.parse_property_key()?;
407 if kind == MemberKind::Method && !self.is_punct("(") {
409 let field_init = if self.eat_punct("=") {
410 Some(self.parse_assign()?)
411 } else {
412 None
413 };
414 self.semicolon()?;
415 return Ok(ClassMember {
416 key,
417 computed,
418 kind: MemberKind::Field,
419 is_static,
420 is_generator: false,
421 is_async: false,
422 params: Vec::new(),
423 body: Vec::new(),
424 field_init,
425 });
426 }
427 let is_ctor = !is_static
429 && !computed
430 && matches!(&key, Expr::Str(s) if s == "constructor")
431 && kind == MemberKind::Method;
432 let params = self.parse_params()?;
433 self.expect_punct("{")?;
434 let body = self.parse_fn_body_block(is_generator, is_async)?;
435 Ok(ClassMember {
436 key,
437 computed,
438 kind: if is_ctor {
439 MemberKind::Constructor
440 } else {
441 kind
442 },
443 is_static,
444 is_generator,
445 is_async,
446 params,
447 body,
448 field_init: None,
449 })
450 }
451
452 fn peek_is_member_punct(&self, n: usize) -> bool {
455 matches!(
456 self.toks.get(self.pos + n).map(|t| &t.tok),
457 Some(Tok::Punct(p)) if p == "(" || p == "=" || p == ";" || p == "}"
458 )
459 }
460
461 fn parse_property_key(&mut self) -> Result<(Expr, bool), String> {
464 if self.is_punct("[") {
465 self.advance();
466 let k = self.parse_assign()?;
467 self.expect_punct("]")?;
468 Ok((k, true))
469 } else {
470 match self.tok().clone() {
471 Tok::Str(s) => {
472 self.advance();
473 Ok((Expr::Str(s), false))
474 }
475 Tok::Num(n) => {
476 self.advance();
477 Ok((Expr::Str(crate::host::fmt_number(n)), false))
478 }
479 Tok::Ident(s) => {
480 self.advance();
481 Ok((Expr::Str(s), false))
482 }
483 other => Err(format!(
484 "SyntaxError: bad member key {other:?} (line {})",
485 self.line()
486 )),
487 }
488 }
489 }
490
491 fn opt_label(&mut self) -> Option<String> {
493 if self.newline_before() {
494 return None;
495 }
496 if let Tok::Ident(s) = self.tok() {
497 if !is_keyword(s) {
498 let s = s.clone();
499 self.advance();
500 return Some(s);
501 }
502 }
503 None
504 }
505
506 fn parse_block_body(&mut self) -> Result<Vec<Stmt>, String> {
508 let mut out = Vec::new();
509 while !self.is_punct("}") && !self.at_eof() {
510 out.push(self.parse_stmt()?);
511 }
512 self.expect_punct("}")?;
513 Ok(out)
514 }
515
516 fn parse_decl_kind(&mut self) -> DeclKind {
517 let k = match self.tok() {
518 Tok::Ident(s) if s == "let" => DeclKind::Let,
519 Tok::Ident(s) if s == "const" => DeclKind::Const,
520 _ => DeclKind::Var,
521 };
522 self.advance();
523 k
524 }
525
526 fn parse_declarators(&mut self) -> Result<Vec<Declarator>, String> {
527 let mut decls = Vec::new();
528 loop {
529 let target = self.parse_binding_target()?;
530 let init = if self.eat_punct("=") {
531 Some(self.parse_assign()?)
532 } else {
533 None
534 };
535 decls.push(Declarator { target, init });
536 if !self.eat_punct(",") {
537 break;
538 }
539 }
540 Ok(decls)
541 }
542
543 fn parse_binding_target(&mut self) -> Result<Expr, String> {
545 if self.is_punct("[") {
546 self.parse_array_literal()
547 } else if self.is_punct("{") {
548 self.parse_object_literal()
549 } else {
550 Ok(Expr::Ident(self.ident_name()?))
551 }
552 }
553
554 fn parse_if(&mut self) -> Result<StmtKind, String> {
555 self.advance(); self.expect_punct("(")?;
557 let test = self.parse_expr()?;
558 self.expect_punct(")")?;
559 let cons = Box::new(self.parse_stmt()?);
560 let alt = if self.eat_kw("else") {
561 Some(Box::new(self.parse_stmt()?))
562 } else {
563 None
564 };
565 Ok(StmtKind::If { test, cons, alt })
566 }
567
568 fn parse_while(&mut self) -> Result<StmtKind, String> {
569 self.advance();
570 self.expect_punct("(")?;
571 let test = self.parse_expr()?;
572 self.expect_punct(")")?;
573 let body = Box::new(self.parse_stmt()?);
574 Ok(StmtKind::While { test, body })
575 }
576
577 fn parse_do_while(&mut self) -> Result<StmtKind, String> {
578 self.advance();
579 let body = Box::new(self.parse_stmt()?);
580 if !self.eat_kw("while") {
581 return Err(format!(
582 "SyntaxError: expected 'while' (line {})",
583 self.line()
584 ));
585 }
586 self.expect_punct("(")?;
587 let test = self.parse_expr()?;
588 self.expect_punct(")")?;
589 self.semicolon()?;
590 Ok(StmtKind::DoWhile { body, test })
591 }
592
593 fn parse_for(&mut self) -> Result<StmtKind, String> {
594 self.advance();
595 let is_await = self.eat_kw("await");
597 self.expect_punct("(")?;
598 let decl_kind = match self.tok() {
600 Tok::Ident(s) if s == "var" || s == "let" || s == "const" => {
601 Some(self.parse_decl_kind())
602 }
603 _ => None,
604 };
605 if decl_kind.is_none() && self.is_punct(";") {
607 return self.parse_c_for(None);
608 }
609 let first_target = if decl_kind.is_some() {
611 self.parse_binding_target()?
612 } else {
613 self.parse_expr_no_in()?
614 };
615 if self.eat_kw("of") {
616 let iter = self.parse_assign()?;
617 self.expect_punct(")")?;
618 let body = Box::new(self.parse_stmt()?);
619 return Ok(StmtKind::ForOf {
620 decl_kind,
621 target: first_target,
622 iter,
623 body,
624 is_await,
625 });
626 }
627 if self.eat_kw("in") {
628 let object = self.parse_assign()?;
629 self.expect_punct(")")?;
630 let body = Box::new(self.parse_stmt()?);
631 return Ok(StmtKind::ForIn {
632 decl_kind,
633 target: first_target,
634 object,
635 body,
636 });
637 }
638 let init_stmt = if let Some(k) = decl_kind {
640 let init = if self.eat_punct("=") {
641 Some(self.parse_assign()?)
642 } else {
643 None
644 };
645 let mut decls = vec![Declarator {
646 target: first_target,
647 init,
648 }];
649 while self.eat_punct(",") {
650 let target = self.parse_binding_target()?;
651 let init = if self.eat_punct("=") {
652 Some(self.parse_assign()?)
653 } else {
654 None
655 };
656 decls.push(Declarator { target, init });
657 }
658 StmtKind::Decl { kind: k, decls }
659 } else {
660 let init = if self.is_punct(",") {
663 let mut items = vec![first_target];
664 while self.eat_punct(",") {
665 items.push(self.parse_expr_no_in()?);
666 }
667 Expr::Sequence(items)
668 } else {
669 first_target
670 };
671 StmtKind::Expr(init)
672 };
673 self.parse_c_for(Some(Stmt::from(init_stmt)))
674 }
675
676 fn parse_c_for(&mut self, init: Option<Stmt>) -> Result<StmtKind, String> {
677 self.expect_punct(";")?;
678 let test = if self.is_punct(";") {
679 None
680 } else {
681 Some(self.parse_expr()?)
682 };
683 self.expect_punct(";")?;
684 let update = if self.is_punct(")") {
685 None
686 } else {
687 Some(self.parse_expr()?)
688 };
689 self.expect_punct(")")?;
690 let body = Box::new(self.parse_stmt()?);
691 Ok(StmtKind::For {
692 init: init.map(Box::new),
693 test,
694 update,
695 body,
696 })
697 }
698
699 fn parse_switch(&mut self) -> Result<StmtKind, String> {
700 self.advance();
701 self.expect_punct("(")?;
702 let disc = self.parse_expr()?;
703 self.expect_punct(")")?;
704 self.expect_punct("{")?;
705 let mut cases = Vec::new();
706 while !self.is_punct("}") && !self.at_eof() {
707 let test = if self.eat_kw("case") {
708 let e = self.parse_expr()?;
709 Some(e)
710 } else if self.eat_kw("default") {
711 None
712 } else {
713 return Err(format!(
714 "SyntaxError: expected 'case' or 'default' (line {})",
715 self.line()
716 ));
717 };
718 self.expect_punct(":")?;
719 let mut body = Vec::new();
720 while !self.is_punct("}")
721 && !self.is_kw("case")
722 && !self.is_kw("default")
723 && !self.at_eof()
724 {
725 body.push(self.parse_stmt()?);
726 }
727 cases.push(SwitchCase { test, body });
728 }
729 self.expect_punct("}")?;
730 Ok(StmtKind::Switch { disc, cases })
731 }
732
733 fn parse_try(&mut self) -> Result<StmtKind, String> {
734 self.advance();
735 self.expect_punct("{")?;
736 let block = self.parse_block_body()?;
737 let handler = if self.eat_kw("catch") {
738 let param = if self.eat_punct("(") {
739 let p = self.parse_binding_target()?;
740 self.expect_punct(")")?;
741 Some(p)
742 } else {
743 None
744 };
745 self.expect_punct("{")?;
746 let body = self.parse_block_body()?;
747 Some((param, body))
748 } else {
749 None
750 };
751 let finalizer = if self.eat_kw("finally") {
752 self.expect_punct("{")?;
753 Some(self.parse_block_body()?)
754 } else {
755 None
756 };
757 Ok(StmtKind::Try {
758 block,
759 handler,
760 finalizer,
761 })
762 }
763
764 fn parse_expr(&mut self) -> Result<Expr, String> {
767 let first = self.parse_assign()?;
768 if self.is_punct(",") {
769 let mut items = vec![first];
770 while self.eat_punct(",") {
771 items.push(self.parse_assign()?);
772 }
773 Ok(Expr::Sequence(items))
774 } else {
775 Ok(first)
776 }
777 }
778
779 fn parse_expr_no_in(&mut self) -> Result<Expr, String> {
781 let saved = self.no_in;
784 self.no_in = true;
785 let r = self.parse_assign();
786 self.no_in = saved;
787 r
788 }
789
790 fn allow_in<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, String>) -> Result<T, String> {
793 let saved = self.no_in;
794 self.no_in = false;
795 let r = f(self);
796 self.no_in = saved;
797 r
798 }
799
800 fn parse_assign(&mut self) -> Result<Expr, String> {
801 if let Some(arrow) = self.try_parse_arrow()? {
803 return Ok(arrow);
804 }
805 let left = self.parse_conditional()?;
806 let op = match self.tok() {
808 Tok::Punct(p) => p.clone(),
809 _ => return Ok(left),
810 };
811 let compound = match op.as_str() {
812 "=" => None,
813 "+=" => Some(BinOp::Add),
814 "-=" => Some(BinOp::Sub),
815 "*=" => Some(BinOp::Mul),
816 "/=" => Some(BinOp::Div),
817 "%=" => Some(BinOp::Mod),
818 "**=" => Some(BinOp::Pow),
819 "&=" => Some(BinOp::BitAnd),
820 "|=" => Some(BinOp::BitOr),
821 "^=" => Some(BinOp::BitXor),
822 "<<=" => Some(BinOp::Shl),
823 ">>=" => Some(BinOp::Shr),
824 ">>>=" => Some(BinOp::UShr),
825 "&&=" | "||=" | "??=" => {
826 self.advance();
828 let value = self.parse_assign()?;
829 let lop = match op.as_str() {
830 "&&=" => LogicalOp::And,
831 "||=" => LogicalOp::Or,
832 _ => LogicalOp::Nullish,
833 };
834 return Ok(Expr::Assign {
835 target: Box::new(left.clone()),
836 value: Box::new(Expr::Logical(lop, Box::new(left), Box::new(value))),
837 });
838 }
839 _ => return Ok(left),
840 };
841 self.advance();
842 let value = self.parse_assign()?;
843 let value = match compound {
844 None => value,
845 Some(b) => Expr::Binary(b, Box::new(left.clone()), Box::new(value)),
846 };
847 Ok(Expr::Assign {
848 target: Box::new(left),
849 value: Box::new(value),
850 })
851 }
852
853 fn parse_conditional(&mut self) -> Result<Expr, String> {
854 let test = self.parse_binary(0)?;
855 if self.eat_punct("?") {
856 let cons = self.parse_assign()?;
857 self.expect_punct(":")?;
858 let alt = self.parse_assign()?;
859 Ok(Expr::Conditional {
860 test: Box::new(test),
861 cons: Box::new(cons),
862 alt: Box::new(alt),
863 })
864 } else {
865 Ok(test)
866 }
867 }
868
869 fn parse_binary(&mut self, min_prec: u8) -> Result<Expr, String> {
871 let mut left = self.parse_unary()?;
872 while let Some((prec, right_assoc, logical, bin)) = self.bin_info() {
873 if prec < min_prec {
874 break;
875 }
876 self.advance();
877 let next_min = if right_assoc { prec } else { prec + 1 };
878 let right = self.parse_binary(next_min)?;
879 left = if let Some(lop) = logical {
880 Expr::Logical(lop, Box::new(left), Box::new(right))
881 } else {
882 Expr::Binary(bin.unwrap(), Box::new(left), Box::new(right))
883 };
884 }
885 Ok(left)
886 }
887
888 fn bin_info(&self) -> Option<(u8, bool, Option<LogicalOp>, Option<BinOp>)> {
890 let p = match self.tok() {
891 Tok::Punct(p) => p.as_str(),
892 Tok::Ident(s) if s == "in" => {
895 if self.no_in {
896 return None;
897 }
898 "in"
899 }
900 Tok::Ident(s) if s == "instanceof" => "instanceof",
901 _ => return None,
902 };
903 let (prec, ra, log, bin) = match p {
904 "??" => (1, false, Some(LogicalOp::Nullish), None),
905 "||" => (2, false, Some(LogicalOp::Or), None),
906 "&&" => (3, false, Some(LogicalOp::And), None),
907 "|" => (4, false, None, Some(BinOp::BitOr)),
908 "^" => (5, false, None, Some(BinOp::BitXor)),
909 "&" => (6, false, None, Some(BinOp::BitAnd)),
910 "==" => (7, false, None, Some(BinOp::EqEq)),
911 "!=" => (7, false, None, Some(BinOp::NeEq)),
912 "===" => (7, false, None, Some(BinOp::EqEqEq)),
913 "!==" => (7, false, None, Some(BinOp::NeEqEq)),
914 "<" => (8, false, None, Some(BinOp::Lt)),
915 "<=" => (8, false, None, Some(BinOp::Le)),
916 ">" => (8, false, None, Some(BinOp::Gt)),
917 ">=" => (8, false, None, Some(BinOp::Ge)),
918 "in" => (8, false, None, Some(BinOp::In)),
919 "instanceof" => (8, false, None, Some(BinOp::InstanceOf)),
920 "<<" => (9, false, None, Some(BinOp::Shl)),
921 ">>" => (9, false, None, Some(BinOp::Shr)),
922 ">>>" => (9, false, None, Some(BinOp::UShr)),
923 "+" => (10, false, None, Some(BinOp::Add)),
924 "-" => (10, false, None, Some(BinOp::Sub)),
925 "*" => (11, false, None, Some(BinOp::Mul)),
926 "/" => (11, false, None, Some(BinOp::Div)),
927 "%" => (11, false, None, Some(BinOp::Mod)),
928 "**" => (12, true, None, Some(BinOp::Pow)),
929 _ => return None,
930 };
931 Some((prec, ra, log, bin))
932 }
933
934 fn parse_unary(&mut self) -> Result<Expr, String> {
935 let op = match self.tok() {
936 Tok::Punct(p) if p == "!" => Some(UnOp::Not),
937 Tok::Punct(p) if p == "~" => Some(UnOp::BitNot),
938 Tok::Punct(p) if p == "+" => Some(UnOp::Pos),
939 Tok::Punct(p) if p == "-" => Some(UnOp::Neg),
940 Tok::Ident(s) if s == "typeof" => Some(UnOp::TypeOf),
941 Tok::Ident(s) if s == "void" => Some(UnOp::Void),
942 Tok::Ident(s) if s == "delete" => Some(UnOp::Delete),
943 _ => None,
944 };
945 if let Some(op) = op {
946 self.advance();
947 let e = self.parse_unary()?;
948 return Ok(Expr::Unary(op, Box::new(e)));
949 }
950 if self.is_punct("++") || self.is_punct("--") {
952 let op = if self.is_punct("++") {
953 UpdateOp::Inc
954 } else {
955 UpdateOp::Dec
956 };
957 self.advance();
958 let e = self.parse_unary()?;
959 return Ok(Expr::Update {
960 op,
961 prefix: true,
962 target: Box::new(e),
963 });
964 }
965 self.parse_postfix()
966 }
967
968 fn parse_postfix(&mut self) -> Result<Expr, String> {
969 let mut e = self.parse_call_member()?;
970 if (self.is_punct("++") || self.is_punct("--")) && !self.newline_before() {
972 let op = if self.is_punct("++") {
973 UpdateOp::Inc
974 } else {
975 UpdateOp::Dec
976 };
977 self.advance();
978 e = Expr::Update {
979 op,
980 prefix: false,
981 target: Box::new(e),
982 };
983 }
984 Ok(e)
985 }
986
987 fn parse_call_member(&mut self) -> Result<Expr, String> {
988 let mut e = if self.eat_kw("new") {
989 if self.is_punct(".") {
991 self.advance();
992 let prop = self.ident_name()?;
993 if prop != "target" {
994 return Err(format!(
995 "SyntaxError: expected 'target' (line {})",
996 self.line()
997 ));
998 }
999 Expr::NewTarget
1000 } else {
1001 let callee = self.parse_call_member_no_call()?;
1002 let args = if self.is_punct("(") {
1003 self.parse_args()?
1004 } else {
1005 Vec::new()
1006 };
1007 Expr::New {
1008 callee: Box::new(callee),
1009 args,
1010 }
1011 }
1012 } else {
1013 self.parse_primary()?
1014 };
1015 loop {
1016 if self.eat_punct(".") {
1017 let property = self.ident_name()?;
1018 e = Expr::Member {
1019 object: Box::new(e),
1020 property,
1021 optional: false,
1022 };
1023 } else if self.eat_punct("?.") {
1024 if self.is_punct("(") {
1025 let args = self.parse_args()?;
1026 e = Expr::Call {
1027 func: Box::new(e),
1028 args,
1029 optional: true,
1030 };
1031 } else if self.is_punct("[") {
1032 self.advance();
1033 let index = self.allow_in(|p| p.parse_expr())?;
1034 self.expect_punct("]")?;
1035 e = Expr::Index {
1036 object: Box::new(e),
1037 index: Box::new(index),
1038 optional: true,
1039 };
1040 } else {
1041 let property = self.ident_name()?;
1042 e = Expr::Member {
1043 object: Box::new(e),
1044 property,
1045 optional: true,
1046 };
1047 }
1048 } else if self.is_punct("[") {
1049 self.advance();
1050 let index = self.allow_in(|p| p.parse_expr())?;
1051 self.expect_punct("]")?;
1052 e = Expr::Index {
1053 object: Box::new(e),
1054 index: Box::new(index),
1055 optional: false,
1056 };
1057 } else if self.is_punct("(") {
1058 let args = self.parse_args()?;
1059 e = Expr::Call {
1060 func: Box::new(e),
1061 args,
1062 optional: false,
1063 };
1064 } else if matches!(self.tok(), Tok::Template { .. }) {
1065 e = self.parse_tagged_template(e)?;
1068 } else {
1069 break;
1070 }
1071 }
1072 Ok(e)
1073 }
1074
1075 fn parse_tagged_template(&mut self, tag: Expr) -> Result<Expr, String> {
1078 let (quasis, raws, exprs_src) = match self.tok().clone() {
1079 Tok::Template {
1080 quasis,
1081 raws,
1082 exprs,
1083 } => (quasis, raws, exprs),
1084 _ => unreachable!(),
1085 };
1086 self.advance();
1087 let mut exprs = Vec::new();
1088 for src in &exprs_src {
1089 exprs.push(parse_expr_source(src)?);
1090 }
1091 Ok(Expr::TaggedTemplate {
1092 tag: Box::new(tag),
1093 quasis,
1094 raws,
1095 exprs,
1096 })
1097 }
1098
1099 fn parse_call_member_no_call(&mut self) -> Result<Expr, String> {
1101 let mut e = self.parse_primary()?;
1102 loop {
1103 if self.eat_punct(".") {
1104 let property = self.ident_name()?;
1105 e = Expr::Member {
1106 object: Box::new(e),
1107 property,
1108 optional: false,
1109 };
1110 } else if self.is_punct("[") {
1111 self.advance();
1112 let index = self.allow_in(|p| p.parse_expr())?;
1113 self.expect_punct("]")?;
1114 e = Expr::Index {
1115 object: Box::new(e),
1116 index: Box::new(index),
1117 optional: false,
1118 };
1119 } else {
1120 break;
1121 }
1122 }
1123 Ok(e)
1124 }
1125
1126 fn parse_args(&mut self) -> Result<Vec<Expr>, String> {
1127 self.expect_punct("(")?;
1128 let args = self.allow_in(|p| {
1131 let mut args = Vec::new();
1132 while !p.is_punct(")") {
1133 if p.eat_punct("...") {
1134 let e = p.parse_assign()?;
1135 args.push(Expr::Spread(Box::new(e)));
1136 } else {
1137 args.push(p.parse_assign()?);
1138 }
1139 if !p.eat_punct(",") {
1140 break;
1141 }
1142 }
1143 Ok(args)
1144 })?;
1145 self.expect_punct(")")?;
1146 Ok(args)
1147 }
1148
1149 fn parse_primary(&mut self) -> Result<Expr, String> {
1150 match self.tok().clone() {
1151 Tok::Num(n) => {
1152 self.advance();
1153 Ok(Expr::Number(n))
1154 }
1155 Tok::BigInt(s) => {
1156 self.advance();
1157 Ok(Expr::BigInt(s))
1158 }
1159 Tok::Regex(pat, flags) => {
1160 self.advance();
1161 Ok(Expr::Regex(pat, flags))
1162 }
1163 Tok::Str(s) => {
1164 self.advance();
1165 Ok(Expr::Str(s))
1166 }
1167 Tok::Template {
1168 quasis,
1169 raws: _,
1170 exprs,
1171 } => {
1172 self.advance();
1173 let mut parsed = Vec::new();
1174 for src in &exprs {
1175 parsed.push(parse_expr_source(src)?);
1176 }
1177 Ok(Expr::Template {
1178 quasis,
1179 exprs: parsed,
1180 })
1181 }
1182 Tok::Punct(p) if p == "(" => {
1183 self.advance();
1184 let e = self.parse_expr()?;
1185 self.expect_punct(")")?;
1186 Ok(e)
1187 }
1188 Tok::Punct(p) if p == "[" => self.parse_array_literal(),
1189 Tok::Punct(p) if p == "{" => self.parse_object_literal(),
1190 Tok::Ident(s) => {
1191 match s.as_str() {
1192 "true" => {
1193 self.advance();
1194 Ok(Expr::True)
1195 }
1196 "false" => {
1197 self.advance();
1198 Ok(Expr::False)
1199 }
1200 "null" => {
1201 self.advance();
1202 Ok(Expr::Null)
1203 }
1204 "this" => {
1205 self.advance();
1206 Ok(Expr::This)
1207 }
1208 "super" => {
1209 self.advance();
1210 Ok(Expr::Super)
1211 }
1212 "class" => Ok(Expr::Class(Box::new(self.parse_class(false)?))),
1213 "function" => self.parse_function_expr(false),
1214 "async" if self.peek_kw(1, "function") && !self.peek_newline(1) => {
1215 self.advance(); self.parse_function_expr(true)
1217 }
1218 "yield" if self.in_generator => {
1219 self.advance();
1220 let delegate = self.eat_punct("*");
1221 let arg = if delegate
1224 || !(self.is_punct(")")
1225 || self.is_punct("]")
1226 || self.is_punct("}")
1227 || self.is_punct(",")
1228 || self.is_punct(";")
1229 || self.is_punct(":")
1230 || self.newline_before()
1231 || self.at_eof())
1232 {
1233 Some(Box::new(self.parse_assign()?))
1234 } else {
1235 None
1236 };
1237 Ok(Expr::Yield { arg, delegate })
1238 }
1239 "await" if self.in_async => {
1240 self.advance();
1241 let e = self.parse_unary()?;
1242 Ok(Expr::Await(Box::new(e)))
1243 }
1244 _ if is_keyword(&s) => Err(format!(
1245 "SyntaxError: unexpected keyword '{s}' (line {})",
1246 self.line()
1247 )),
1248 _ => {
1249 self.advance();
1250 Ok(Expr::Ident(s))
1251 }
1252 }
1253 }
1254 other => Err(format!(
1255 "SyntaxError: unexpected token {other:?} (line {})",
1256 self.line()
1257 )),
1258 }
1259 }
1260
1261 fn parse_array_literal(&mut self) -> Result<Expr, String> {
1262 self.expect_punct("[")?;
1263 let mut items = Vec::new();
1264 while !self.is_punct("]") {
1265 if self.is_punct(",") {
1266 items.push(Expr::Undefined);
1268 self.advance();
1269 continue;
1270 }
1271 if self.eat_punct("...") {
1272 let e = self.parse_assign()?;
1273 items.push(Expr::Spread(Box::new(e)));
1274 } else {
1275 items.push(self.parse_assign()?);
1276 }
1277 if !self.eat_punct(",") {
1278 break;
1279 }
1280 }
1281 self.expect_punct("]")?;
1282 Ok(Expr::Array(items))
1283 }
1284
1285 fn parse_object_literal(&mut self) -> Result<Expr, String> {
1286 self.expect_punct("{")?;
1287 let mut props = Vec::new();
1288 while !self.is_punct("}") {
1289 if self.eat_punct("...") {
1290 let e = self.parse_assign()?;
1291 props.push(Prop::Spread(e));
1292 if !self.eat_punct(",") {
1293 break;
1294 }
1295 continue;
1296 }
1297 if (self.is_kw("get") || self.is_kw("set"))
1300 && !self.peek_is_member_punct(1)
1301 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1302 {
1303 let is_getter = self.is_kw("get");
1304 self.advance();
1305 let (key, computed) = self.parse_property_key()?;
1306 let params = self.parse_params()?;
1307 self.expect_punct("{")?;
1308 let body = self.parse_block_body()?;
1309 let func = Expr::Function {
1310 params,
1311 body: FnBody::Block(body),
1312 is_arrow: false,
1313 name: None,
1314 is_generator: false,
1315 is_async: false,
1316 };
1317 props.push(Prop::Accessor {
1318 key,
1319 computed,
1320 is_getter,
1321 func,
1322 });
1323 if !self.eat_punct(",") {
1324 break;
1325 }
1326 continue;
1327 }
1328 let mut m_async = false;
1330 let mut m_gen = false;
1331 if self.is_kw("async")
1332 && !self.peek_is_member_punct(1)
1333 && !self.peek_newline(1)
1334 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1335 {
1336 self.advance();
1337 m_async = true;
1338 }
1339 if self.is_punct("*") {
1340 self.advance();
1341 m_gen = true;
1342 }
1343 let (key, computed) = self.parse_property_key()?;
1344 if self.is_punct("(") {
1346 let params = self.parse_params()?;
1347 self.expect_punct("{")?;
1348 let body = self.parse_fn_body_block(m_gen, m_async)?;
1349 let f = Expr::Function {
1350 params,
1351 body: FnBody::Block(body),
1352 is_arrow: false,
1353 name: None,
1354 is_generator: m_gen,
1355 is_async: m_async,
1356 };
1357 props.push(Prop::KeyValue {
1358 key,
1359 value: f,
1360 computed,
1361 });
1362 } else if self.eat_punct(":") {
1363 let value = self.parse_assign()?;
1364 props.push(Prop::KeyValue {
1365 key,
1366 value,
1367 computed,
1368 });
1369 } else {
1370 let name = match &key {
1373 Expr::Str(s) => s.clone(),
1374 _ => return Err(format!("SyntaxError: bad shorthand (line {})", self.line())),
1375 };
1376 let value = if self.eat_punct("=") {
1377 let d = self.parse_assign()?;
1379 Expr::Assign {
1380 target: Box::new(Expr::Ident(name.clone())),
1381 value: Box::new(d),
1382 }
1383 } else {
1384 Expr::Ident(name)
1385 };
1386 props.push(Prop::KeyValue {
1387 key,
1388 value,
1389 computed,
1390 });
1391 }
1392 if !self.eat_punct(",") {
1393 break;
1394 }
1395 }
1396 self.expect_punct("}")?;
1397 Ok(Expr::Object(props))
1398 }
1399
1400 fn parse_params(&mut self) -> Result<Vec<Param>, String> {
1402 self.expect_punct("(")?;
1403 let mut params = Vec::new();
1404 while !self.is_punct(")") {
1405 let rest = self.eat_punct("...");
1406 let pattern = self.parse_binding_target()?;
1407 let default = if !rest && self.eat_punct("=") {
1408 Some(self.parse_assign()?)
1409 } else {
1410 None
1411 };
1412 params.push(Param {
1413 pattern,
1414 default,
1415 rest,
1416 });
1417 if !self.eat_punct(",") {
1418 break;
1419 }
1420 }
1421 self.expect_punct(")")?;
1422 Ok(params)
1423 }
1424
1425 fn try_parse_arrow(&mut self) -> Result<Option<Expr>, String> {
1428 let mut is_async = false;
1431 let mut base = self.pos;
1432 if self.is_kw("async") && !self.peek_newline(1) {
1433 let next = self.toks.get(self.pos + 1).map(|t| &t.tok);
1434 let looks_async_arrow = matches!(next, Some(Tok::Punct(p)) if p == "(")
1435 || matches!(next, Some(Tok::Ident(n)) if !is_keyword(n) && self.peek_is_arrow_after(2));
1436 if looks_async_arrow {
1437 is_async = true;
1438 base += 1;
1439 }
1440 }
1441 if let Some(Tok::Ident(name)) = self.toks.get(base).map(|t| &t.tok) {
1443 if !is_keyword(name)
1444 && matches!(self.toks.get(base + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1445 {
1446 let name = name.clone();
1447 if is_async {
1448 self.advance(); }
1450 self.advance(); self.advance(); let body = self.parse_arrow_body(is_async)?;
1453 return Ok(Some(Expr::Function {
1454 params: vec![Param {
1455 pattern: Expr::Ident(name),
1456 default: None,
1457 rest: false,
1458 }],
1459 body,
1460 is_arrow: true,
1461 name: None,
1462 is_generator: false,
1463 is_async,
1464 }));
1465 }
1466 }
1467 if matches!(self.toks.get(base).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "(") {
1469 if let Some(close) = self.matching_paren(base) {
1470 let after = close + 1;
1471 if matches!(self.toks.get(after).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1472 {
1473 if is_async {
1474 self.advance(); }
1476 let params = self.parse_params()?;
1477 self.expect_punct("=>")?;
1478 let body = self.parse_arrow_body(is_async)?;
1479 return Ok(Some(Expr::Function {
1480 params,
1481 body,
1482 is_arrow: true,
1483 name: None,
1484 is_generator: false,
1485 is_async,
1486 }));
1487 }
1488 }
1489 }
1490 Ok(None)
1491 }
1492
1493 fn parse_arrow_body(&mut self, is_async: bool) -> Result<FnBody, String> {
1494 let (pg, pa) = (self.in_generator, self.in_async);
1495 self.in_generator = false;
1496 self.in_async = is_async;
1497 let r = if self.is_punct("{") {
1498 self.advance();
1499 self.parse_block_body().map(FnBody::Block)
1500 } else {
1501 self.parse_assign().map(|e| FnBody::Expr(Box::new(e)))
1502 };
1503 self.in_generator = pg;
1504 self.in_async = pa;
1505 r
1506 }
1507
1508 fn peek_is_arrow_after(&self, n: usize) -> bool {
1510 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1511 }
1512
1513 fn matching_paren(&self, open: usize) -> Option<usize> {
1515 let mut depth = 0i32;
1516 let mut i = open;
1517 while i < self.toks.len() {
1518 match &self.toks[i].tok {
1519 Tok::Punct(p) if p == "(" || p == "[" || p == "{" => depth += 1,
1520 Tok::Punct(p) if p == ")" || p == "]" || p == "}" => {
1521 depth -= 1;
1522 if depth == 0 {
1523 return Some(i);
1524 }
1525 }
1526 Tok::Eof => return None,
1527 _ => {}
1528 }
1529 i += 1;
1530 }
1531 None
1532 }
1533}
1534
1535fn parse_expr_source(src: &str) -> Result<Expr, String> {
1537 let toks = lex(src)?;
1538 let mut p = Parser {
1539 toks,
1540 pos: 0,
1541 in_generator: false,
1542 in_async: false,
1543 no_in: false,
1544 };
1545 let e = p.parse_expr()?;
1546 Ok(e)
1547}