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