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
50#[derive(Default)]
52struct PrivateScope {
53 declared: Vec<String>,
54 used: Vec<String>,
55}
56
57fn private_not_declared(name: &str) -> String {
58 format!("SyntaxError: Private field '{name}' must be declared in an enclosing class")
59}
60
61struct Parser {
62 toks: Vec<Token>,
63 pos: usize,
64 in_generator: bool,
66 in_async: bool,
68 no_in: bool,
73 class_scopes: Vec<PrivateScope>,
79 spans: bool,
82}
83
84pub fn parse(src: &str) -> Result<Vec<Stmt>, String> {
87 let desugared = crate::rust_ffi::desugar(src);
88 let spans = desugared == src;
91 let toks = lex(&desugared)?;
92 let mut p = Parser {
93 toks,
94 pos: 0,
95 in_generator: false,
96 in_async: false,
97 no_in: false,
98 class_scopes: Vec::new(),
99 spans,
100 };
101 let mut out = Vec::new();
102 while !p.at_eof() {
103 out.push(p.parse_stmt()?);
104 }
105 Ok(out)
106}
107
108impl Parser {
109 fn cur(&self) -> &Token {
111 &self.toks[self.pos]
112 }
113 fn parse_field(&mut self, src: &str, at: u32) -> Result<Expr, String> {
121 let mut p = field_parser(src, self.spans.then_some(at))?;
122 p.in_generator = self.in_generator;
123 p.in_async = self.in_async;
124 if !self.class_scopes.is_empty() {
125 p.class_scopes.push(PrivateScope::default());
126 }
127 let e = p.parse_expr()?;
128 if let (Some(scope), Some(inner)) = (self.class_scopes.last_mut(), p.class_scopes.pop()) {
129 scope.used.extend(inner.used);
130 }
131 Ok(e)
132 }
133
134 fn start_at(&self, i: usize) -> u32 {
136 self.toks[i].start
137 }
138 fn span_from(&self, start: u32) -> Span {
140 if !self.spans || self.pos == 0 {
141 return (0, 0);
142 }
143 (start, self.toks[self.pos - 1].end)
144 }
145 fn tok(&self) -> &Tok {
146 &self.toks[self.pos].tok
147 }
148 fn line(&self) -> u32 {
149 self.toks[self.pos].line
150 }
151 fn at_eof(&self) -> bool {
152 matches!(self.tok(), Tok::Eof)
153 }
154 fn newline_before(&self) -> bool {
155 self.cur().newline_before
156 }
157 fn advance(&mut self) -> Tok {
158 let t = self.toks[self.pos].tok.clone();
159 if self.pos + 1 < self.toks.len() {
160 self.pos += 1;
161 }
162 t
163 }
164
165 fn is_punct(&self, s: &str) -> bool {
167 matches!(self.tok(), Tok::Punct(p) if p == s)
168 }
169 fn is_kw(&self, s: &str) -> bool {
171 matches!(self.tok(), Tok::Ident(i) if i == s)
172 }
173 fn eat_punct(&mut self, s: &str) -> bool {
175 if self.is_punct(s) {
176 self.advance();
177 true
178 } else {
179 false
180 }
181 }
182 fn eat_kw(&mut self, s: &str) -> bool {
183 if self.is_kw(s) {
184 self.advance();
185 true
186 } else {
187 false
188 }
189 }
190 fn expect_punct(&mut self, s: &str) -> Result<(), String> {
191 if self.eat_punct(s) {
192 Ok(())
193 } else {
194 Err(format!(
195 "SyntaxError: expected '{s}' but found {:?} (line {})",
196 self.tok(),
197 self.line()
198 ))
199 }
200 }
201
202 fn ident_name(&mut self) -> Result<String, String> {
205 match self.tok().clone() {
206 Tok::Ident(s) => {
207 self.advance();
208 Ok(s)
209 }
210 other => Err(format!(
211 "SyntaxError: expected identifier but found {other:?} (line {})",
212 self.line()
213 )),
214 }
215 }
216
217 fn semicolon(&mut self) -> Result<(), String> {
219 if self.eat_punct(";") {
220 return Ok(());
221 }
222 if self.newline_before() || self.is_punct("}") || self.at_eof() {
223 return Ok(());
224 }
225 Err(format!(
226 "SyntaxError: expected ';' but found {:?} (line {})",
227 self.tok(),
228 self.line()
229 ))
230 }
231
232 fn parse_stmt(&mut self) -> Result<Stmt, String> {
234 let line = self.line();
235 let kind = match self.tok().clone() {
236 Tok::Punct(p) if p == "{" => {
237 self.advance();
238 StmtKind::Block(self.parse_block_body()?)
239 }
240 Tok::Punct(p) if p == ";" => {
241 self.advance();
242 StmtKind::Empty
243 }
244 Tok::Ident(kw) if kw == "var" || kw == "let" || kw == "const" => {
245 let k = self.parse_decl_kind();
246 let decls = self.parse_declarators()?;
247 self.semicolon()?;
248 StmtKind::Decl { kind: k, decls }
249 }
250 Tok::Ident(kw) if kw == "function" => self.parse_func_decl(false)?,
251 Tok::Ident(kw)
254 if kw == "async" && self.peek_kw(1, "function") && !self.peek_newline(1) =>
255 {
256 self.advance(); self.parse_func_decl(true)?
258 }
259 Tok::Ident(kw) if kw == "class" => {
260 let node = self.parse_class(true)?;
261 StmtKind::ClassDecl(node)
262 }
263 Tok::Ident(kw) if kw == "if" => self.parse_if()?,
264 Tok::Ident(kw) if kw == "while" => self.parse_while()?,
265 Tok::Ident(kw) if kw == "do" => self.parse_do_while()?,
266 Tok::Ident(kw) if kw == "for" => self.parse_for()?,
267 Tok::Ident(kw) if kw == "switch" => self.parse_switch()?,
268 Tok::Ident(kw) if kw == "return" => {
269 self.advance();
270 let arg = if self.is_punct(";")
271 || self.is_punct("}")
272 || self.newline_before()
273 || self.at_eof()
274 {
275 None
276 } else {
277 Some(self.parse_expr()?)
278 };
279 self.semicolon()?;
280 StmtKind::Return(arg)
281 }
282 Tok::Ident(kw) if kw == "break" => {
283 self.advance();
284 let label = self.opt_label();
285 self.semicolon()?;
286 StmtKind::Break(label)
287 }
288 Tok::Ident(kw) if kw == "continue" => {
289 self.advance();
290 let label = self.opt_label();
291 self.semicolon()?;
292 StmtKind::Continue(label)
293 }
294 Tok::Ident(kw) if kw == "throw" => {
295 self.advance();
296 let e = self.parse_expr()?;
297 self.semicolon()?;
298 StmtKind::Throw(e)
299 }
300 Tok::Ident(kw) if kw == "try" => self.parse_try()?,
301 Tok::Ident(name) if matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":") =>
306 {
307 self.advance(); self.advance(); let body = Box::new(self.parse_stmt()?);
310 StmtKind::Labeled { label: name, body }
311 }
312 _ => {
313 let e = self.parse_expr()?;
314 self.semicolon()?;
315 StmtKind::Expr(e)
316 }
317 };
318 Ok(Stmt::new(kind, line))
319 }
320
321 fn peek_kw(&self, n: usize, kw: &str) -> bool {
323 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Ident(s)) if s == kw)
324 }
325 fn peek_newline(&self, n: usize) -> bool {
327 self.toks
328 .get(self.pos + n)
329 .map(|t| t.newline_before)
330 .unwrap_or(false)
331 }
332
333 fn parse_func_decl(&mut self, is_async: bool) -> Result<StmtKind, String> {
336 let start = self.start_at(if is_async { self.pos - 1 } else { self.pos });
338 self.advance(); let is_generator = self.eat_punct("*");
340 let name = self.ident_name()?;
341 let params = self.parse_params()?;
342 self.expect_punct("{")?;
343 let body = self.parse_fn_body_block(is_generator, is_async)?;
344 Ok(StmtKind::FuncDecl {
345 name,
346 params,
347 body,
348 is_generator,
349 is_async,
350 span: self.span_from(start),
351 })
352 }
353
354 fn parse_fn_body_block(
357 &mut self,
358 is_generator: bool,
359 is_async: bool,
360 ) -> Result<Vec<Stmt>, String> {
361 let (pg, pa) = (self.in_generator, self.in_async);
362 self.in_generator = is_generator;
363 self.in_async = is_async;
364 let body = self.parse_block_body();
365 self.in_generator = pg;
366 self.in_async = pa;
367 body
368 }
369
370 fn parse_function_expr(&mut self, is_async: bool) -> Result<Expr, String> {
373 let start = self.start_at(if is_async { self.pos - 1 } else { self.pos });
374 self.advance(); let is_generator = self.eat_punct("*");
376 let name = if let Tok::Ident(n) = self.tok() {
377 if !is_keyword(n) {
378 let n = n.clone();
379 self.advance();
380 Some(n)
381 } else {
382 None
383 }
384 } else {
385 None
386 };
387 let params = self.parse_params()?;
388 self.expect_punct("{")?;
389 let body = self.parse_fn_body_block(is_generator, is_async)?;
390 Ok(Expr::Function {
391 params,
392 body: FnBody::Block(body),
393 is_arrow: false,
394 name,
395 is_generator,
396 is_async,
397 is_method: false,
398 span: self.span_from(start),
399 })
400 }
401
402 fn check_private_in_scope(&mut self, property: &str) -> Result<(), String> {
410 if !property.starts_with('#') {
411 return Ok(());
412 }
413 match self.class_scopes.last_mut() {
414 Some(scope) => scope.used.push(property.to_string()),
417 None => return Err(private_not_declared(property)),
418 }
419 Ok(())
420 }
421
422 fn parse_class(&mut self, _decl: bool) -> Result<ClassNode, String> {
423 self.class_scopes.push(PrivateScope::default());
424 let out = self.parse_class_inner();
425 let scope = self.class_scopes.pop().unwrap_or_default();
426 let out = out?;
427 for name in &scope.used {
428 if scope.declared.contains(name) {
429 continue;
430 }
431 match self.class_scopes.last_mut() {
434 Some(outer) => outer.used.push(name.clone()),
435 None => return Err(private_not_declared(name)),
436 }
437 }
438 Ok(out)
439 }
440
441 fn parse_class_inner(&mut self) -> Result<ClassNode, String> {
442 let start = self.start_at(self.pos);
443 self.advance(); let name = if let Tok::Ident(n) = self.tok() {
445 if !is_keyword(n) && n != "extends" {
446 let n = n.clone();
447 self.advance();
448 Some(n)
449 } else {
450 None
451 }
452 } else {
453 None
454 };
455 let parent = if self.eat_kw("extends") {
456 Some(Box::new(self.parse_call_member()?))
459 } else {
460 None
461 };
462 self.expect_punct("{")?;
463 let mut members = Vec::new();
464 while !self.is_punct("}") && !self.at_eof() {
465 if self.eat_punct(";") {
466 continue; }
468 let member = self.parse_class_member()?;
469 if let Expr::Str(k) = &member.key {
470 if k.starts_with('#') {
471 if let Some(scope) = self.class_scopes.last_mut() {
472 scope.declared.push(k.clone());
473 }
474 }
475 }
476 members.push(member);
477 }
478 self.expect_punct("}")?;
479 Ok(ClassNode {
480 name,
481 parent,
482 members,
483 span: self.span_from(start),
484 })
485 }
486
487 fn parse_class_member(&mut self) -> Result<ClassMember, String> {
490 let is_static = self.is_kw("static") && !self.peek_is_member_punct(1) && {
491 self.advance();
492 true
493 };
494 let start = self.start_at(self.pos);
495 if is_static && self.is_punct("{") {
500 self.advance();
501 let body = self.parse_fn_body_block(false, false)?;
504 return Ok(ClassMember {
505 key: Expr::Str(String::new()),
506 computed: false,
507 kind: MemberKind::StaticBlock,
508 is_static: true,
509 is_generator: false,
510 is_async: false,
511 params: Vec::new(),
512 body,
513 field_init: None,
514 span: self.span_from(start),
515 });
516 }
517 let mut kind = MemberKind::Method;
520 let mut is_async = false;
521 let mut is_generator = false;
522 if self.is_kw("get") && !self.peek_is_member_punct(1) {
523 self.advance();
524 kind = MemberKind::Get;
525 } else if self.is_kw("set") && !self.peek_is_member_punct(1) {
526 self.advance();
527 kind = MemberKind::Set;
528 } else {
529 if self.is_kw("async") && !self.peek_is_member_punct(1) && !self.peek_newline(1) {
530 self.advance();
531 is_async = true;
532 }
533 if self.eat_punct("*") {
534 is_generator = true;
535 }
536 }
537 let (key, computed) = self.parse_property_key()?;
539 if kind == MemberKind::Method && !self.is_punct("(") {
541 let field_init = if self.eat_punct("=") {
542 Some(self.parse_assign()?)
543 } else {
544 None
545 };
546 self.semicolon()?;
547 return Ok(ClassMember {
548 key,
549 computed,
550 kind: MemberKind::Field,
551 is_static,
552 is_generator: false,
553 is_async: false,
554 params: Vec::new(),
555 body: Vec::new(),
556 field_init,
557 span: (0, 0),
558 });
559 }
560 let is_ctor = !is_static
562 && !computed
563 && matches!(&key, Expr::Str(s) if s == "constructor")
564 && kind == MemberKind::Method;
565 let params = self.parse_params()?;
566 self.expect_punct("{")?;
567 let body = self.parse_fn_body_block(is_generator, is_async)?;
568 Ok(ClassMember {
569 key,
570 computed,
571 kind: if is_ctor {
572 MemberKind::Constructor
573 } else {
574 kind
575 },
576 is_static,
577 is_generator,
578 is_async,
579 params,
580 body,
581 field_init: None,
582 span: self.span_from(start),
583 })
584 }
585
586 fn peek_is_member_punct(&self, n: usize) -> bool {
589 matches!(
590 self.toks.get(self.pos + n).map(|t| &t.tok),
591 Some(Tok::Punct(p)) if p == "(" || p == "=" || p == ";" || p == "}"
592 )
593 }
594
595 fn parse_property_key(&mut self) -> Result<(Expr, bool), String> {
598 if self.is_punct("[") {
599 self.advance();
600 let k = self.parse_assign()?;
601 self.expect_punct("]")?;
602 Ok((k, true))
603 } else {
604 match self.tok().clone() {
605 Tok::Str(s) => {
606 self.advance();
607 Ok((Expr::Str(s), false))
608 }
609 Tok::Num(n) => {
610 self.advance();
611 Ok((Expr::Str(crate::host::fmt_number(n)), false))
612 }
613 Tok::Ident(s) => {
614 self.advance();
615 Ok((Expr::Str(s), false))
616 }
617 other => Err(format!(
618 "SyntaxError: bad member key {other:?} (line {})",
619 self.line()
620 )),
621 }
622 }
623 }
624
625 fn opt_label(&mut self) -> Option<String> {
627 if self.newline_before() {
628 return None;
629 }
630 if let Tok::Ident(s) = self.tok() {
631 if !is_keyword(s) {
632 let s = s.clone();
633 self.advance();
634 return Some(s);
635 }
636 }
637 None
638 }
639
640 fn parse_block_body(&mut self) -> Result<Vec<Stmt>, String> {
642 let mut out = Vec::new();
643 while !self.is_punct("}") && !self.at_eof() {
644 out.push(self.parse_stmt()?);
645 }
646 self.expect_punct("}")?;
647 Ok(out)
648 }
649
650 fn parse_decl_kind(&mut self) -> DeclKind {
651 let k = match self.tok() {
652 Tok::Ident(s) if s == "let" => DeclKind::Let,
653 Tok::Ident(s) if s == "const" => DeclKind::Const,
654 _ => DeclKind::Var,
655 };
656 self.advance();
657 k
658 }
659
660 fn parse_declarators(&mut self) -> Result<Vec<Declarator>, String> {
661 let mut decls = Vec::new();
662 loop {
663 let target = self.parse_binding_target()?;
664 let init = if self.eat_punct("=") {
665 Some(self.parse_assign()?)
666 } else {
667 None
668 };
669 decls.push(Declarator { target, init });
670 if !self.eat_punct(",") {
671 break;
672 }
673 }
674 Ok(decls)
675 }
676
677 fn parse_binding_target(&mut self) -> Result<Expr, String> {
679 if self.is_punct("[") {
680 self.parse_array_literal()
681 } else if self.is_punct("{") {
682 self.parse_object_literal()
683 } else {
684 Ok(Expr::Ident(self.ident_name()?))
685 }
686 }
687
688 fn parse_if(&mut self) -> Result<StmtKind, String> {
689 self.advance(); self.expect_punct("(")?;
691 let test = self.parse_expr()?;
692 self.expect_punct(")")?;
693 let cons = Box::new(self.parse_stmt()?);
694 let alt = if self.eat_kw("else") {
695 Some(Box::new(self.parse_stmt()?))
696 } else {
697 None
698 };
699 Ok(StmtKind::If { test, cons, alt })
700 }
701
702 fn parse_while(&mut self) -> Result<StmtKind, String> {
703 self.advance();
704 self.expect_punct("(")?;
705 let test = self.parse_expr()?;
706 self.expect_punct(")")?;
707 let body = Box::new(self.parse_stmt()?);
708 Ok(StmtKind::While { test, body })
709 }
710
711 fn parse_do_while(&mut self) -> Result<StmtKind, String> {
712 self.advance();
713 let body = Box::new(self.parse_stmt()?);
714 if !self.eat_kw("while") {
715 return Err(format!(
716 "SyntaxError: expected 'while' (line {})",
717 self.line()
718 ));
719 }
720 self.expect_punct("(")?;
721 let test = self.parse_expr()?;
722 self.expect_punct(")")?;
723 self.semicolon()?;
724 Ok(StmtKind::DoWhile { body, test })
725 }
726
727 fn parse_for(&mut self) -> Result<StmtKind, String> {
728 self.advance();
729 let is_await = self.eat_kw("await");
731 self.expect_punct("(")?;
732 let decl_kind = match self.tok() {
734 Tok::Ident(s) if s == "var" || s == "let" || s == "const" => {
735 Some(self.parse_decl_kind())
736 }
737 _ => None,
738 };
739 if decl_kind.is_none() && self.is_punct(";") {
741 return self.parse_c_for(None);
742 }
743 let first_target = if decl_kind.is_some() {
745 self.parse_binding_target()?
746 } else {
747 self.parse_expr_no_in()?
748 };
749 if self.eat_kw("of") {
750 let iter = self.parse_assign()?;
751 self.expect_punct(")")?;
752 let body = Box::new(self.parse_stmt()?);
753 return Ok(StmtKind::ForOf {
754 decl_kind,
755 target: first_target,
756 iter,
757 body,
758 is_await,
759 });
760 }
761 if self.eat_kw("in") {
762 let object = self.parse_assign()?;
763 self.expect_punct(")")?;
764 let body = Box::new(self.parse_stmt()?);
765 return Ok(StmtKind::ForIn {
766 decl_kind,
767 target: first_target,
768 object,
769 body,
770 });
771 }
772 let init_stmt = if let Some(k) = decl_kind {
774 let init = if self.eat_punct("=") {
775 Some(self.parse_assign()?)
776 } else {
777 None
778 };
779 let mut decls = vec![Declarator {
780 target: first_target,
781 init,
782 }];
783 while self.eat_punct(",") {
784 let target = self.parse_binding_target()?;
785 let init = if self.eat_punct("=") {
786 Some(self.parse_assign()?)
787 } else {
788 None
789 };
790 decls.push(Declarator { target, init });
791 }
792 StmtKind::Decl { kind: k, decls }
793 } else {
794 let init = if self.is_punct(",") {
797 let mut items = vec![first_target];
798 while self.eat_punct(",") {
799 items.push(self.parse_expr_no_in()?);
800 }
801 Expr::Sequence(items)
802 } else {
803 first_target
804 };
805 StmtKind::Expr(init)
806 };
807 self.parse_c_for(Some(Stmt::from(init_stmt)))
808 }
809
810 fn parse_c_for(&mut self, init: Option<Stmt>) -> Result<StmtKind, String> {
811 self.expect_punct(";")?;
812 let test = if self.is_punct(";") {
813 None
814 } else {
815 Some(self.parse_expr()?)
816 };
817 self.expect_punct(";")?;
818 let update = if self.is_punct(")") {
819 None
820 } else {
821 Some(self.parse_expr()?)
822 };
823 self.expect_punct(")")?;
824 let body = Box::new(self.parse_stmt()?);
825 Ok(StmtKind::For {
826 init: init.map(Box::new),
827 test,
828 update,
829 body,
830 })
831 }
832
833 fn parse_switch(&mut self) -> Result<StmtKind, String> {
834 self.advance();
835 self.expect_punct("(")?;
836 let disc = self.parse_expr()?;
837 self.expect_punct(")")?;
838 self.expect_punct("{")?;
839 let mut cases = Vec::new();
840 while !self.is_punct("}") && !self.at_eof() {
841 let test = if self.eat_kw("case") {
842 let e = self.parse_expr()?;
843 Some(e)
844 } else if self.eat_kw("default") {
845 None
846 } else {
847 return Err(format!(
848 "SyntaxError: expected 'case' or 'default' (line {})",
849 self.line()
850 ));
851 };
852 self.expect_punct(":")?;
853 let mut body = Vec::new();
854 while !self.is_punct("}")
855 && !self.is_kw("case")
856 && !self.is_kw("default")
857 && !self.at_eof()
858 {
859 body.push(self.parse_stmt()?);
860 }
861 cases.push(SwitchCase { test, body });
862 }
863 self.expect_punct("}")?;
864 Ok(StmtKind::Switch { disc, cases })
865 }
866
867 fn parse_try(&mut self) -> Result<StmtKind, String> {
868 self.advance();
869 self.expect_punct("{")?;
870 let block = self.parse_block_body()?;
871 let handler = if self.eat_kw("catch") {
872 let param = if self.eat_punct("(") {
873 let p = self.parse_binding_target()?;
874 self.expect_punct(")")?;
875 Some(p)
876 } else {
877 None
878 };
879 self.expect_punct("{")?;
880 let body = self.parse_block_body()?;
881 Some((param, body))
882 } else {
883 None
884 };
885 let finalizer = if self.eat_kw("finally") {
886 self.expect_punct("{")?;
887 Some(self.parse_block_body()?)
888 } else {
889 None
890 };
891 Ok(StmtKind::Try {
892 block,
893 handler,
894 finalizer,
895 })
896 }
897
898 fn parse_expr(&mut self) -> Result<Expr, String> {
901 let first = self.parse_assign()?;
902 if self.is_punct(",") {
903 let mut items = vec![first];
904 while self.eat_punct(",") {
905 items.push(self.parse_assign()?);
906 }
907 Ok(Expr::Sequence(items))
908 } else {
909 Ok(first)
910 }
911 }
912
913 fn parse_expr_no_in(&mut self) -> Result<Expr, String> {
915 let saved = self.no_in;
918 self.no_in = true;
919 let r = self.parse_assign();
920 self.no_in = saved;
921 r
922 }
923
924 fn has_optional_link(e: &Expr) -> bool {
928 match e {
929 Expr::Member {
930 object, optional, ..
931 } => *optional || Self::has_optional_link(object),
932 Expr::Index {
933 object, optional, ..
934 } => *optional || Self::has_optional_link(object),
935 Expr::Call { func, optional, .. } => *optional || Self::has_optional_link(func),
936 _ => false,
937 }
938 }
939
940 fn allow_in<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, String>) -> Result<T, String> {
943 let saved = self.no_in;
944 self.no_in = false;
945 let r = f(self);
946 self.no_in = saved;
947 r
948 }
949
950 fn parse_assign(&mut self) -> Result<Expr, String> {
951 if let Some(arrow) = self.try_parse_arrow()? {
953 return Ok(arrow);
954 }
955 let left = self.parse_conditional()?;
956 let op = match self.tok() {
958 Tok::Punct(p) => p.clone(),
959 _ => return Ok(left),
960 };
961 let compound = match op.as_str() {
962 "=" => None,
963 "+=" => Some(BinOp::Add),
964 "-=" => Some(BinOp::Sub),
965 "*=" => Some(BinOp::Mul),
966 "/=" => Some(BinOp::Div),
967 "%=" => Some(BinOp::Mod),
968 "**=" => Some(BinOp::Pow),
969 "&=" => Some(BinOp::BitAnd),
970 "|=" => Some(BinOp::BitOr),
971 "^=" => Some(BinOp::BitXor),
972 "<<=" => Some(BinOp::Shl),
973 ">>=" => Some(BinOp::Shr),
974 ">>>=" => Some(BinOp::UShr),
975 "&&=" | "||=" | "??=" => {
976 self.advance();
982 let value = self.parse_assign()?;
983 let lop = match op.as_str() {
984 "&&=" => LogicalOp::And,
985 "||=" => LogicalOp::Or,
986 _ => LogicalOp::Nullish,
987 };
988 return Ok(Expr::Assign {
989 target: Box::new(left),
990 op: Some(AssignOp::Logical(lop)),
991 value: Box::new(value),
992 });
993 }
994 _ => return Ok(left),
995 };
996 self.advance();
997 let value = self.parse_assign()?;
998 Ok(Expr::Assign {
999 target: Box::new(left),
1000 op: compound.map(AssignOp::Binary),
1001 value: Box::new(value),
1002 })
1003 }
1004
1005 fn parse_conditional(&mut self) -> Result<Expr, String> {
1006 let test = self.parse_binary(0)?;
1007 if self.eat_punct("?") {
1008 let cons = self.parse_assign()?;
1009 self.expect_punct(":")?;
1010 let alt = self.parse_assign()?;
1011 Ok(Expr::Conditional {
1012 test: Box::new(test),
1013 cons: Box::new(cons),
1014 alt: Box::new(alt),
1015 })
1016 } else {
1017 Ok(test)
1018 }
1019 }
1020
1021 fn parse_binary(&mut self, min_prec: u8) -> Result<Expr, String> {
1023 let mut left = self.parse_unary()?;
1024 while let Some((prec, right_assoc, logical, bin)) = self.bin_info() {
1025 if prec < min_prec {
1026 break;
1027 }
1028 self.advance();
1029 let next_min = if right_assoc { prec } else { prec + 1 };
1030 let right = self.parse_binary(next_min)?;
1031 left = if let Some(lop) = logical {
1032 Expr::Logical(lop, Box::new(left), Box::new(right))
1033 } else {
1034 Expr::Binary(bin.unwrap(), Box::new(left), Box::new(right))
1035 };
1036 }
1037 Ok(left)
1038 }
1039
1040 fn bin_info(&self) -> Option<(u8, bool, Option<LogicalOp>, Option<BinOp>)> {
1042 let p = match self.tok() {
1043 Tok::Punct(p) => p.as_str(),
1044 Tok::Ident(s) if s == "in" => {
1047 if self.no_in {
1048 return None;
1049 }
1050 "in"
1051 }
1052 Tok::Ident(s) if s == "instanceof" => "instanceof",
1053 _ => return None,
1054 };
1055 let (prec, ra, log, bin) = match p {
1056 "??" => (1, false, Some(LogicalOp::Nullish), None),
1057 "||" => (2, false, Some(LogicalOp::Or), None),
1058 "&&" => (3, false, Some(LogicalOp::And), None),
1059 "|" => (4, false, None, Some(BinOp::BitOr)),
1060 "^" => (5, false, None, Some(BinOp::BitXor)),
1061 "&" => (6, false, None, Some(BinOp::BitAnd)),
1062 "==" => (7, false, None, Some(BinOp::EqEq)),
1063 "!=" => (7, false, None, Some(BinOp::NeEq)),
1064 "===" => (7, false, None, Some(BinOp::EqEqEq)),
1065 "!==" => (7, false, None, Some(BinOp::NeEqEq)),
1066 "<" => (8, false, None, Some(BinOp::Lt)),
1067 "<=" => (8, false, None, Some(BinOp::Le)),
1068 ">" => (8, false, None, Some(BinOp::Gt)),
1069 ">=" => (8, false, None, Some(BinOp::Ge)),
1070 "in" => (8, false, None, Some(BinOp::In)),
1071 "instanceof" => (8, false, None, Some(BinOp::InstanceOf)),
1072 "<<" => (9, false, None, Some(BinOp::Shl)),
1073 ">>" => (9, false, None, Some(BinOp::Shr)),
1074 ">>>" => (9, false, None, Some(BinOp::UShr)),
1075 "+" => (10, false, None, Some(BinOp::Add)),
1076 "-" => (10, false, None, Some(BinOp::Sub)),
1077 "*" => (11, false, None, Some(BinOp::Mul)),
1078 "/" => (11, false, None, Some(BinOp::Div)),
1079 "%" => (11, false, None, Some(BinOp::Mod)),
1080 "**" => (12, true, None, Some(BinOp::Pow)),
1081 _ => return None,
1082 };
1083 Some((prec, ra, log, bin))
1084 }
1085
1086 fn reject_unary_before_pow(&mut self) -> Result<(), String> {
1091 if self.is_punct("**") {
1092 return Err(format!(
1093 "SyntaxError: Unary operator used immediately before exponentiation \
1094 expression. Parenthesis must be used to disambiguate operator \
1095 precedence (line {})",
1096 self.line()
1097 ));
1098 }
1099 Ok(())
1100 }
1101
1102 fn parse_unary(&mut self) -> Result<Expr, String> {
1103 let op = match self.tok() {
1104 Tok::Punct(p) if p == "!" => Some(UnOp::Not),
1105 Tok::Punct(p) if p == "~" => Some(UnOp::BitNot),
1106 Tok::Punct(p) if p == "+" => Some(UnOp::Pos),
1107 Tok::Punct(p) if p == "-" => Some(UnOp::Neg),
1108 Tok::Ident(s) if s == "typeof" => Some(UnOp::TypeOf),
1109 Tok::Ident(s) if s == "void" => Some(UnOp::Void),
1110 Tok::Ident(s) if s == "delete" => Some(UnOp::Delete),
1111 _ => None,
1112 };
1113 if let Some(op) = op {
1114 self.advance();
1115 let e = self.parse_unary()?;
1116 self.reject_unary_before_pow()?;
1120 return Ok(Expr::Unary(op, Box::new(e)));
1121 }
1122 if self.is_punct("++") || self.is_punct("--") {
1124 let op = if self.is_punct("++") {
1125 UpdateOp::Inc
1126 } else {
1127 UpdateOp::Dec
1128 };
1129 self.advance();
1130 let e = self.parse_unary()?;
1131 return Ok(Expr::Update {
1132 op,
1133 prefix: true,
1134 target: Box::new(e),
1135 });
1136 }
1137 self.parse_postfix()
1138 }
1139
1140 fn parse_postfix(&mut self) -> Result<Expr, String> {
1141 let mut e = self.parse_call_member()?;
1142 if (self.is_punct("++") || self.is_punct("--")) && !self.newline_before() {
1144 let op = if self.is_punct("++") {
1145 UpdateOp::Inc
1146 } else {
1147 UpdateOp::Dec
1148 };
1149 self.advance();
1150 e = Expr::Update {
1151 op,
1152 prefix: false,
1153 target: Box::new(e),
1154 };
1155 }
1156 Ok(e)
1157 }
1158
1159 fn parse_call_member(&mut self) -> Result<Expr, String> {
1160 let mut e = if self.eat_kw("new") {
1161 if self.is_punct(".") {
1163 self.advance();
1164 let prop = self.ident_name()?;
1165 if prop != "target" {
1166 return Err(format!(
1167 "SyntaxError: expected 'target' (line {})",
1168 self.line()
1169 ));
1170 }
1171 Expr::NewTarget
1172 } else {
1173 let callee = self.parse_call_member_no_call()?;
1174 if Self::has_optional_link(&callee) || self.is_punct("?.") {
1180 return Err(
1181 "SyntaxError: Invalid optional chain from new expression".to_string()
1182 );
1183 }
1184 let args = if self.is_punct("(") {
1185 self.parse_args()?
1186 } else {
1187 Vec::new()
1188 };
1189 Expr::New {
1190 callee: Box::new(callee),
1191 args,
1192 }
1193 }
1194 } else {
1195 self.parse_primary()?
1196 };
1197 loop {
1198 if self.eat_punct(".") {
1199 let property = self.ident_name()?;
1200 self.check_private_in_scope(&property)?;
1201 e = Expr::Member {
1202 object: Box::new(e),
1203 property,
1204 optional: false,
1205 };
1206 } else if self.eat_punct("?.") {
1207 if self.is_punct("(") {
1208 let args = self.parse_args()?;
1209 e = Expr::Call {
1210 func: Box::new(e),
1211 args,
1212 optional: true,
1213 };
1214 } else if self.is_punct("[") {
1215 self.advance();
1216 let index = self.allow_in(|p| p.parse_expr())?;
1217 self.expect_punct("]")?;
1218 e = Expr::Index {
1219 object: Box::new(e),
1220 index: Box::new(index),
1221 optional: true,
1222 };
1223 } else {
1224 let property = self.ident_name()?;
1225 e = Expr::Member {
1226 object: Box::new(e),
1227 property,
1228 optional: true,
1229 };
1230 }
1231 } else if self.is_punct("[") {
1232 self.advance();
1233 let index = self.allow_in(|p| p.parse_expr())?;
1234 self.expect_punct("]")?;
1235 e = Expr::Index {
1236 object: Box::new(e),
1237 index: Box::new(index),
1238 optional: false,
1239 };
1240 } else if self.is_punct("(") {
1241 let args = self.parse_args()?;
1242 e = Expr::Call {
1243 func: Box::new(e),
1244 args,
1245 optional: false,
1246 };
1247 } else if matches!(self.tok(), Tok::Template { .. }) {
1248 if Self::has_optional_link(&e) {
1254 return Err(
1255 "SyntaxError: Invalid tagged template on optional chain".to_string()
1256 );
1257 }
1258 e = self.parse_tagged_template(e)?;
1259 } else {
1260 break;
1261 }
1262 }
1263 Ok(e)
1264 }
1265
1266 fn parse_tagged_template(&mut self, tag: Expr) -> Result<Expr, String> {
1269 let (quasis, raws, exprs_src, expr_at) = match self.tok().clone() {
1270 Tok::Template {
1271 quasis,
1272 raws,
1273 exprs,
1274 expr_at,
1275 } => (quasis, raws, exprs, expr_at),
1276 _ => unreachable!(),
1277 };
1278 self.advance();
1279 let mut exprs = Vec::new();
1280 for (src, at) in exprs_src.iter().zip(expr_at) {
1281 exprs.push(self.parse_field(src, at)?);
1282 }
1283 Ok(Expr::TaggedTemplate {
1284 tag: Box::new(tag),
1285 quasis,
1286 raws,
1287 exprs,
1288 })
1289 }
1290
1291 fn parse_call_member_no_call(&mut self) -> Result<Expr, String> {
1293 let mut e = self.parse_primary()?;
1294 loop {
1295 if self.eat_punct(".") {
1296 let property = self.ident_name()?;
1297 self.check_private_in_scope(&property)?;
1298 e = Expr::Member {
1299 object: Box::new(e),
1300 property,
1301 optional: false,
1302 };
1303 } else if self.is_punct("[") {
1304 self.advance();
1305 let index = self.allow_in(|p| p.parse_expr())?;
1306 self.expect_punct("]")?;
1307 e = Expr::Index {
1308 object: Box::new(e),
1309 index: Box::new(index),
1310 optional: false,
1311 };
1312 } else {
1313 break;
1314 }
1315 }
1316 Ok(e)
1317 }
1318
1319 fn parse_args(&mut self) -> Result<Vec<Expr>, String> {
1320 self.expect_punct("(")?;
1321 let args = self.allow_in(|p| {
1324 let mut args = Vec::new();
1325 while !p.is_punct(")") {
1326 if p.eat_punct("...") {
1327 let e = p.parse_assign()?;
1328 args.push(Expr::Spread(Box::new(e)));
1329 } else {
1330 args.push(p.parse_assign()?);
1331 }
1332 if !p.eat_punct(",") {
1333 break;
1334 }
1335 }
1336 Ok(args)
1337 })?;
1338 self.expect_punct(")")?;
1339 Ok(args)
1340 }
1341
1342 fn parse_primary(&mut self) -> Result<Expr, String> {
1343 match self.tok().clone() {
1344 Tok::Num(n) => {
1345 self.advance();
1346 Ok(Expr::Number(n))
1347 }
1348 Tok::BigInt(s) => {
1349 self.advance();
1350 Ok(Expr::BigInt(s))
1351 }
1352 Tok::Regex(pat, flags) => {
1353 self.advance();
1354 Ok(Expr::Regex(pat, flags))
1355 }
1356 Tok::Str(s) => {
1357 self.advance();
1358 Ok(Expr::Str(s))
1359 }
1360 Tok::Template {
1361 quasis,
1362 raws: _,
1363 exprs,
1364 expr_at,
1365 } => {
1366 self.advance();
1367 let mut parsed = Vec::new();
1368 for (src, at) in exprs.iter().zip(expr_at) {
1369 parsed.push(self.parse_field(src, at)?);
1370 }
1371 Ok(Expr::Template {
1372 quasis,
1373 exprs: parsed,
1374 })
1375 }
1376 Tok::Punct(p) if p == "(" => {
1377 self.advance();
1378 let e = self.parse_expr()?;
1379 self.expect_punct(")")?;
1380 if Self::has_optional_link(&e) {
1396 return Ok(Expr::Sequence(vec![e]));
1397 }
1398 Ok(e)
1399 }
1400 Tok::Punct(p) if p == "[" => self.parse_array_literal(),
1401 Tok::Punct(p) if p == "{" => self.parse_object_literal(),
1402 Tok::Ident(s) => {
1403 match s.as_str() {
1404 "true" => {
1405 self.advance();
1406 Ok(Expr::True)
1407 }
1408 "false" => {
1409 self.advance();
1410 Ok(Expr::False)
1411 }
1412 "null" => {
1413 self.advance();
1414 Ok(Expr::Null)
1415 }
1416 "this" => {
1417 self.advance();
1418 Ok(Expr::This)
1419 }
1420 "super" => {
1421 self.advance();
1422 Ok(Expr::Super)
1423 }
1424 "class" => Ok(Expr::Class(Box::new(self.parse_class(false)?))),
1425 "function" => self.parse_function_expr(false),
1426 "async" if self.peek_kw(1, "function") && !self.peek_newline(1) => {
1427 self.advance(); self.parse_function_expr(true)
1429 }
1430 "yield" if self.in_generator => {
1431 self.advance();
1432 let delegate = self.eat_punct("*");
1433 let arg = if delegate
1436 || !(self.is_punct(")")
1437 || self.is_punct("]")
1438 || self.is_punct("}")
1439 || self.is_punct(",")
1440 || self.is_punct(";")
1441 || self.is_punct(":")
1442 || self.newline_before()
1443 || self.at_eof())
1444 {
1445 Some(Box::new(self.parse_assign()?))
1446 } else {
1447 None
1448 };
1449 Ok(Expr::Yield { arg, delegate })
1450 }
1451 "await" if self.in_async => {
1452 self.advance();
1453 let e = self.parse_unary()?;
1454 self.reject_unary_before_pow()?;
1457 Ok(Expr::Await(Box::new(e)))
1458 }
1459 _ if is_keyword(&s) => Err(format!(
1460 "SyntaxError: unexpected keyword '{s}' (line {})",
1461 self.line()
1462 )),
1463 _ => {
1464 self.advance();
1465 Ok(Expr::Ident(s))
1466 }
1467 }
1468 }
1469 other => Err(format!(
1470 "SyntaxError: unexpected token {other:?} (line {})",
1471 self.line()
1472 )),
1473 }
1474 }
1475
1476 fn parse_array_literal(&mut self) -> Result<Expr, String> {
1477 self.expect_punct("[")?;
1478 let mut items = Vec::new();
1479 while !self.is_punct("]") {
1480 if self.is_punct(",") {
1481 items.push(Expr::Hole);
1483 self.advance();
1484 continue;
1485 }
1486 if self.eat_punct("...") {
1487 let e = self.parse_assign()?;
1488 items.push(Expr::Spread(Box::new(e)));
1489 } else {
1490 items.push(self.parse_assign()?);
1491 }
1492 if !self.eat_punct(",") {
1493 break;
1494 }
1495 }
1496 self.expect_punct("]")?;
1497 Ok(Expr::Array(items))
1498 }
1499
1500 fn parse_object_literal(&mut self) -> Result<Expr, String> {
1501 self.expect_punct("{")?;
1502 let mut props = Vec::new();
1503 while !self.is_punct("}") {
1504 if self.eat_punct("...") {
1505 let e = self.parse_assign()?;
1506 props.push(Prop::Spread(e));
1507 if !self.eat_punct(",") {
1508 break;
1509 }
1510 continue;
1511 }
1512 if (self.is_kw("get") || self.is_kw("set"))
1515 && !self.peek_is_member_punct(1)
1516 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1517 {
1518 let is_getter = self.is_kw("get");
1519 let start = self.start_at(self.pos);
1520 self.advance();
1521 let (key, computed) = self.parse_property_key()?;
1522 let params = self.parse_params()?;
1523 self.expect_punct("{")?;
1524 let body = self.parse_block_body()?;
1525 let func = Expr::Function {
1526 params,
1527 body: FnBody::Block(body),
1528 is_arrow: false,
1529 name: None,
1530 is_generator: false,
1531 is_async: false,
1532 is_method: true,
1533 span: self.span_from(start),
1534 };
1535 props.push(Prop::Accessor {
1536 key,
1537 computed,
1538 is_getter,
1539 func,
1540 });
1541 if !self.eat_punct(",") {
1542 break;
1543 }
1544 continue;
1545 }
1546 let mut m_async = false;
1548 let mut m_gen = false;
1549 let start = self.start_at(self.pos);
1550 if self.is_kw("async")
1551 && !self.peek_is_member_punct(1)
1552 && !self.peek_newline(1)
1553 && !matches!(self.toks.get(self.pos + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == ":" || p == ",")
1554 {
1555 self.advance();
1556 m_async = true;
1557 }
1558 if self.is_punct("*") {
1559 self.advance();
1560 m_gen = true;
1561 }
1562 let (key, computed) = self.parse_property_key()?;
1563 if self.is_punct("(") {
1565 let params = self.parse_params()?;
1566 self.expect_punct("{")?;
1567 let body = self.parse_fn_body_block(m_gen, m_async)?;
1568 let f = Expr::Function {
1569 params,
1570 body: FnBody::Block(body),
1571 is_arrow: false,
1572 name: None,
1573 is_generator: m_gen,
1574 is_async: m_async,
1575 is_method: true,
1576 span: self.span_from(start),
1577 };
1578 props.push(Prop::KeyValue {
1579 key,
1580 value: f,
1581 computed,
1582 });
1583 } else if self.eat_punct(":") {
1584 let value = self.parse_assign()?;
1585 props.push(Prop::KeyValue {
1586 key,
1587 value,
1588 computed,
1589 });
1590 } else {
1591 let name = match &key {
1594 Expr::Str(s) => s.clone(),
1595 _ => return Err(format!("SyntaxError: bad shorthand (line {})", self.line())),
1596 };
1597 let value = if self.eat_punct("=") {
1598 let d = self.parse_assign()?;
1600 Expr::Assign {
1601 target: Box::new(Expr::Ident(name.clone())),
1602 op: None,
1603 value: Box::new(d),
1604 }
1605 } else {
1606 Expr::Ident(name)
1607 };
1608 props.push(Prop::KeyValue {
1609 key,
1610 value,
1611 computed,
1612 });
1613 }
1614 if !self.eat_punct(",") {
1615 break;
1616 }
1617 }
1618 self.expect_punct("}")?;
1619 Ok(Expr::Object(props))
1620 }
1621
1622 fn parse_params(&mut self) -> Result<Vec<Param>, String> {
1624 self.expect_punct("(")?;
1625 let mut params = Vec::new();
1626 while !self.is_punct(")") {
1627 let rest = self.eat_punct("...");
1628 let pattern = self.parse_binding_target()?;
1629 let default = if !rest && self.eat_punct("=") {
1630 Some(self.parse_assign()?)
1631 } else {
1632 None
1633 };
1634 params.push(Param {
1635 pattern,
1636 default,
1637 rest,
1638 });
1639 if !self.eat_punct(",") {
1640 break;
1641 }
1642 }
1643 self.expect_punct(")")?;
1644 Ok(params)
1645 }
1646
1647 fn try_parse_arrow(&mut self) -> Result<Option<Expr>, String> {
1650 let start = self.start_at(self.pos);
1651 let mut is_async = false;
1654 let mut base = self.pos;
1655 if self.is_kw("async") && !self.peek_newline(1) {
1656 let next = self.toks.get(self.pos + 1).map(|t| &t.tok);
1657 let looks_async_arrow = matches!(next, Some(Tok::Punct(p)) if p == "(")
1658 || matches!(next, Some(Tok::Ident(n)) if !is_keyword(n) && self.peek_is_arrow_after(2));
1659 if looks_async_arrow {
1660 is_async = true;
1661 base += 1;
1662 }
1663 }
1664 if let Some(Tok::Ident(name)) = self.toks.get(base).map(|t| &t.tok) {
1666 if !is_keyword(name)
1667 && matches!(self.toks.get(base + 1).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1668 {
1669 let name = name.clone();
1670 if is_async {
1671 self.advance(); }
1673 self.advance(); self.advance(); let body = self.parse_arrow_body(is_async)?;
1676 return Ok(Some(Expr::Function {
1677 params: vec![Param {
1678 pattern: Expr::Ident(name),
1679 default: None,
1680 rest: false,
1681 }],
1682 body,
1683 is_arrow: true,
1684 name: None,
1685 is_generator: false,
1686 is_async,
1687 is_method: false,
1688 span: self.span_from(start),
1689 }));
1690 }
1691 }
1692 if matches!(self.toks.get(base).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "(") {
1694 if let Some(close) = self.matching_paren(base) {
1695 let after = close + 1;
1696 if matches!(self.toks.get(after).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1697 {
1698 if is_async {
1699 self.advance(); }
1701 let params = self.parse_params()?;
1702 self.expect_punct("=>")?;
1703 let body = self.parse_arrow_body(is_async)?;
1704 return Ok(Some(Expr::Function {
1705 params,
1706 body,
1707 is_arrow: true,
1708 name: None,
1709 is_generator: false,
1710 is_async,
1711 is_method: false,
1712 span: self.span_from(start),
1713 }));
1714 }
1715 }
1716 }
1717 Ok(None)
1718 }
1719
1720 fn parse_arrow_body(&mut self, is_async: bool) -> Result<FnBody, String> {
1721 let (pg, pa) = (self.in_generator, self.in_async);
1722 self.in_generator = false;
1723 self.in_async = is_async;
1724 let r = if self.is_punct("{") {
1725 self.advance();
1726 self.parse_block_body().map(FnBody::Block)
1727 } else {
1728 self.parse_assign().map(|e| FnBody::Expr(Box::new(e)))
1729 };
1730 self.in_generator = pg;
1731 self.in_async = pa;
1732 r
1733 }
1734
1735 fn peek_is_arrow_after(&self, n: usize) -> bool {
1737 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1738 }
1739
1740 fn matching_paren(&self, open: usize) -> Option<usize> {
1742 let mut depth = 0i32;
1743 let mut i = open;
1744 while i < self.toks.len() {
1745 match &self.toks[i].tok {
1746 Tok::Punct(p) if p == "(" || p == "[" || p == "{" => depth += 1,
1747 Tok::Punct(p) if p == ")" || p == "]" || p == "}" => {
1748 depth -= 1;
1749 if depth == 0 {
1750 return Some(i);
1751 }
1752 }
1753 Tok::Eof => return None,
1754 _ => {}
1755 }
1756 i += 1;
1757 }
1758 None
1759 }
1760}
1761
1762fn field_parser(src: &str, base: Option<u32>) -> Result<Parser, String> {
1766 let mut toks = lex(src)?;
1767 for t in &mut toks {
1768 t.start += base.unwrap_or(0);
1769 t.end += base.unwrap_or(0);
1770 if let Tok::Template { expr_at, .. } = &mut t.tok {
1771 for at in expr_at {
1772 *at += base.unwrap_or(0);
1773 }
1774 }
1775 }
1776 Ok(Parser {
1777 toks,
1778 pos: 0,
1779 in_generator: false,
1780 in_async: false,
1781 no_in: false,
1782 class_scopes: Vec::new(),
1783 spans: base.is_some(),
1784 })
1785}