1use crate::ast::*;
11use crate::lexer::{lex, Tok, Token};
12
13const KEYWORDS: &[&str] = &[
14 "var", "let", "const", "function", "return", "if", "else", "while", "do", "for", "of", "in",
15 "switch", "case", "default", "break", "continue", "true", "false", "null", "this", "new",
16 "typeof", "void", "delete", "instanceof", "throw", "try", "catch", "finally",
17];
18
19fn is_keyword(s: &str) -> bool {
20 KEYWORDS.contains(&s)
21}
22
23struct Parser {
24 toks: Vec<Token>,
25 pos: usize,
26}
27
28pub fn parse(src: &str) -> Result<Vec<Stmt>, String> {
30 let toks = lex(src)?;
31 let mut p = Parser { toks, pos: 0 };
32 let mut out = Vec::new();
33 while !p.at_eof() {
34 out.push(p.parse_stmt()?);
35 }
36 Ok(out)
37}
38
39impl Parser {
40 fn cur(&self) -> &Token {
42 &self.toks[self.pos]
43 }
44 fn tok(&self) -> &Tok {
45 &self.toks[self.pos].tok
46 }
47 fn line(&self) -> u32 {
48 self.toks[self.pos].line
49 }
50 fn at_eof(&self) -> bool {
51 matches!(self.tok(), Tok::Eof)
52 }
53 fn newline_before(&self) -> bool {
54 self.cur().newline_before
55 }
56 fn advance(&mut self) -> Tok {
57 let t = self.toks[self.pos].tok.clone();
58 if self.pos + 1 < self.toks.len() {
59 self.pos += 1;
60 }
61 t
62 }
63
64 fn is_punct(&self, s: &str) -> bool {
66 matches!(self.tok(), Tok::Punct(p) if p == s)
67 }
68 fn is_kw(&self, s: &str) -> bool {
70 matches!(self.tok(), Tok::Ident(i) if i == s)
71 }
72 fn eat_punct(&mut self, s: &str) -> bool {
74 if self.is_punct(s) {
75 self.advance();
76 true
77 } else {
78 false
79 }
80 }
81 fn eat_kw(&mut self, s: &str) -> bool {
82 if self.is_kw(s) {
83 self.advance();
84 true
85 } else {
86 false
87 }
88 }
89 fn expect_punct(&mut self, s: &str) -> Result<(), String> {
90 if self.eat_punct(s) {
91 Ok(())
92 } else {
93 Err(format!(
94 "SyntaxError: expected '{s}' but found {:?} (line {})",
95 self.tok(),
96 self.line()
97 ))
98 }
99 }
100
101 fn ident_name(&mut self) -> Result<String, String> {
104 match self.tok().clone() {
105 Tok::Ident(s) => {
106 self.advance();
107 Ok(s)
108 }
109 other => Err(format!(
110 "SyntaxError: expected identifier but found {other:?} (line {})",
111 self.line()
112 )),
113 }
114 }
115
116 fn semicolon(&mut self) -> Result<(), String> {
118 if self.eat_punct(";") {
119 return Ok(());
120 }
121 if self.newline_before() || self.is_punct("}") || self.at_eof() {
122 return Ok(());
123 }
124 Err(format!(
125 "SyntaxError: expected ';' but found {:?} (line {})",
126 self.tok(),
127 self.line()
128 ))
129 }
130
131 fn parse_stmt(&mut self) -> Result<Stmt, String> {
133 let line = self.line();
134 let kind = match self.tok().clone() {
135 Tok::Punct(p) if p == "{" => {
136 self.advance();
137 StmtKind::Block(self.parse_block_body()?)
138 }
139 Tok::Punct(p) if p == ";" => {
140 self.advance();
141 StmtKind::Empty
142 }
143 Tok::Ident(kw) if kw == "var" || kw == "let" || kw == "const" => {
144 let k = self.parse_decl_kind();
145 let decls = self.parse_declarators()?;
146 self.semicolon()?;
147 StmtKind::Decl { kind: k, decls }
148 }
149 Tok::Ident(kw) if kw == "function" => {
150 self.advance();
151 let name = self.ident_name()?;
152 let params = self.parse_params()?;
153 self.expect_punct("{")?;
154 let body = self.parse_block_body()?;
155 StmtKind::FuncDecl { name, params, body }
156 }
157 Tok::Ident(kw) if kw == "if" => self.parse_if()?,
158 Tok::Ident(kw) if kw == "while" => self.parse_while()?,
159 Tok::Ident(kw) if kw == "do" => self.parse_do_while()?,
160 Tok::Ident(kw) if kw == "for" => self.parse_for()?,
161 Tok::Ident(kw) if kw == "switch" => self.parse_switch()?,
162 Tok::Ident(kw) if kw == "return" => {
163 self.advance();
164 let arg = if self.is_punct(";") || self.is_punct("}") || self.newline_before() || self.at_eof() {
165 None
166 } else {
167 Some(self.parse_expr()?)
168 };
169 self.semicolon()?;
170 StmtKind::Return(arg)
171 }
172 Tok::Ident(kw) if kw == "break" => {
173 self.advance();
174 let label = self.opt_label();
175 self.semicolon()?;
176 StmtKind::Break(label)
177 }
178 Tok::Ident(kw) if kw == "continue" => {
179 self.advance();
180 let label = self.opt_label();
181 self.semicolon()?;
182 StmtKind::Continue(label)
183 }
184 Tok::Ident(kw) if kw == "throw" => {
185 self.advance();
186 let e = self.parse_expr()?;
187 self.semicolon()?;
188 StmtKind::Throw(e)
189 }
190 Tok::Ident(kw) if kw == "try" => self.parse_try()?,
191 _ => {
192 let e = self.parse_expr()?;
193 self.semicolon()?;
194 StmtKind::Expr(e)
195 }
196 };
197 Ok(Stmt::new(kind, line))
198 }
199
200 fn opt_label(&mut self) -> Option<String> {
202 if self.newline_before() {
203 return None;
204 }
205 if let Tok::Ident(s) = self.tok() {
206 if !is_keyword(s) {
207 let s = s.clone();
208 self.advance();
209 return Some(s);
210 }
211 }
212 None
213 }
214
215 fn parse_block_body(&mut self) -> Result<Vec<Stmt>, String> {
217 let mut out = Vec::new();
218 while !self.is_punct("}") && !self.at_eof() {
219 out.push(self.parse_stmt()?);
220 }
221 self.expect_punct("}")?;
222 Ok(out)
223 }
224
225 fn parse_decl_kind(&mut self) -> DeclKind {
226 let k = match self.tok() {
227 Tok::Ident(s) if s == "let" => DeclKind::Let,
228 Tok::Ident(s) if s == "const" => DeclKind::Const,
229 _ => DeclKind::Var,
230 };
231 self.advance();
232 k
233 }
234
235 fn parse_declarators(&mut self) -> Result<Vec<Declarator>, String> {
236 let mut decls = Vec::new();
237 loop {
238 let target = self.parse_binding_target()?;
239 let init = if self.eat_punct("=") {
240 Some(self.parse_assign()?)
241 } else {
242 None
243 };
244 decls.push(Declarator { target, init });
245 if !self.eat_punct(",") {
246 break;
247 }
248 }
249 Ok(decls)
250 }
251
252 fn parse_binding_target(&mut self) -> Result<Expr, String> {
254 if self.is_punct("[") {
255 self.parse_array_literal()
256 } else if self.is_punct("{") {
257 self.parse_object_literal()
258 } else {
259 Ok(Expr::Ident(self.ident_name()?))
260 }
261 }
262
263 fn parse_if(&mut self) -> Result<StmtKind, String> {
264 self.advance(); self.expect_punct("(")?;
266 let test = self.parse_expr()?;
267 self.expect_punct(")")?;
268 let cons = Box::new(self.parse_stmt()?);
269 let alt = if self.eat_kw("else") {
270 Some(Box::new(self.parse_stmt()?))
271 } else {
272 None
273 };
274 Ok(StmtKind::If { test, cons, alt })
275 }
276
277 fn parse_while(&mut self) -> Result<StmtKind, String> {
278 self.advance();
279 self.expect_punct("(")?;
280 let test = self.parse_expr()?;
281 self.expect_punct(")")?;
282 let body = Box::new(self.parse_stmt()?);
283 Ok(StmtKind::While { test, body })
284 }
285
286 fn parse_do_while(&mut self) -> Result<StmtKind, String> {
287 self.advance();
288 let body = Box::new(self.parse_stmt()?);
289 if !self.eat_kw("while") {
290 return Err(format!("SyntaxError: expected 'while' (line {})", self.line()));
291 }
292 self.expect_punct("(")?;
293 let test = self.parse_expr()?;
294 self.expect_punct(")")?;
295 self.semicolon()?;
296 Ok(StmtKind::DoWhile { body, test })
297 }
298
299 fn parse_for(&mut self) -> Result<StmtKind, String> {
300 self.advance();
301 self.expect_punct("(")?;
302 let decl_kind = match self.tok() {
304 Tok::Ident(s) if s == "var" || s == "let" || s == "const" => Some(self.parse_decl_kind()),
305 _ => None,
306 };
307 if decl_kind.is_none() && self.is_punct(";") {
309 return self.parse_c_for(None);
310 }
311 let first_target = if decl_kind.is_some() {
313 self.parse_binding_target()?
314 } else {
315 self.parse_expr_no_in()?
316 };
317 if self.eat_kw("of") {
318 let iter = self.parse_assign()?;
319 self.expect_punct(")")?;
320 let body = Box::new(self.parse_stmt()?);
321 return Ok(StmtKind::ForOf {
322 decl_kind,
323 target: first_target,
324 iter,
325 body,
326 });
327 }
328 if self.eat_kw("in") {
329 let object = self.parse_assign()?;
330 self.expect_punct(")")?;
331 let body = Box::new(self.parse_stmt()?);
332 return Ok(StmtKind::ForIn {
333 decl_kind,
334 target: first_target,
335 object,
336 body,
337 });
338 }
339 let init_stmt = if let Some(k) = decl_kind {
341 let init = if self.eat_punct("=") {
342 Some(self.parse_assign()?)
343 } else {
344 None
345 };
346 let mut decls = vec![Declarator { target: first_target, init }];
347 while self.eat_punct(",") {
348 let target = self.parse_binding_target()?;
349 let init = if self.eat_punct("=") {
350 Some(self.parse_assign()?)
351 } else {
352 None
353 };
354 decls.push(Declarator { target, init });
355 }
356 StmtKind::Decl { kind: k, decls }
357 } else {
358 StmtKind::Expr(first_target)
359 };
360 self.parse_c_for(Some(Stmt::from(init_stmt)))
361 }
362
363 fn parse_c_for(&mut self, init: Option<Stmt>) -> Result<StmtKind, String> {
364 self.expect_punct(";")?;
365 let test = if self.is_punct(";") {
366 None
367 } else {
368 Some(self.parse_expr()?)
369 };
370 self.expect_punct(";")?;
371 let update = if self.is_punct(")") {
372 None
373 } else {
374 Some(self.parse_expr()?)
375 };
376 self.expect_punct(")")?;
377 let body = Box::new(self.parse_stmt()?);
378 Ok(StmtKind::For {
379 init: init.map(Box::new),
380 test,
381 update,
382 body,
383 })
384 }
385
386 fn parse_switch(&mut self) -> Result<StmtKind, String> {
387 self.advance();
388 self.expect_punct("(")?;
389 let disc = self.parse_expr()?;
390 self.expect_punct(")")?;
391 self.expect_punct("{")?;
392 let mut cases = Vec::new();
393 while !self.is_punct("}") && !self.at_eof() {
394 let test = if self.eat_kw("case") {
395 let e = self.parse_expr()?;
396 Some(e)
397 } else if self.eat_kw("default") {
398 None
399 } else {
400 return Err(format!(
401 "SyntaxError: expected 'case' or 'default' (line {})",
402 self.line()
403 ));
404 };
405 self.expect_punct(":")?;
406 let mut body = Vec::new();
407 while !self.is_punct("}") && !self.is_kw("case") && !self.is_kw("default") && !self.at_eof() {
408 body.push(self.parse_stmt()?);
409 }
410 cases.push(SwitchCase { test, body });
411 }
412 self.expect_punct("}")?;
413 Ok(StmtKind::Switch { disc, cases })
414 }
415
416 fn parse_try(&mut self) -> Result<StmtKind, String> {
417 self.advance();
418 self.expect_punct("{")?;
419 let block = self.parse_block_body()?;
420 let handler = if self.eat_kw("catch") {
421 let param = if self.eat_punct("(") {
422 let p = self.parse_binding_target()?;
423 self.expect_punct(")")?;
424 Some(p)
425 } else {
426 None
427 };
428 self.expect_punct("{")?;
429 let body = self.parse_block_body()?;
430 Some((param, body))
431 } else {
432 None
433 };
434 let finalizer = if self.eat_kw("finally") {
435 self.expect_punct("{")?;
436 Some(self.parse_block_body()?)
437 } else {
438 None
439 };
440 Ok(StmtKind::Try {
441 block,
442 handler,
443 finalizer,
444 })
445 }
446
447 fn parse_expr(&mut self) -> Result<Expr, String> {
450 let first = self.parse_assign()?;
451 if self.is_punct(",") {
452 let mut items = vec![first];
453 while self.eat_punct(",") {
454 items.push(self.parse_assign()?);
455 }
456 Ok(Expr::Sequence(items))
457 } else {
458 Ok(first)
459 }
460 }
461
462 fn parse_expr_no_in(&mut self) -> Result<Expr, String> {
464 self.parse_assign()
467 }
468
469 fn parse_assign(&mut self) -> Result<Expr, String> {
470 if let Some(arrow) = self.try_parse_arrow()? {
472 return Ok(arrow);
473 }
474 let left = self.parse_conditional()?;
475 let op = match self.tok() {
477 Tok::Punct(p) => p.clone(),
478 _ => return Ok(left),
479 };
480 let compound = match op.as_str() {
481 "=" => None,
482 "+=" => Some(BinOp::Add),
483 "-=" => Some(BinOp::Sub),
484 "*=" => Some(BinOp::Mul),
485 "/=" => Some(BinOp::Div),
486 "%=" => Some(BinOp::Mod),
487 "**=" => Some(BinOp::Pow),
488 "&=" => Some(BinOp::BitAnd),
489 "|=" => Some(BinOp::BitOr),
490 "^=" => Some(BinOp::BitXor),
491 "<<=" => Some(BinOp::Shl),
492 ">>=" => Some(BinOp::Shr),
493 ">>>=" => Some(BinOp::UShr),
494 "&&=" | "||=" | "??=" => {
495 self.advance();
497 let value = self.parse_assign()?;
498 let lop = match op.as_str() {
499 "&&=" => LogicalOp::And,
500 "||=" => LogicalOp::Or,
501 _ => LogicalOp::Nullish,
502 };
503 return Ok(Expr::Assign {
504 target: Box::new(left.clone()),
505 value: Box::new(Expr::Logical(lop, Box::new(left), Box::new(value))),
506 });
507 }
508 _ => return Ok(left),
509 };
510 self.advance();
511 let value = self.parse_assign()?;
512 let value = match compound {
513 None => value,
514 Some(b) => Expr::Binary(b, Box::new(left.clone()), Box::new(value)),
515 };
516 Ok(Expr::Assign {
517 target: Box::new(left),
518 value: Box::new(value),
519 })
520 }
521
522 fn parse_conditional(&mut self) -> Result<Expr, String> {
523 let test = self.parse_binary(0)?;
524 if self.eat_punct("?") {
525 let cons = self.parse_assign()?;
526 self.expect_punct(":")?;
527 let alt = self.parse_assign()?;
528 Ok(Expr::Conditional {
529 test: Box::new(test),
530 cons: Box::new(cons),
531 alt: Box::new(alt),
532 })
533 } else {
534 Ok(test)
535 }
536 }
537
538 fn parse_binary(&mut self, min_prec: u8) -> Result<Expr, String> {
540 let mut left = self.parse_unary()?;
541 while let Some((prec, right_assoc, logical, bin)) = self.bin_info() {
542 if prec < min_prec {
543 break;
544 }
545 self.advance();
546 let next_min = if right_assoc { prec } else { prec + 1 };
547 let right = self.parse_binary(next_min)?;
548 left = if let Some(lop) = logical {
549 Expr::Logical(lop, Box::new(left), Box::new(right))
550 } else {
551 Expr::Binary(bin.unwrap(), Box::new(left), Box::new(right))
552 };
553 }
554 Ok(left)
555 }
556
557 fn bin_info(&self) -> Option<(u8, bool, Option<LogicalOp>, Option<BinOp>)> {
559 let p = match self.tok() {
560 Tok::Punct(p) => p.as_str(),
561 Tok::Ident(s) if s == "in" => "in",
562 Tok::Ident(s) if s == "instanceof" => "instanceof",
563 _ => return None,
564 };
565 let (prec, ra, log, bin) = match p {
566 "??" => (1, false, Some(LogicalOp::Nullish), None),
567 "||" => (2, false, Some(LogicalOp::Or), None),
568 "&&" => (3, false, Some(LogicalOp::And), None),
569 "|" => (4, false, None, Some(BinOp::BitOr)),
570 "^" => (5, false, None, Some(BinOp::BitXor)),
571 "&" => (6, false, None, Some(BinOp::BitAnd)),
572 "==" => (7, false, None, Some(BinOp::EqEq)),
573 "!=" => (7, false, None, Some(BinOp::NeEq)),
574 "===" => (7, false, None, Some(BinOp::EqEqEq)),
575 "!==" => (7, false, None, Some(BinOp::NeEqEq)),
576 "<" => (8, false, None, Some(BinOp::Lt)),
577 "<=" => (8, false, None, Some(BinOp::Le)),
578 ">" => (8, false, None, Some(BinOp::Gt)),
579 ">=" => (8, false, None, Some(BinOp::Ge)),
580 "in" => (8, false, None, Some(BinOp::In)),
581 "instanceof" => (8, false, None, Some(BinOp::InstanceOf)),
582 "<<" => (9, false, None, Some(BinOp::Shl)),
583 ">>" => (9, false, None, Some(BinOp::Shr)),
584 ">>>" => (9, false, None, Some(BinOp::UShr)),
585 "+" => (10, false, None, Some(BinOp::Add)),
586 "-" => (10, false, None, Some(BinOp::Sub)),
587 "*" => (11, false, None, Some(BinOp::Mul)),
588 "/" => (11, false, None, Some(BinOp::Div)),
589 "%" => (11, false, None, Some(BinOp::Mod)),
590 "**" => (12, true, None, Some(BinOp::Pow)),
591 _ => return None,
592 };
593 Some((prec, ra, log, bin))
594 }
595
596 fn parse_unary(&mut self) -> Result<Expr, String> {
597 let op = match self.tok() {
598 Tok::Punct(p) if p == "!" => Some(UnOp::Not),
599 Tok::Punct(p) if p == "~" => Some(UnOp::BitNot),
600 Tok::Punct(p) if p == "+" => Some(UnOp::Pos),
601 Tok::Punct(p) if p == "-" => Some(UnOp::Neg),
602 Tok::Ident(s) if s == "typeof" => Some(UnOp::TypeOf),
603 Tok::Ident(s) if s == "void" => Some(UnOp::Void),
604 Tok::Ident(s) if s == "delete" => Some(UnOp::Delete),
605 _ => None,
606 };
607 if let Some(op) = op {
608 self.advance();
609 let e = self.parse_unary()?;
610 return Ok(Expr::Unary(op, Box::new(e)));
611 }
612 if self.is_punct("++") || self.is_punct("--") {
614 let op = if self.is_punct("++") { UpdateOp::Inc } else { UpdateOp::Dec };
615 self.advance();
616 let e = self.parse_unary()?;
617 return Ok(Expr::Update {
618 op,
619 prefix: true,
620 target: Box::new(e),
621 });
622 }
623 self.parse_postfix()
624 }
625
626 fn parse_postfix(&mut self) -> Result<Expr, String> {
627 let mut e = self.parse_call_member()?;
628 if (self.is_punct("++") || self.is_punct("--")) && !self.newline_before() {
630 let op = if self.is_punct("++") { UpdateOp::Inc } else { UpdateOp::Dec };
631 self.advance();
632 e = Expr::Update {
633 op,
634 prefix: false,
635 target: Box::new(e),
636 };
637 }
638 Ok(e)
639 }
640
641 fn parse_call_member(&mut self) -> Result<Expr, String> {
642 let mut e = if self.eat_kw("new") {
643 let callee = self.parse_call_member_no_call()?;
644 let args = if self.is_punct("(") {
645 self.parse_args()?
646 } else {
647 Vec::new()
648 };
649 Expr::New {
650 callee: Box::new(callee),
651 args,
652 }
653 } else {
654 self.parse_primary()?
655 };
656 loop {
657 if self.eat_punct(".") {
658 let property = self.ident_name()?;
659 e = Expr::Member {
660 object: Box::new(e),
661 property,
662 optional: false,
663 };
664 } else if self.eat_punct("?.") {
665 if self.is_punct("(") {
666 let args = self.parse_args()?;
667 e = Expr::Call {
668 func: Box::new(e),
669 args,
670 optional: true,
671 };
672 } else if self.is_punct("[") {
673 self.advance();
674 let index = self.parse_expr()?;
675 self.expect_punct("]")?;
676 e = Expr::Index {
677 object: Box::new(e),
678 index: Box::new(index),
679 optional: true,
680 };
681 } else {
682 let property = self.ident_name()?;
683 e = Expr::Member {
684 object: Box::new(e),
685 property,
686 optional: true,
687 };
688 }
689 } else if self.is_punct("[") {
690 self.advance();
691 let index = self.parse_expr()?;
692 self.expect_punct("]")?;
693 e = Expr::Index {
694 object: Box::new(e),
695 index: Box::new(index),
696 optional: false,
697 };
698 } else if self.is_punct("(") {
699 let args = self.parse_args()?;
700 e = Expr::Call {
701 func: Box::new(e),
702 args,
703 optional: false,
704 };
705 } else {
706 break;
707 }
708 }
709 Ok(e)
710 }
711
712 fn parse_call_member_no_call(&mut self) -> Result<Expr, String> {
714 let mut e = self.parse_primary()?;
715 loop {
716 if self.eat_punct(".") {
717 let property = self.ident_name()?;
718 e = Expr::Member {
719 object: Box::new(e),
720 property,
721 optional: false,
722 };
723 } else if self.is_punct("[") {
724 self.advance();
725 let index = self.parse_expr()?;
726 self.expect_punct("]")?;
727 e = Expr::Index {
728 object: Box::new(e),
729 index: Box::new(index),
730 optional: false,
731 };
732 } else {
733 break;
734 }
735 }
736 Ok(e)
737 }
738
739 fn parse_args(&mut self) -> Result<Vec<Expr>, String> {
740 self.expect_punct("(")?;
741 let mut args = Vec::new();
742 while !self.is_punct(")") {
743 if self.eat_punct("...") {
744 let e = self.parse_assign()?;
745 args.push(Expr::Spread(Box::new(e)));
746 } else {
747 args.push(self.parse_assign()?);
748 }
749 if !self.eat_punct(",") {
750 break;
751 }
752 }
753 self.expect_punct(")")?;
754 Ok(args)
755 }
756
757 fn parse_primary(&mut self) -> Result<Expr, String> {
758 match self.tok().clone() {
759 Tok::Num(n) => {
760 self.advance();
761 Ok(Expr::Number(n))
762 }
763 Tok::Str(s) => {
764 self.advance();
765 Ok(Expr::Str(s))
766 }
767 Tok::Template { quasis, exprs } => {
768 self.advance();
769 let mut parsed = Vec::new();
770 for src in &exprs {
771 parsed.push(parse_expr_source(src)?);
772 }
773 Ok(Expr::Template {
774 quasis,
775 exprs: parsed,
776 })
777 }
778 Tok::Punct(p) if p == "(" => {
779 self.advance();
780 let e = self.parse_expr()?;
781 self.expect_punct(")")?;
782 Ok(e)
783 }
784 Tok::Punct(p) if p == "[" => self.parse_array_literal(),
785 Tok::Punct(p) if p == "{" => self.parse_object_literal(),
786 Tok::Ident(s) => {
787 match s.as_str() {
788 "true" => {
789 self.advance();
790 Ok(Expr::True)
791 }
792 "false" => {
793 self.advance();
794 Ok(Expr::False)
795 }
796 "null" => {
797 self.advance();
798 Ok(Expr::Null)
799 }
800 "this" => {
801 self.advance();
802 Ok(Expr::This)
803 }
804 "function" => {
805 self.advance();
806 let name = if let Tok::Ident(n) = self.tok() {
807 if !is_keyword(n) {
808 let n = n.clone();
809 self.advance();
810 Some(n)
811 } else {
812 None
813 }
814 } else {
815 None
816 };
817 let params = self.parse_params()?;
818 self.expect_punct("{")?;
819 let body = self.parse_block_body()?;
820 Ok(Expr::Function {
821 params,
822 body: FnBody::Block(body),
823 is_arrow: false,
824 name,
825 })
826 }
827 _ if is_keyword(&s) => Err(format!(
828 "SyntaxError: unexpected keyword '{s}' (line {})",
829 self.line()
830 )),
831 _ => {
832 self.advance();
833 Ok(Expr::Ident(s))
834 }
835 }
836 }
837 other => Err(format!(
838 "SyntaxError: unexpected token {other:?} (line {})",
839 self.line()
840 )),
841 }
842 }
843
844 fn parse_array_literal(&mut self) -> Result<Expr, String> {
845 self.expect_punct("[")?;
846 let mut items = Vec::new();
847 while !self.is_punct("]") {
848 if self.is_punct(",") {
849 items.push(Expr::Undefined);
851 self.advance();
852 continue;
853 }
854 if self.eat_punct("...") {
855 let e = self.parse_assign()?;
856 items.push(Expr::Spread(Box::new(e)));
857 } else {
858 items.push(self.parse_assign()?);
859 }
860 if !self.eat_punct(",") {
861 break;
862 }
863 }
864 self.expect_punct("]")?;
865 Ok(Expr::Array(items))
866 }
867
868 fn parse_object_literal(&mut self) -> Result<Expr, String> {
869 self.expect_punct("{")?;
870 let mut props = Vec::new();
871 while !self.is_punct("}") {
872 if self.eat_punct("...") {
873 let e = self.parse_assign()?;
874 props.push(Prop::Spread(e));
875 if !self.eat_punct(",") {
876 break;
877 }
878 continue;
879 }
880 let (key, computed) = if self.is_punct("[") {
882 self.advance();
883 let k = self.parse_assign()?;
884 self.expect_punct("]")?;
885 (k, true)
886 } else {
887 match self.tok().clone() {
888 Tok::Str(s) => {
889 self.advance();
890 (Expr::Str(s), false)
891 }
892 Tok::Num(n) => {
893 self.advance();
894 (Expr::Str(crate::host::fmt_number(n)), false)
895 }
896 Tok::Ident(s) => {
897 self.advance();
898 (Expr::Str(s), false)
899 }
900 other => {
901 return Err(format!(
902 "SyntaxError: bad object key {other:?} (line {})",
903 self.line()
904 ))
905 }
906 }
907 };
908 if self.is_punct("(") {
910 let params = self.parse_params()?;
911 self.expect_punct("{")?;
912 let body = self.parse_block_body()?;
913 let f = Expr::Function {
914 params,
915 body: FnBody::Block(body),
916 is_arrow: false,
917 name: None,
918 };
919 props.push(Prop::KeyValue {
920 key,
921 value: f,
922 computed,
923 });
924 } else if self.eat_punct(":") {
925 let value = self.parse_assign()?;
926 props.push(Prop::KeyValue {
927 key,
928 value,
929 computed,
930 });
931 } else {
932 let name = match &key {
935 Expr::Str(s) => s.clone(),
936 _ => return Err(format!("SyntaxError: bad shorthand (line {})", self.line())),
937 };
938 let value = if self.eat_punct("=") {
939 let d = self.parse_assign()?;
941 Expr::Assign {
942 target: Box::new(Expr::Ident(name.clone())),
943 value: Box::new(d),
944 }
945 } else {
946 Expr::Ident(name)
947 };
948 props.push(Prop::KeyValue {
949 key,
950 value,
951 computed,
952 });
953 }
954 if !self.eat_punct(",") {
955 break;
956 }
957 }
958 self.expect_punct("}")?;
959 Ok(Expr::Object(props))
960 }
961
962 fn parse_params(&mut self) -> Result<Vec<Param>, String> {
964 self.expect_punct("(")?;
965 let mut params = Vec::new();
966 while !self.is_punct(")") {
967 let rest = self.eat_punct("...");
968 let pattern = self.parse_binding_target()?;
969 let default = if !rest && self.eat_punct("=") {
970 Some(self.parse_assign()?)
971 } else {
972 None
973 };
974 params.push(Param {
975 pattern,
976 default,
977 rest,
978 });
979 if !self.eat_punct(",") {
980 break;
981 }
982 }
983 self.expect_punct(")")?;
984 Ok(params)
985 }
986
987 fn try_parse_arrow(&mut self) -> Result<Option<Expr>, String> {
990 if let Tok::Ident(name) = self.tok() {
992 if !is_keyword(name) && self.peek_is_arrow_after(1) {
993 let name = name.clone();
994 self.advance(); self.advance(); let body = self.parse_arrow_body()?;
997 return Ok(Some(Expr::Function {
998 params: vec![Param {
999 pattern: Expr::Ident(name),
1000 default: None,
1001 rest: false,
1002 }],
1003 body,
1004 is_arrow: true,
1005 name: None,
1006 }));
1007 }
1008 }
1009 if self.is_punct("(") {
1011 if let Some(close) = self.matching_paren(self.pos) {
1012 let after = close + 1;
1013 if matches!(self.toks.get(after).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>") {
1014 let params = self.parse_params()?;
1015 self.expect_punct("=>")?;
1016 let body = self.parse_arrow_body()?;
1017 return Ok(Some(Expr::Function {
1018 params,
1019 body,
1020 is_arrow: true,
1021 name: None,
1022 }));
1023 }
1024 }
1025 }
1026 Ok(None)
1027 }
1028
1029 fn parse_arrow_body(&mut self) -> Result<FnBody, String> {
1030 if self.is_punct("{") {
1031 self.advance();
1032 Ok(FnBody::Block(self.parse_block_body()?))
1033 } else {
1034 Ok(FnBody::Expr(Box::new(self.parse_assign()?)))
1035 }
1036 }
1037
1038 fn peek_is_arrow_after(&self, n: usize) -> bool {
1040 matches!(self.toks.get(self.pos + n).map(|t| &t.tok), Some(Tok::Punct(p)) if p == "=>")
1041 }
1042
1043 fn matching_paren(&self, open: usize) -> Option<usize> {
1045 let mut depth = 0i32;
1046 let mut i = open;
1047 while i < self.toks.len() {
1048 match &self.toks[i].tok {
1049 Tok::Punct(p) if p == "(" || p == "[" || p == "{" => depth += 1,
1050 Tok::Punct(p) if p == ")" || p == "]" || p == "}" => {
1051 depth -= 1;
1052 if depth == 0 {
1053 return Some(i);
1054 }
1055 }
1056 Tok::Eof => return None,
1057 _ => {}
1058 }
1059 i += 1;
1060 }
1061 None
1062 }
1063}
1064
1065fn parse_expr_source(src: &str) -> Result<Expr, String> {
1067 let toks = lex(src)?;
1068 let mut p = Parser { toks, pos: 0 };
1069 let e = p.parse_expr()?;
1070 Ok(e)
1071}