we (web engine): Experimental web browser project to understand the limits of Claude
1//! Recursive-descent JavaScript parser with Pratt expression parsing.
2//!
3//! Transforms a token stream from the [`crate::lexer::Lexer`] into an
4//! [`crate::ast::Program`] AST.
5
6use crate::ast::*;
7use crate::lexer::{LexError, Lexer, SourcePos, Span, Token, TokenKind};
8use std::fmt;
9
10// ── Error ───────────────────────────────────────────────────
11
12/// An error produced during parsing.
13#[derive(Debug, Clone, PartialEq)]
14pub struct ParseError {
15 pub message: String,
16 pub pos: SourcePos,
17}
18
19impl fmt::Display for ParseError {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 write!(
22 f,
23 "ParseError at {}:{}: {}",
24 self.pos.line, self.pos.col, self.message
25 )
26 }
27}
28
29impl From<LexError> for ParseError {
30 fn from(e: LexError) -> Self {
31 ParseError {
32 message: e.message,
33 pos: e.pos,
34 }
35 }
36}
37
38// ── Parser ──────────────────────────────────────────────────
39
40pub struct Parser {
41 tokens: Vec<Token>,
42 pos: usize,
43 /// When false, `in` is not treated as a binary operator (for-init disambiguation).
44 allow_in: bool,
45}
46
47impl Parser {
48 /// Parse source as a script.
49 pub fn parse(source: &str) -> Result<Program, ParseError> {
50 let tokens = Lexer::tokenize(source)?;
51 let mut parser = Parser {
52 tokens,
53 pos: 0,
54 allow_in: true,
55 };
56 parser.parse_program(SourceType::Script)
57 }
58
59 /// Parse source as a module.
60 pub fn parse_module(source: &str) -> Result<Program, ParseError> {
61 let tokens = Lexer::tokenize(source)?;
62 let mut parser = Parser {
63 tokens,
64 pos: 0,
65 allow_in: true,
66 };
67 parser.parse_program(SourceType::Module)
68 }
69
70 // ── Token navigation ────────────────────────────────────
71
72 fn peek(&self) -> &Token {
73 &self.tokens[self.pos.min(self.tokens.len() - 1)]
74 }
75
76 fn peek_kind(&self) -> &TokenKind {
77 &self.peek().kind
78 }
79
80 fn peek_ahead(&self, offset: usize) -> &TokenKind {
81 let idx = (self.pos + offset).min(self.tokens.len() - 1);
82 &self.tokens[idx].kind
83 }
84
85 fn at(&self, kind: &TokenKind) -> bool {
86 std::mem::discriminant(self.peek_kind()) == std::mem::discriminant(kind)
87 }
88
89 fn at_eof(&self) -> bool {
90 matches!(self.peek_kind(), TokenKind::Eof)
91 }
92
93 fn advance(&mut self) -> Token {
94 let tok = self.tokens[self.pos.min(self.tokens.len() - 1)].clone();
95 if self.pos < self.tokens.len() - 1 {
96 self.pos += 1;
97 }
98 tok
99 }
100
101 fn eat(&mut self, kind: &TokenKind) -> bool {
102 if self.at(kind) {
103 self.advance();
104 true
105 } else {
106 false
107 }
108 }
109
110 fn expect(&mut self, kind: &TokenKind) -> Result<Token, ParseError> {
111 if self.at(kind) {
112 Ok(self.advance())
113 } else {
114 Err(self.error(format!("expected {:?}, found {:?}", kind, self.peek_kind())))
115 }
116 }
117
118 fn expect_semicolon(&mut self) -> Result<(), ParseError> {
119 if self.eat(&TokenKind::Semicolon) {
120 return Ok(());
121 }
122 // ASI: insert semicolon before `}`, at EOF, or after newline
123 if matches!(self.peek_kind(), TokenKind::RBrace | TokenKind::Eof)
124 || self.peek().preceded_by_newline
125 {
126 return Ok(());
127 }
128 Err(self.error(format!("expected `;`, found {:?}", self.peek_kind())))
129 }
130
131 fn expect_identifier(&mut self) -> Result<String, ParseError> {
132 match self.peek_kind().clone() {
133 TokenKind::Identifier(name) => {
134 self.advance();
135 Ok(name)
136 }
137 _ => Err(self.error(format!("expected identifier, found {:?}", self.peek_kind()))),
138 }
139 }
140
141 fn start_span(&self) -> SourcePos {
142 self.peek().span.start
143 }
144
145 fn end_span(&self) -> SourcePos {
146 if self.pos > 0 {
147 self.tokens[self.pos - 1].span.end
148 } else {
149 self.peek().span.start
150 }
151 }
152
153 fn span_from(&self, start: SourcePos) -> Span {
154 Span {
155 start,
156 end: self.end_span(),
157 }
158 }
159
160 fn error(&self, message: String) -> ParseError {
161 ParseError {
162 message,
163 pos: self.peek().span.start,
164 }
165 }
166
167 // ── Program ─────────────────────────────────────────────
168
169 fn parse_program(&mut self, source_type: SourceType) -> Result<Program, ParseError> {
170 let start = self.start_span();
171 let mut body = Vec::new();
172 while !self.at_eof() {
173 body.push(self.parse_statement_list_item()?);
174 }
175 Ok(Program {
176 body,
177 source_type,
178 span: self.span_from(start),
179 })
180 }
181
182 fn parse_statement_list_item(&mut self) -> Result<Stmt, ParseError> {
183 match self.peek_kind() {
184 TokenKind::Function => self.parse_function_declaration(),
185 TokenKind::Class => self.parse_class_declaration(),
186 TokenKind::Var | TokenKind::Let | TokenKind::Const => {
187 self.parse_variable_declaration_stmt()
188 }
189 TokenKind::Async
190 if matches!(self.peek_ahead(1), TokenKind::Function)
191 && !self.tokens[self.pos + 1].preceded_by_newline =>
192 {
193 self.parse_async_function_declaration()
194 }
195 TokenKind::Import
196 if !matches!(self.peek_ahead(1), TokenKind::LParen | TokenKind::Dot) =>
197 {
198 self.parse_import_declaration()
199 }
200 TokenKind::Export => self.parse_export_declaration(),
201 _ => self.parse_statement(),
202 }
203 }
204
205 // ── Statements ──────────────────────────────────────────
206
207 fn parse_statement(&mut self) -> Result<Stmt, ParseError> {
208 match self.peek_kind() {
209 TokenKind::LBrace => self.parse_block_stmt(),
210 TokenKind::Semicolon => {
211 let start = self.start_span();
212 self.advance();
213 Ok(Stmt {
214 kind: StmtKind::Empty,
215 span: self.span_from(start),
216 })
217 }
218 TokenKind::If => self.parse_if(),
219 TokenKind::For => self.parse_for(),
220 TokenKind::While => self.parse_while(),
221 TokenKind::Do => self.parse_do_while(),
222 TokenKind::Switch => self.parse_switch(),
223 TokenKind::Try => self.parse_try(),
224 TokenKind::Return => self.parse_return(),
225 TokenKind::Throw => self.parse_throw(),
226 TokenKind::Break => self.parse_break(),
227 TokenKind::Continue => self.parse_continue(),
228 TokenKind::With => self.parse_with(),
229 TokenKind::Debugger => {
230 let start = self.start_span();
231 self.advance();
232 self.expect_semicolon()?;
233 Ok(Stmt {
234 kind: StmtKind::Debugger,
235 span: self.span_from(start),
236 })
237 }
238 // Labeled statement: `ident: stmt`
239 TokenKind::Identifier(_) if matches!(self.peek_ahead(1), TokenKind::Colon) => {
240 self.parse_labeled()
241 }
242 // Variable declarations can also appear as statements
243 TokenKind::Var | TokenKind::Let | TokenKind::Const => {
244 self.parse_variable_declaration_stmt()
245 }
246 // Function/class declarations in statement position
247 TokenKind::Function => self.parse_function_declaration(),
248 TokenKind::Class => self.parse_class_declaration(),
249 TokenKind::Async
250 if matches!(self.peek_ahead(1), TokenKind::Function)
251 && !self.tokens[self.pos + 1].preceded_by_newline =>
252 {
253 self.parse_async_function_declaration()
254 }
255 _ => self.parse_expression_statement(),
256 }
257 }
258
259 fn parse_block_stmt(&mut self) -> Result<Stmt, ParseError> {
260 let start = self.start_span();
261 let body = self.parse_block_body()?;
262 Ok(Stmt {
263 kind: StmtKind::Block(body),
264 span: self.span_from(start),
265 })
266 }
267
268 fn parse_block_body(&mut self) -> Result<Vec<Stmt>, ParseError> {
269 self.expect(&TokenKind::LBrace)?;
270 let mut body = Vec::new();
271 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
272 body.push(self.parse_statement_list_item()?);
273 }
274 self.expect(&TokenKind::RBrace)?;
275 Ok(body)
276 }
277
278 fn parse_expression_statement(&mut self) -> Result<Stmt, ParseError> {
279 let start = self.start_span();
280 let expr = self.parse_expression()?;
281 self.expect_semicolon()?;
282 Ok(Stmt {
283 kind: StmtKind::Expr(expr),
284 span: self.span_from(start),
285 })
286 }
287
288 fn parse_if(&mut self) -> Result<Stmt, ParseError> {
289 let start = self.start_span();
290 self.expect(&TokenKind::If)?;
291 self.expect(&TokenKind::LParen)?;
292 let test = self.parse_expression()?;
293 self.expect(&TokenKind::RParen)?;
294 let consequent = Box::new(self.parse_statement()?);
295 let alternate = if self.eat(&TokenKind::Else) {
296 Some(Box::new(self.parse_statement()?))
297 } else {
298 None
299 };
300 Ok(Stmt {
301 kind: StmtKind::If {
302 test,
303 consequent,
304 alternate,
305 },
306 span: self.span_from(start),
307 })
308 }
309
310 fn parse_while(&mut self) -> Result<Stmt, ParseError> {
311 let start = self.start_span();
312 self.expect(&TokenKind::While)?;
313 self.expect(&TokenKind::LParen)?;
314 let test = self.parse_expression()?;
315 self.expect(&TokenKind::RParen)?;
316 let body = Box::new(self.parse_statement()?);
317 Ok(Stmt {
318 kind: StmtKind::While { test, body },
319 span: self.span_from(start),
320 })
321 }
322
323 fn parse_do_while(&mut self) -> Result<Stmt, ParseError> {
324 let start = self.start_span();
325 self.expect(&TokenKind::Do)?;
326 let body = Box::new(self.parse_statement()?);
327 self.expect(&TokenKind::While)?;
328 self.expect(&TokenKind::LParen)?;
329 let test = self.parse_expression()?;
330 self.expect(&TokenKind::RParen)?;
331 self.expect_semicolon()?;
332 Ok(Stmt {
333 kind: StmtKind::DoWhile { body, test },
334 span: self.span_from(start),
335 })
336 }
337
338 fn parse_for(&mut self) -> Result<Stmt, ParseError> {
339 let start = self.start_span();
340 self.expect(&TokenKind::For)?;
341 self.expect(&TokenKind::LParen)?;
342
343 // Check for for-in/for-of with var/let/const
344 if matches!(
345 self.peek_kind(),
346 TokenKind::Var | TokenKind::Let | TokenKind::Const
347 ) {
348 let var_kind = match self.peek_kind() {
349 TokenKind::Var => VarKind::Var,
350 TokenKind::Let => VarKind::Let,
351 TokenKind::Const => VarKind::Const,
352 _ => unreachable!(),
353 };
354 self.advance();
355 let pattern = self.parse_binding_pattern()?;
356
357 if self.eat(&TokenKind::In) {
358 let right = self.parse_expression()?;
359 self.expect(&TokenKind::RParen)?;
360 let body = Box::new(self.parse_statement()?);
361 return Ok(Stmt {
362 kind: StmtKind::ForIn {
363 left: ForInOfLeft::VarDecl {
364 kind: var_kind,
365 pattern,
366 },
367 right,
368 body,
369 },
370 span: self.span_from(start),
371 });
372 }
373 if self.eat(&TokenKind::Of) {
374 let right = self.parse_assignment_expression()?;
375 self.expect(&TokenKind::RParen)?;
376 let body = Box::new(self.parse_statement()?);
377 return Ok(Stmt {
378 kind: StmtKind::ForOf {
379 left: ForInOfLeft::VarDecl {
380 kind: var_kind,
381 pattern,
382 },
383 right,
384 body,
385 is_await: false,
386 },
387 span: self.span_from(start),
388 });
389 }
390
391 // Regular for: parse remaining declarators
392 let mut declarators = vec![VarDeclarator {
393 span: pattern.span,
394 init: if self.eat(&TokenKind::Assign) {
395 Some(self.parse_assignment_expression_no_in()?)
396 } else {
397 None
398 },
399 pattern,
400 }];
401 while self.eat(&TokenKind::Comma) {
402 declarators.push(self.parse_var_declarator_no_in()?);
403 }
404 self.expect(&TokenKind::Semicolon)?;
405 let test = if self.at(&TokenKind::Semicolon) {
406 None
407 } else {
408 Some(self.parse_expression()?)
409 };
410 self.expect(&TokenKind::Semicolon)?;
411 let update = if self.at(&TokenKind::RParen) {
412 None
413 } else {
414 Some(self.parse_expression()?)
415 };
416 self.expect(&TokenKind::RParen)?;
417 let body = Box::new(self.parse_statement()?);
418 return Ok(Stmt {
419 kind: StmtKind::For {
420 init: Some(ForInit::VarDecl {
421 kind: var_kind,
422 declarators,
423 }),
424 test,
425 update,
426 body,
427 },
428 span: self.span_from(start),
429 });
430 }
431
432 // No var/let/const
433 if self.eat(&TokenKind::Semicolon) {
434 // for(; ...)
435 let test = if self.at(&TokenKind::Semicolon) {
436 None
437 } else {
438 Some(self.parse_expression()?)
439 };
440 self.expect(&TokenKind::Semicolon)?;
441 let update = if self.at(&TokenKind::RParen) {
442 None
443 } else {
444 Some(self.parse_expression()?)
445 };
446 self.expect(&TokenKind::RParen)?;
447 let body = Box::new(self.parse_statement()?);
448 return Ok(Stmt {
449 kind: StmtKind::For {
450 init: None,
451 test,
452 update,
453 body,
454 },
455 span: self.span_from(start),
456 });
457 }
458
459 // Expression init — might be for-in/for-of
460 let old_allow_in = self.allow_in;
461 self.allow_in = false;
462 let init_expr = self.parse_expression()?;
463 self.allow_in = old_allow_in;
464
465 if self.eat(&TokenKind::In) {
466 let pattern = self.expr_to_pattern(&init_expr)?;
467 let right = self.parse_expression()?;
468 self.expect(&TokenKind::RParen)?;
469 let body = Box::new(self.parse_statement()?);
470 return Ok(Stmt {
471 kind: StmtKind::ForIn {
472 left: ForInOfLeft::Pattern(pattern),
473 right,
474 body,
475 },
476 span: self.span_from(start),
477 });
478 }
479 if self.eat(&TokenKind::Of) {
480 let pattern = self.expr_to_pattern(&init_expr)?;
481 let right = self.parse_assignment_expression()?;
482 self.expect(&TokenKind::RParen)?;
483 let body = Box::new(self.parse_statement()?);
484 return Ok(Stmt {
485 kind: StmtKind::ForOf {
486 left: ForInOfLeft::Pattern(pattern),
487 right,
488 body,
489 is_await: false,
490 },
491 span: self.span_from(start),
492 });
493 }
494
495 self.expect(&TokenKind::Semicolon)?;
496 let test = if self.at(&TokenKind::Semicolon) {
497 None
498 } else {
499 Some(self.parse_expression()?)
500 };
501 self.expect(&TokenKind::Semicolon)?;
502 let update = if self.at(&TokenKind::RParen) {
503 None
504 } else {
505 Some(self.parse_expression()?)
506 };
507 self.expect(&TokenKind::RParen)?;
508 let body = Box::new(self.parse_statement()?);
509 Ok(Stmt {
510 kind: StmtKind::For {
511 init: Some(ForInit::Expr(init_expr)),
512 test,
513 update,
514 body,
515 },
516 span: self.span_from(start),
517 })
518 }
519
520 fn parse_switch(&mut self) -> Result<Stmt, ParseError> {
521 let start = self.start_span();
522 self.expect(&TokenKind::Switch)?;
523 self.expect(&TokenKind::LParen)?;
524 let discriminant = self.parse_expression()?;
525 self.expect(&TokenKind::RParen)?;
526 self.expect(&TokenKind::LBrace)?;
527 let mut cases = Vec::new();
528 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
529 let case_start = self.start_span();
530 let test = if self.eat(&TokenKind::Case) {
531 Some(self.parse_expression()?)
532 } else {
533 self.expect(&TokenKind::Default)?;
534 None
535 };
536 self.expect(&TokenKind::Colon)?;
537 let mut consequent = Vec::new();
538 while !matches!(
539 self.peek_kind(),
540 TokenKind::Case | TokenKind::Default | TokenKind::RBrace
541 ) && !self.at_eof()
542 {
543 consequent.push(self.parse_statement_list_item()?);
544 }
545 cases.push(SwitchCase {
546 test,
547 consequent,
548 span: self.span_from(case_start),
549 });
550 }
551 self.expect(&TokenKind::RBrace)?;
552 Ok(Stmt {
553 kind: StmtKind::Switch {
554 discriminant,
555 cases,
556 },
557 span: self.span_from(start),
558 })
559 }
560
561 fn parse_try(&mut self) -> Result<Stmt, ParseError> {
562 let start = self.start_span();
563 self.expect(&TokenKind::Try)?;
564 let block = self.parse_block_body()?;
565
566 let handler = if self.eat(&TokenKind::Catch) {
567 let catch_start = self.start_span();
568 let param = if self.eat(&TokenKind::LParen) {
569 let pat = self.parse_binding_pattern()?;
570 self.expect(&TokenKind::RParen)?;
571 Some(pat)
572 } else {
573 None
574 };
575 let body = self.parse_block_body()?;
576 Some(CatchClause {
577 param,
578 body,
579 span: self.span_from(catch_start),
580 })
581 } else {
582 None
583 };
584
585 let finalizer = if self.eat(&TokenKind::Finally) {
586 Some(self.parse_block_body()?)
587 } else {
588 None
589 };
590
591 if handler.is_none() && finalizer.is_none() {
592 return Err(self.error("try requires catch or finally".into()));
593 }
594
595 Ok(Stmt {
596 kind: StmtKind::Try {
597 block,
598 handler,
599 finalizer,
600 },
601 span: self.span_from(start),
602 })
603 }
604
605 fn parse_return(&mut self) -> Result<Stmt, ParseError> {
606 let start = self.start_span();
607 self.expect(&TokenKind::Return)?;
608 // Restricted production: newline after return inserts semicolon
609 let argument = if matches!(
610 self.peek_kind(),
611 TokenKind::Semicolon | TokenKind::RBrace | TokenKind::Eof
612 ) || self.peek().preceded_by_newline
613 {
614 None
615 } else {
616 Some(self.parse_expression()?)
617 };
618 self.expect_semicolon()?;
619 Ok(Stmt {
620 kind: StmtKind::Return(argument),
621 span: self.span_from(start),
622 })
623 }
624
625 fn parse_throw(&mut self) -> Result<Stmt, ParseError> {
626 let start = self.start_span();
627 self.expect(&TokenKind::Throw)?;
628 if self.peek().preceded_by_newline {
629 return Err(ParseError {
630 message: "newline not allowed after throw".into(),
631 pos: self.peek().span.start,
632 });
633 }
634 let argument = self.parse_expression()?;
635 self.expect_semicolon()?;
636 Ok(Stmt {
637 kind: StmtKind::Throw(argument),
638 span: self.span_from(start),
639 })
640 }
641
642 fn parse_break(&mut self) -> Result<Stmt, ParseError> {
643 let start = self.start_span();
644 self.expect(&TokenKind::Break)?;
645 let label = if !self.peek().preceded_by_newline {
646 if let TokenKind::Identifier(name) = self.peek_kind().clone() {
647 self.advance();
648 Some(name)
649 } else {
650 None
651 }
652 } else {
653 None
654 };
655 self.expect_semicolon()?;
656 Ok(Stmt {
657 kind: StmtKind::Break(label),
658 span: self.span_from(start),
659 })
660 }
661
662 fn parse_continue(&mut self) -> Result<Stmt, ParseError> {
663 let start = self.start_span();
664 self.expect(&TokenKind::Continue)?;
665 let label = if !self.peek().preceded_by_newline {
666 if let TokenKind::Identifier(name) = self.peek_kind().clone() {
667 self.advance();
668 Some(name)
669 } else {
670 None
671 }
672 } else {
673 None
674 };
675 self.expect_semicolon()?;
676 Ok(Stmt {
677 kind: StmtKind::Continue(label),
678 span: self.span_from(start),
679 })
680 }
681
682 fn parse_labeled(&mut self) -> Result<Stmt, ParseError> {
683 let start = self.start_span();
684 let label = self.expect_identifier()?;
685 self.expect(&TokenKind::Colon)?;
686 let body = Box::new(self.parse_statement()?);
687 Ok(Stmt {
688 kind: StmtKind::Labeled { label, body },
689 span: self.span_from(start),
690 })
691 }
692
693 fn parse_with(&mut self) -> Result<Stmt, ParseError> {
694 let start = self.start_span();
695 self.expect(&TokenKind::With)?;
696 self.expect(&TokenKind::LParen)?;
697 let object = self.parse_expression()?;
698 self.expect(&TokenKind::RParen)?;
699 let body = Box::new(self.parse_statement()?);
700 Ok(Stmt {
701 kind: StmtKind::With { object, body },
702 span: self.span_from(start),
703 })
704 }
705
706 // ── Variable declarations ───────────────────────────────
707
708 fn parse_variable_declaration_stmt(&mut self) -> Result<Stmt, ParseError> {
709 let start = self.start_span();
710 let kind = match self.peek_kind() {
711 TokenKind::Var => VarKind::Var,
712 TokenKind::Let => VarKind::Let,
713 TokenKind::Const => VarKind::Const,
714 _ => return Err(self.error("expected var, let, or const".into())),
715 };
716 self.advance();
717 let mut declarators = vec![self.parse_var_declarator()?];
718 while self.eat(&TokenKind::Comma) {
719 declarators.push(self.parse_var_declarator()?);
720 }
721 self.expect_semicolon()?;
722 Ok(Stmt {
723 kind: StmtKind::VarDecl { kind, declarators },
724 span: self.span_from(start),
725 })
726 }
727
728 fn parse_var_declarator(&mut self) -> Result<VarDeclarator, ParseError> {
729 let start = self.start_span();
730 let pattern = self.parse_binding_pattern()?;
731 let init = if self.eat(&TokenKind::Assign) {
732 Some(self.parse_assignment_expression()?)
733 } else {
734 None
735 };
736 Ok(VarDeclarator {
737 pattern,
738 init,
739 span: self.span_from(start),
740 })
741 }
742
743 fn parse_var_declarator_no_in(&mut self) -> Result<VarDeclarator, ParseError> {
744 let start = self.start_span();
745 let pattern = self.parse_binding_pattern()?;
746 let init = if self.eat(&TokenKind::Assign) {
747 Some(self.parse_assignment_expression_no_in()?)
748 } else {
749 None
750 };
751 Ok(VarDeclarator {
752 pattern,
753 init,
754 span: self.span_from(start),
755 })
756 }
757
758 // ── Binding patterns (destructuring) ────────────────────
759
760 fn parse_binding_pattern(&mut self) -> Result<Pattern, ParseError> {
761 match self.peek_kind() {
762 TokenKind::LBracket => self.parse_array_pattern(),
763 TokenKind::LBrace => self.parse_object_pattern(),
764 _ => {
765 let start = self.start_span();
766 let name = self.expect_identifier()?;
767 Ok(Pattern {
768 kind: PatternKind::Identifier(name),
769 span: self.span_from(start),
770 })
771 }
772 }
773 }
774
775 fn parse_array_pattern(&mut self) -> Result<Pattern, ParseError> {
776 let start = self.start_span();
777 self.expect(&TokenKind::LBracket)?;
778 let mut elements = Vec::new();
779 let mut rest = None;
780 while !self.at(&TokenKind::RBracket) && !self.at_eof() {
781 if self.eat(&TokenKind::Comma) {
782 elements.push(None);
783 continue;
784 }
785 if self.at(&TokenKind::Ellipsis) {
786 self.advance();
787 rest = Some(Box::new(self.parse_binding_pattern()?));
788 self.eat(&TokenKind::Comma); // trailing comma after rest
789 break;
790 }
791 let mut pat = self.parse_binding_pattern()?;
792 if self.eat(&TokenKind::Assign) {
793 let right = self.parse_assignment_expression()?;
794 let span = Span {
795 start: pat.span.start,
796 end: right.span.end,
797 };
798 pat = Pattern {
799 kind: PatternKind::Assign {
800 left: Box::new(pat),
801 right: Box::new(right),
802 },
803 span,
804 };
805 }
806 elements.push(Some(pat));
807 if !self.eat(&TokenKind::Comma) {
808 break;
809 }
810 }
811 self.expect(&TokenKind::RBracket)?;
812 Ok(Pattern {
813 kind: PatternKind::Array { elements, rest },
814 span: self.span_from(start),
815 })
816 }
817
818 fn parse_object_pattern(&mut self) -> Result<Pattern, ParseError> {
819 let start = self.start_span();
820 self.expect(&TokenKind::LBrace)?;
821 let mut properties = Vec::new();
822 let mut rest = None;
823 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
824 if self.at(&TokenKind::Ellipsis) {
825 self.advance();
826 rest = Some(Box::new(self.parse_binding_pattern()?));
827 self.eat(&TokenKind::Comma);
828 break;
829 }
830 let prop_start = self.start_span();
831 let (key, computed) = self.parse_property_name()?;
832 if self.eat(&TokenKind::Colon) {
833 // { key: pattern }
834 let mut value = self.parse_binding_pattern()?;
835 if self.eat(&TokenKind::Assign) {
836 let right = self.parse_assignment_expression()?;
837 let span = Span {
838 start: value.span.start,
839 end: right.span.end,
840 };
841 value = Pattern {
842 kind: PatternKind::Assign {
843 left: Box::new(value),
844 right: Box::new(right),
845 },
846 span,
847 };
848 }
849 properties.push(ObjectPatternProp {
850 key,
851 value,
852 computed,
853 shorthand: false,
854 span: self.span_from(prop_start),
855 });
856 } else {
857 // Shorthand: { name } or { name = default }
858 let name = match &key {
859 PropertyKey::Identifier(n) => n.clone(),
860 _ => return Err(self.error("shorthand properties require identifier".into())),
861 };
862 let ident_span = self.span_from(prop_start);
863 let mut value = Pattern {
864 kind: PatternKind::Identifier(name.clone()),
865 span: ident_span,
866 };
867 if self.eat(&TokenKind::Assign) {
868 let right = self.parse_assignment_expression()?;
869 let span = Span {
870 start: value.span.start,
871 end: right.span.end,
872 };
873 value = Pattern {
874 kind: PatternKind::Assign {
875 left: Box::new(value),
876 right: Box::new(right),
877 },
878 span,
879 };
880 }
881 properties.push(ObjectPatternProp {
882 key,
883 value,
884 computed,
885 shorthand: true,
886 span: self.span_from(prop_start),
887 });
888 }
889 if !self.eat(&TokenKind::Comma) {
890 break;
891 }
892 }
893 self.expect(&TokenKind::RBrace)?;
894 Ok(Pattern {
895 kind: PatternKind::Object { properties, rest },
896 span: self.span_from(start),
897 })
898 }
899
900 // ── Function declarations ───────────────────────────────
901
902 fn parse_function_declaration(&mut self) -> Result<Stmt, ParseError> {
903 let start = self.start_span();
904 self.expect(&TokenKind::Function)?;
905 let is_generator = self.eat(&TokenKind::Star);
906 let id = Some(self.expect_identifier()?);
907 let (params, body) = self.parse_function_params_and_body()?;
908 Ok(Stmt {
909 kind: StmtKind::FunctionDecl(FunctionDef {
910 id,
911 params,
912 body,
913 is_async: false,
914 is_generator,
915 }),
916 span: self.span_from(start),
917 })
918 }
919
920 fn parse_async_function_declaration(&mut self) -> Result<Stmt, ParseError> {
921 let start = self.start_span();
922 self.expect(&TokenKind::Async)?;
923 self.expect(&TokenKind::Function)?;
924 let is_generator = self.eat(&TokenKind::Star);
925 let id = Some(self.expect_identifier()?);
926 let (params, body) = self.parse_function_params_and_body()?;
927 Ok(Stmt {
928 kind: StmtKind::FunctionDecl(FunctionDef {
929 id,
930 params,
931 body,
932 is_async: true,
933 is_generator,
934 }),
935 span: self.span_from(start),
936 })
937 }
938
939 fn parse_function_params_and_body(&mut self) -> Result<(Vec<Pattern>, Vec<Stmt>), ParseError> {
940 self.expect(&TokenKind::LParen)?;
941 let params = self.parse_formal_parameters()?;
942 self.expect(&TokenKind::RParen)?;
943 let body = self.parse_block_body()?;
944 Ok((params, body))
945 }
946
947 fn parse_formal_parameters(&mut self) -> Result<Vec<Pattern>, ParseError> {
948 let mut params = Vec::new();
949 while !self.at(&TokenKind::RParen) && !self.at_eof() {
950 if self.at(&TokenKind::Ellipsis) {
951 self.advance();
952 params.push(self.parse_binding_pattern()?);
953 self.eat(&TokenKind::Comma);
954 break;
955 }
956 let mut pat = self.parse_binding_pattern()?;
957 if self.eat(&TokenKind::Assign) {
958 let right = self.parse_assignment_expression()?;
959 let span = Span {
960 start: pat.span.start,
961 end: right.span.end,
962 };
963 pat = Pattern {
964 kind: PatternKind::Assign {
965 left: Box::new(pat),
966 right: Box::new(right),
967 },
968 span,
969 };
970 }
971 params.push(pat);
972 if !self.eat(&TokenKind::Comma) {
973 break;
974 }
975 }
976 Ok(params)
977 }
978
979 // ── Class declarations ──────────────────────────────────
980
981 fn parse_class_declaration(&mut self) -> Result<Stmt, ParseError> {
982 let start = self.start_span();
983 let class_def = self.parse_class(true)?;
984 Ok(Stmt {
985 kind: StmtKind::ClassDecl(class_def),
986 span: self.span_from(start),
987 })
988 }
989
990 fn parse_class(&mut self, require_name: bool) -> Result<ClassDef, ParseError> {
991 self.expect(&TokenKind::Class)?;
992 let id = if require_name {
993 Some(self.expect_identifier()?)
994 } else if let TokenKind::Identifier(_) = self.peek_kind() {
995 Some(self.expect_identifier()?)
996 } else {
997 None
998 };
999 let super_class = if self.eat(&TokenKind::Extends) {
1000 Some(Box::new(self.parse_left_hand_side_expression()?))
1001 } else {
1002 None
1003 };
1004 let body = self.parse_class_body()?;
1005 Ok(ClassDef {
1006 id,
1007 super_class,
1008 body,
1009 })
1010 }
1011
1012 fn parse_class_body(&mut self) -> Result<Vec<ClassMember>, ParseError> {
1013 self.expect(&TokenKind::LBrace)?;
1014 let mut members = Vec::new();
1015 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
1016 if self.eat(&TokenKind::Semicolon) {
1017 continue;
1018 }
1019 members.push(self.parse_class_member()?);
1020 }
1021 self.expect(&TokenKind::RBrace)?;
1022 Ok(members)
1023 }
1024
1025 fn parse_class_member(&mut self) -> Result<ClassMember, ParseError> {
1026 let start = self.start_span();
1027 let is_static = self.eat(&TokenKind::Static);
1028
1029 // Check for getter/setter
1030 if let TokenKind::Identifier(ref name) = self.peek_kind().clone() {
1031 if (name == "get" || name == "set")
1032 && !matches!(
1033 self.peek_ahead(1),
1034 TokenKind::LParen | TokenKind::Assign | TokenKind::Semicolon
1035 )
1036 {
1037 let kind = if name == "get" {
1038 MethodKind::Get
1039 } else {
1040 MethodKind::Set
1041 };
1042 self.advance();
1043 let (key, computed) = self.parse_property_name()?;
1044 let (params, body) = self.parse_function_params_and_body()?;
1045 return Ok(ClassMember {
1046 kind: ClassMemberKind::Method {
1047 key,
1048 value: FunctionDef {
1049 id: None,
1050 params,
1051 body,
1052 is_async: false,
1053 is_generator: false,
1054 },
1055 kind,
1056 is_static,
1057 computed,
1058 },
1059 span: self.span_from(start),
1060 });
1061 }
1062 }
1063
1064 // Generator method
1065 let is_generator = self.eat(&TokenKind::Star);
1066
1067 // Async method
1068 let is_async = if !is_generator
1069 && matches!(self.peek_kind(), TokenKind::Async)
1070 && !matches!(
1071 self.peek_ahead(1),
1072 TokenKind::LParen | TokenKind::Assign | TokenKind::Semicolon
1073 ) {
1074 self.advance();
1075 true
1076 } else {
1077 false
1078 };
1079
1080 let is_generator = is_generator || (is_async && self.eat(&TokenKind::Star));
1081
1082 let (key, computed) = self.parse_property_name()?;
1083
1084 // Check for constructor
1085 let method_kind =
1086 if !is_static && !computed && key == PropertyKey::Identifier("constructor".into()) {
1087 MethodKind::Constructor
1088 } else {
1089 MethodKind::Method
1090 };
1091
1092 if self.at(&TokenKind::LParen) {
1093 let (params, body) = self.parse_function_params_and_body()?;
1094 Ok(ClassMember {
1095 kind: ClassMemberKind::Method {
1096 key,
1097 value: FunctionDef {
1098 id: None,
1099 params,
1100 body,
1101 is_async,
1102 is_generator,
1103 },
1104 kind: method_kind,
1105 is_static,
1106 computed,
1107 },
1108 span: self.span_from(start),
1109 })
1110 } else {
1111 // Class field
1112 let value = if self.eat(&TokenKind::Assign) {
1113 Some(self.parse_assignment_expression()?)
1114 } else {
1115 None
1116 };
1117 self.expect_semicolon()?;
1118 Ok(ClassMember {
1119 kind: ClassMemberKind::Property {
1120 key,
1121 value,
1122 is_static,
1123 computed,
1124 },
1125 span: self.span_from(start),
1126 })
1127 }
1128 }
1129
1130 // ── Import / Export ─────────────────────────────────────
1131
1132 fn parse_import_declaration(&mut self) -> Result<Stmt, ParseError> {
1133 let start = self.start_span();
1134 self.expect(&TokenKind::Import)?;
1135
1136 // `import "source"` — side-effect import
1137 if let TokenKind::String(source) = self.peek_kind().clone() {
1138 self.advance();
1139 self.expect_semicolon()?;
1140 return Ok(Stmt {
1141 kind: StmtKind::Import {
1142 specifiers: vec![],
1143 source,
1144 },
1145 span: self.span_from(start),
1146 });
1147 }
1148
1149 let mut specifiers = Vec::new();
1150
1151 // `import * as ns from "source"`
1152 if self.eat(&TokenKind::Star) {
1153 self.expect_identifier_matching("as")?;
1154 let local = self.expect_identifier()?;
1155 specifiers.push(ImportSpecifier::Namespace(local));
1156 }
1157 // `import { a, b as c } from "source"`
1158 else if self.at(&TokenKind::LBrace) {
1159 self.advance();
1160 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
1161 let imported = self.expect_identifier()?;
1162 let local = if self.eat_identifier_matching("as") {
1163 self.expect_identifier()?
1164 } else {
1165 imported.clone()
1166 };
1167 specifiers.push(ImportSpecifier::Named { imported, local });
1168 if !self.eat(&TokenKind::Comma) {
1169 break;
1170 }
1171 }
1172 self.expect(&TokenKind::RBrace)?;
1173 }
1174 // `import defaultExport from "source"` or `import defaultExport, { ... } from "source"`
1175 else {
1176 let default_name = self.expect_identifier()?;
1177 specifiers.push(ImportSpecifier::Default(default_name));
1178
1179 if self.eat(&TokenKind::Comma) {
1180 if self.eat(&TokenKind::Star) {
1181 self.expect_identifier_matching("as")?;
1182 let local = self.expect_identifier()?;
1183 specifiers.push(ImportSpecifier::Namespace(local));
1184 } else {
1185 self.expect(&TokenKind::LBrace)?;
1186 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
1187 let imported = self.expect_identifier()?;
1188 let local = if self.eat_identifier_matching("as") {
1189 self.expect_identifier()?
1190 } else {
1191 imported.clone()
1192 };
1193 specifiers.push(ImportSpecifier::Named { imported, local });
1194 if !self.eat(&TokenKind::Comma) {
1195 break;
1196 }
1197 }
1198 self.expect(&TokenKind::RBrace)?;
1199 }
1200 }
1201 }
1202
1203 self.expect_identifier_matching("from")?;
1204 let source = match self.peek_kind().clone() {
1205 TokenKind::String(s) => {
1206 self.advance();
1207 s
1208 }
1209 _ => return Err(self.error("expected module source string".into())),
1210 };
1211 self.expect_semicolon()?;
1212 Ok(Stmt {
1213 kind: StmtKind::Import { specifiers, source },
1214 span: self.span_from(start),
1215 })
1216 }
1217
1218 fn parse_export_declaration(&mut self) -> Result<Stmt, ParseError> {
1219 let start = self.start_span();
1220 self.expect(&TokenKind::Export)?;
1221
1222 // `export default ...`
1223 if self.eat(&TokenKind::Default) {
1224 if matches!(self.peek_kind(), TokenKind::Function) {
1225 // Named function → declaration, anonymous → default expression
1226 let has_name = matches!(self.peek_ahead(1), TokenKind::Identifier(_))
1227 || (matches!(self.peek_ahead(1), TokenKind::Star)
1228 && matches!(self.peek_ahead(2), TokenKind::Identifier(_)));
1229 if has_name {
1230 let decl = self.parse_function_declaration()?;
1231 return Ok(Stmt {
1232 kind: StmtKind::Export(ExportDecl::Declaration(Box::new(decl))),
1233 span: self.span_from(start),
1234 });
1235 }
1236 let expr = self.parse_function_expression()?;
1237 return Ok(Stmt {
1238 kind: StmtKind::Export(ExportDecl::Default(expr)),
1239 span: self.span_from(start),
1240 });
1241 }
1242 if matches!(self.peek_kind(), TokenKind::Class) {
1243 // Named class → declaration, anonymous → default expression
1244 if matches!(self.peek_ahead(1), TokenKind::Identifier(_)) {
1245 let decl = self.parse_class_declaration()?;
1246 return Ok(Stmt {
1247 kind: StmtKind::Export(ExportDecl::Declaration(Box::new(decl))),
1248 span: self.span_from(start),
1249 });
1250 }
1251 let expr = self.parse_class_expression()?;
1252 return Ok(Stmt {
1253 kind: StmtKind::Export(ExportDecl::Default(expr)),
1254 span: self.span_from(start),
1255 });
1256 }
1257 let expr = self.parse_assignment_expression()?;
1258 self.expect_semicolon()?;
1259 return Ok(Stmt {
1260 kind: StmtKind::Export(ExportDecl::Default(expr)),
1261 span: self.span_from(start),
1262 });
1263 }
1264
1265 // `export * from "source"`
1266 if self.eat(&TokenKind::Star) {
1267 self.expect_identifier_matching("from")?;
1268 let source = match self.peek_kind().clone() {
1269 TokenKind::String(s) => {
1270 self.advance();
1271 s
1272 }
1273 _ => return Err(self.error("expected module source string".into())),
1274 };
1275 self.expect_semicolon()?;
1276 return Ok(Stmt {
1277 kind: StmtKind::Export(ExportDecl::AllFrom(source)),
1278 span: self.span_from(start),
1279 });
1280 }
1281
1282 // `export { a, b as c } [from "source"]`
1283 if self.at(&TokenKind::LBrace) {
1284 self.advance();
1285 let mut specifiers = Vec::new();
1286 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
1287 let local = self.expect_identifier()?;
1288 let exported = if self.eat_identifier_matching("as") {
1289 self.expect_identifier()?
1290 } else {
1291 local.clone()
1292 };
1293 specifiers.push(ExportSpecifier { local, exported });
1294 if !self.eat(&TokenKind::Comma) {
1295 break;
1296 }
1297 }
1298 self.expect(&TokenKind::RBrace)?;
1299 let source = if self.eat_identifier_matching("from") {
1300 match self.peek_kind().clone() {
1301 TokenKind::String(s) => {
1302 self.advance();
1303 Some(s)
1304 }
1305 _ => return Err(self.error("expected module source string".into())),
1306 }
1307 } else {
1308 None
1309 };
1310 self.expect_semicolon()?;
1311 return Ok(Stmt {
1312 kind: StmtKind::Export(ExportDecl::Named { specifiers, source }),
1313 span: self.span_from(start),
1314 });
1315 }
1316
1317 // `export var/let/const/function/class ...`
1318 let decl = self.parse_statement_list_item()?;
1319 Ok(Stmt {
1320 kind: StmtKind::Export(ExportDecl::Declaration(Box::new(decl))),
1321 span: self.span_from(start),
1322 })
1323 }
1324
1325 // ── Helper for contextual keywords ──────────────────────
1326
1327 fn expect_identifier_matching(&mut self, expected: &str) -> Result<(), ParseError> {
1328 match self.peek_kind().clone() {
1329 TokenKind::Identifier(ref name) if name == expected => {
1330 self.advance();
1331 Ok(())
1332 }
1333 _ => Err(self.error(format!("expected '{}'", expected))),
1334 }
1335 }
1336
1337 fn eat_identifier_matching(&mut self, expected: &str) -> bool {
1338 if let TokenKind::Identifier(ref name) = self.peek_kind() {
1339 if name == expected {
1340 self.advance();
1341 return true;
1342 }
1343 }
1344 false
1345 }
1346
1347 // ── Expressions ─────────────────────────────────────────
1348
1349 fn parse_expression(&mut self) -> Result<Expr, ParseError> {
1350 let start = self.start_span();
1351 let expr = self.parse_assignment_expression()?;
1352 if !self.at(&TokenKind::Comma) {
1353 return Ok(expr);
1354 }
1355 let mut exprs = vec![expr];
1356 while self.eat(&TokenKind::Comma) {
1357 exprs.push(self.parse_assignment_expression()?);
1358 }
1359 Ok(Expr {
1360 kind: ExprKind::Sequence(exprs),
1361 span: self.span_from(start),
1362 })
1363 }
1364
1365 fn parse_assignment_expression(&mut self) -> Result<Expr, ParseError> {
1366 // Check for arrow function: `x => ...` or `async x => ...`
1367 if let TokenKind::Identifier(ref name) = self.peek_kind().clone() {
1368 if matches!(self.peek_ahead(1), TokenKind::Arrow) && !self.peek().preceded_by_newline {
1369 let param_start = self.start_span();
1370 let name = name.clone();
1371 self.advance(); // identifier
1372 self.advance(); // =>
1373 let params = vec![Pattern {
1374 kind: PatternKind::Identifier(name),
1375 span: self.span_from(param_start),
1376 }];
1377 return self.parse_arrow_body(param_start, params, false);
1378 }
1379 }
1380
1381 // Check for `async x => ...` or `async (...)` arrow
1382 if matches!(self.peek_kind(), TokenKind::Async) && !self.peek().preceded_by_newline {
1383 if let TokenKind::Identifier(_) = self.peek_ahead(1) {
1384 if matches!(self.peek_ahead(2), TokenKind::Arrow) {
1385 let start = self.start_span();
1386 self.advance(); // async
1387 let param_start = self.start_span();
1388 let name = self.expect_identifier()?;
1389 self.advance(); // =>
1390 let params = vec![Pattern {
1391 kind: PatternKind::Identifier(name),
1392 span: self.span_from(param_start),
1393 }];
1394 return self.parse_arrow_body(start, params, true);
1395 }
1396 }
1397 }
1398
1399 let start = self.start_span();
1400 let left = self.parse_conditional_expression()?;
1401
1402 // Check for arrow function after parenthesized expr: `(a, b) => ...`
1403 if matches!(self.peek_kind(), TokenKind::Arrow) && !self.peek().preceded_by_newline {
1404 self.advance(); // =>
1405 let params = self.expr_to_params(&left)?;
1406 return self.parse_arrow_body(start, params, false);
1407 }
1408
1409 // Assignment
1410 if let Some(op) = self.peek_assign_op() {
1411 self.advance();
1412 let right = self.parse_assignment_expression()?;
1413 return Ok(Expr {
1414 span: self.span_from(start),
1415 kind: ExprKind::Assignment {
1416 op,
1417 left: Box::new(left),
1418 right: Box::new(right),
1419 },
1420 });
1421 }
1422
1423 Ok(left)
1424 }
1425
1426 fn parse_assignment_expression_no_in(&mut self) -> Result<Expr, ParseError> {
1427 let old = self.allow_in;
1428 self.allow_in = false;
1429 let result = self.parse_assignment_expression();
1430 self.allow_in = old;
1431 result
1432 }
1433
1434 fn parse_arrow_body(
1435 &mut self,
1436 start: SourcePos,
1437 params: Vec<Pattern>,
1438 is_async: bool,
1439 ) -> Result<Expr, ParseError> {
1440 let body = if self.at(&TokenKind::LBrace) {
1441 ArrowBody::Block(self.parse_block_body()?)
1442 } else {
1443 ArrowBody::Expr(Box::new(self.parse_assignment_expression()?))
1444 };
1445 Ok(Expr {
1446 kind: ExprKind::Arrow {
1447 params,
1448 body,
1449 is_async,
1450 },
1451 span: self.span_from(start),
1452 })
1453 }
1454
1455 fn parse_conditional_expression(&mut self) -> Result<Expr, ParseError> {
1456 let start = self.start_span();
1457 let expr = self.parse_binary_expression(0)?;
1458 if !self.eat(&TokenKind::Question) {
1459 return Ok(expr);
1460 }
1461 let consequent = self.parse_assignment_expression()?;
1462 self.expect(&TokenKind::Colon)?;
1463 let alternate = self.parse_assignment_expression()?;
1464 Ok(Expr {
1465 kind: ExprKind::Conditional {
1466 test: Box::new(expr),
1467 consequent: Box::new(consequent),
1468 alternate: Box::new(alternate),
1469 },
1470 span: self.span_from(start),
1471 })
1472 }
1473
1474 // ── Pratt expression parsing ────────────────────────────
1475
1476 fn parse_binary_expression(&mut self, min_bp: u8) -> Result<Expr, ParseError> {
1477 let start = self.start_span();
1478 let mut left = self.parse_unary_expression()?;
1479
1480 loop {
1481 let Some((op, left_bp, right_bp)) = self.peek_binary_op() else {
1482 break;
1483 };
1484 if left_bp < min_bp {
1485 break;
1486 }
1487 self.advance();
1488
1489 let right = self.parse_binary_expression(right_bp)?;
1490 let span = self.span_from(start);
1491
1492 left = match op {
1493 BinOrLogical::Binary(op) => Expr {
1494 kind: ExprKind::Binary {
1495 op,
1496 left: Box::new(left),
1497 right: Box::new(right),
1498 },
1499 span,
1500 },
1501 BinOrLogical::Logical(op) => Expr {
1502 kind: ExprKind::Logical {
1503 op,
1504 left: Box::new(left),
1505 right: Box::new(right),
1506 },
1507 span,
1508 },
1509 };
1510 }
1511
1512 Ok(left)
1513 }
1514
1515 fn parse_unary_expression(&mut self) -> Result<Expr, ParseError> {
1516 let start = self.start_span();
1517 match self.peek_kind() {
1518 TokenKind::Minus => {
1519 self.advance();
1520 let arg = self.parse_unary_expression()?;
1521 Ok(Expr {
1522 kind: ExprKind::Unary {
1523 op: UnaryOp::Minus,
1524 argument: Box::new(arg),
1525 },
1526 span: self.span_from(start),
1527 })
1528 }
1529 TokenKind::Plus => {
1530 self.advance();
1531 let arg = self.parse_unary_expression()?;
1532 Ok(Expr {
1533 kind: ExprKind::Unary {
1534 op: UnaryOp::Plus,
1535 argument: Box::new(arg),
1536 },
1537 span: self.span_from(start),
1538 })
1539 }
1540 TokenKind::Not => {
1541 self.advance();
1542 let arg = self.parse_unary_expression()?;
1543 Ok(Expr {
1544 kind: ExprKind::Unary {
1545 op: UnaryOp::Not,
1546 argument: Box::new(arg),
1547 },
1548 span: self.span_from(start),
1549 })
1550 }
1551 TokenKind::Tilde => {
1552 self.advance();
1553 let arg = self.parse_unary_expression()?;
1554 Ok(Expr {
1555 kind: ExprKind::Unary {
1556 op: UnaryOp::BitwiseNot,
1557 argument: Box::new(arg),
1558 },
1559 span: self.span_from(start),
1560 })
1561 }
1562 TokenKind::Typeof => {
1563 self.advance();
1564 let arg = self.parse_unary_expression()?;
1565 Ok(Expr {
1566 kind: ExprKind::Unary {
1567 op: UnaryOp::Typeof,
1568 argument: Box::new(arg),
1569 },
1570 span: self.span_from(start),
1571 })
1572 }
1573 TokenKind::Void => {
1574 self.advance();
1575 let arg = self.parse_unary_expression()?;
1576 Ok(Expr {
1577 kind: ExprKind::Unary {
1578 op: UnaryOp::Void,
1579 argument: Box::new(arg),
1580 },
1581 span: self.span_from(start),
1582 })
1583 }
1584 TokenKind::Delete => {
1585 self.advance();
1586 let arg = self.parse_unary_expression()?;
1587 Ok(Expr {
1588 kind: ExprKind::Unary {
1589 op: UnaryOp::Delete,
1590 argument: Box::new(arg),
1591 },
1592 span: self.span_from(start),
1593 })
1594 }
1595 TokenKind::PlusPlus => {
1596 self.advance();
1597 let arg = self.parse_unary_expression()?;
1598 Ok(Expr {
1599 kind: ExprKind::Update {
1600 op: UpdateOp::Increment,
1601 argument: Box::new(arg),
1602 prefix: true,
1603 },
1604 span: self.span_from(start),
1605 })
1606 }
1607 TokenKind::MinusMinus => {
1608 self.advance();
1609 let arg = self.parse_unary_expression()?;
1610 Ok(Expr {
1611 kind: ExprKind::Update {
1612 op: UpdateOp::Decrement,
1613 argument: Box::new(arg),
1614 prefix: true,
1615 },
1616 span: self.span_from(start),
1617 })
1618 }
1619 TokenKind::Await => {
1620 self.advance();
1621 let arg = self.parse_unary_expression()?;
1622 Ok(Expr {
1623 kind: ExprKind::Await(Box::new(arg)),
1624 span: self.span_from(start),
1625 })
1626 }
1627 _ => self.parse_postfix_expression(),
1628 }
1629 }
1630
1631 fn parse_postfix_expression(&mut self) -> Result<Expr, ParseError> {
1632 let start = self.start_span();
1633 let mut expr = self.parse_call_expression()?;
1634
1635 if !self.peek().preceded_by_newline {
1636 if matches!(self.peek_kind(), TokenKind::PlusPlus) {
1637 self.advance();
1638 expr = Expr {
1639 kind: ExprKind::Update {
1640 op: UpdateOp::Increment,
1641 argument: Box::new(expr),
1642 prefix: false,
1643 },
1644 span: self.span_from(start),
1645 };
1646 } else if matches!(self.peek_kind(), TokenKind::MinusMinus) {
1647 self.advance();
1648 expr = Expr {
1649 kind: ExprKind::Update {
1650 op: UpdateOp::Decrement,
1651 argument: Box::new(expr),
1652 prefix: false,
1653 },
1654 span: self.span_from(start),
1655 };
1656 }
1657 }
1658
1659 Ok(expr)
1660 }
1661
1662 fn parse_call_expression(&mut self) -> Result<Expr, ParseError> {
1663 let start = self.start_span();
1664
1665 if matches!(self.peek_kind(), TokenKind::New) {
1666 return self.parse_new_expression();
1667 }
1668
1669 let mut expr = self.parse_primary_expression()?;
1670
1671 loop {
1672 match self.peek_kind() {
1673 TokenKind::Dot => {
1674 self.advance();
1675 let prop_start = self.start_span();
1676 let name = self.expect_identifier()?;
1677 expr = Expr {
1678 kind: ExprKind::Member {
1679 object: Box::new(expr),
1680 property: Box::new(Expr {
1681 kind: ExprKind::Identifier(name),
1682 span: self.span_from(prop_start),
1683 }),
1684 computed: false,
1685 },
1686 span: self.span_from(start),
1687 };
1688 }
1689 TokenKind::LBracket => {
1690 self.advance();
1691 let prop = self.parse_expression()?;
1692 self.expect(&TokenKind::RBracket)?;
1693 expr = Expr {
1694 kind: ExprKind::Member {
1695 object: Box::new(expr),
1696 property: Box::new(prop),
1697 computed: true,
1698 },
1699 span: self.span_from(start),
1700 };
1701 }
1702 TokenKind::LParen => {
1703 let arguments = self.parse_arguments()?;
1704 expr = Expr {
1705 kind: ExprKind::Call {
1706 callee: Box::new(expr),
1707 arguments,
1708 },
1709 span: self.span_from(start),
1710 };
1711 }
1712 TokenKind::QuestionDot => {
1713 self.advance();
1714 // ?. can be followed by identifier, [expr], or (args)
1715 match self.peek_kind() {
1716 TokenKind::LBracket => {
1717 self.advance();
1718 let prop = self.parse_expression()?;
1719 self.expect(&TokenKind::RBracket)?;
1720 expr = Expr {
1721 kind: ExprKind::Member {
1722 object: Box::new(Expr {
1723 kind: ExprKind::OptionalChain {
1724 base: Box::new(expr.clone()),
1725 },
1726 span: self.span_from(start),
1727 }),
1728 property: Box::new(prop),
1729 computed: true,
1730 },
1731 span: self.span_from(start),
1732 };
1733 }
1734 TokenKind::LParen => {
1735 let arguments = self.parse_arguments()?;
1736 expr = Expr {
1737 kind: ExprKind::Call {
1738 callee: Box::new(Expr {
1739 kind: ExprKind::OptionalChain {
1740 base: Box::new(expr.clone()),
1741 },
1742 span: self.span_from(start),
1743 }),
1744 arguments,
1745 },
1746 span: self.span_from(start),
1747 };
1748 }
1749 _ => {
1750 let prop_start = self.start_span();
1751 let name = self.expect_identifier()?;
1752 expr = Expr {
1753 kind: ExprKind::Member {
1754 object: Box::new(Expr {
1755 kind: ExprKind::OptionalChain {
1756 base: Box::new(expr.clone()),
1757 },
1758 span: self.span_from(start),
1759 }),
1760 property: Box::new(Expr {
1761 kind: ExprKind::Identifier(name),
1762 span: self.span_from(prop_start),
1763 }),
1764 computed: false,
1765 },
1766 span: self.span_from(start),
1767 };
1768 }
1769 }
1770 }
1771 TokenKind::TemplateFull(_) | TokenKind::TemplateHead(_) => {
1772 let quasi = self.parse_template_literal()?;
1773 expr = Expr {
1774 kind: ExprKind::TaggedTemplate {
1775 tag: Box::new(expr),
1776 quasi: Box::new(quasi),
1777 },
1778 span: self.span_from(start),
1779 };
1780 }
1781 _ => break,
1782 }
1783 }
1784
1785 Ok(expr)
1786 }
1787
1788 fn parse_new_expression(&mut self) -> Result<Expr, ParseError> {
1789 let start = self.start_span();
1790 self.expect(&TokenKind::New)?;
1791
1792 // new new Foo() → new (new Foo())
1793 if matches!(self.peek_kind(), TokenKind::New) {
1794 let callee = self.parse_new_expression()?;
1795 return Ok(Expr {
1796 kind: ExprKind::New {
1797 callee: Box::new(callee),
1798 arguments: vec![],
1799 },
1800 span: self.span_from(start),
1801 });
1802 }
1803
1804 let callee = self.parse_primary_expression()?;
1805 // Allow member access on the callee
1806 let callee = self.parse_member_chain(start, callee)?;
1807 let arguments = if self.at(&TokenKind::LParen) {
1808 self.parse_arguments()?
1809 } else {
1810 vec![]
1811 };
1812 Ok(Expr {
1813 kind: ExprKind::New {
1814 callee: Box::new(callee),
1815 arguments,
1816 },
1817 span: self.span_from(start),
1818 })
1819 }
1820
1821 fn parse_member_chain(&mut self, start: SourcePos, mut expr: Expr) -> Result<Expr, ParseError> {
1822 loop {
1823 match self.peek_kind() {
1824 TokenKind::Dot => {
1825 self.advance();
1826 let prop_start = self.start_span();
1827 let name = self.expect_identifier()?;
1828 expr = Expr {
1829 kind: ExprKind::Member {
1830 object: Box::new(expr),
1831 property: Box::new(Expr {
1832 kind: ExprKind::Identifier(name),
1833 span: self.span_from(prop_start),
1834 }),
1835 computed: false,
1836 },
1837 span: self.span_from(start),
1838 };
1839 }
1840 TokenKind::LBracket => {
1841 self.advance();
1842 let prop = self.parse_expression()?;
1843 self.expect(&TokenKind::RBracket)?;
1844 expr = Expr {
1845 kind: ExprKind::Member {
1846 object: Box::new(expr),
1847 property: Box::new(prop),
1848 computed: true,
1849 },
1850 span: self.span_from(start),
1851 };
1852 }
1853 _ => break,
1854 }
1855 }
1856 Ok(expr)
1857 }
1858
1859 fn parse_left_hand_side_expression(&mut self) -> Result<Expr, ParseError> {
1860 self.parse_call_expression()
1861 }
1862
1863 fn parse_arguments(&mut self) -> Result<Vec<Expr>, ParseError> {
1864 self.expect(&TokenKind::LParen)?;
1865 let mut args = Vec::new();
1866 while !self.at(&TokenKind::RParen) && !self.at_eof() {
1867 if self.at(&TokenKind::Ellipsis) {
1868 let start = self.start_span();
1869 self.advance();
1870 let arg = self.parse_assignment_expression()?;
1871 args.push(Expr {
1872 kind: ExprKind::Spread(Box::new(arg)),
1873 span: self.span_from(start),
1874 });
1875 } else {
1876 args.push(self.parse_assignment_expression()?);
1877 }
1878 if !self.eat(&TokenKind::Comma) {
1879 break;
1880 }
1881 }
1882 self.expect(&TokenKind::RParen)?;
1883 Ok(args)
1884 }
1885
1886 // ── Primary expressions ─────────────────────────────────
1887
1888 fn parse_primary_expression(&mut self) -> Result<Expr, ParseError> {
1889 let start = self.start_span();
1890 match self.peek_kind().clone() {
1891 TokenKind::Number(n) => {
1892 self.advance();
1893 Ok(Expr {
1894 kind: ExprKind::Number(n),
1895 span: self.span_from(start),
1896 })
1897 }
1898 TokenKind::String(s) => {
1899 self.advance();
1900 Ok(Expr {
1901 kind: ExprKind::String(s),
1902 span: self.span_from(start),
1903 })
1904 }
1905 TokenKind::True => {
1906 self.advance();
1907 Ok(Expr {
1908 kind: ExprKind::Bool(true),
1909 span: self.span_from(start),
1910 })
1911 }
1912 TokenKind::False => {
1913 self.advance();
1914 Ok(Expr {
1915 kind: ExprKind::Bool(false),
1916 span: self.span_from(start),
1917 })
1918 }
1919 TokenKind::Null => {
1920 self.advance();
1921 Ok(Expr {
1922 kind: ExprKind::Null,
1923 span: self.span_from(start),
1924 })
1925 }
1926 TokenKind::This => {
1927 self.advance();
1928 Ok(Expr {
1929 kind: ExprKind::This,
1930 span: self.span_from(start),
1931 })
1932 }
1933 TokenKind::Identifier(name) => {
1934 self.advance();
1935 Ok(Expr {
1936 kind: ExprKind::Identifier(name),
1937 span: self.span_from(start),
1938 })
1939 }
1940 TokenKind::LParen => self.parse_parenthesized_expression(),
1941 TokenKind::LBracket => self.parse_array_expression(),
1942 TokenKind::LBrace => self.parse_object_expression(),
1943 TokenKind::Function => self.parse_function_expression(),
1944 TokenKind::Class => self.parse_class_expression(),
1945 TokenKind::Async => {
1946 // async function expression
1947 if matches!(self.peek_ahead(1), TokenKind::Function)
1948 && !self.tokens[self.pos + 1].preceded_by_newline
1949 {
1950 return self.parse_async_function_expression();
1951 }
1952 // Otherwise treat 'async' as an identifier
1953 self.advance();
1954 Ok(Expr {
1955 kind: ExprKind::Identifier("async".into()),
1956 span: self.span_from(start),
1957 })
1958 }
1959 TokenKind::TemplateFull(_) | TokenKind::TemplateHead(_) => {
1960 self.parse_template_literal()
1961 }
1962 TokenKind::RegExp { pattern, flags } => {
1963 self.advance();
1964 Ok(Expr {
1965 kind: ExprKind::RegExp { pattern, flags },
1966 span: self.span_from(start),
1967 })
1968 }
1969 TokenKind::Yield => {
1970 self.advance();
1971 let delegate = self.eat(&TokenKind::Star);
1972 let argument = if !self.peek().preceded_by_newline
1973 && !matches!(
1974 self.peek_kind(),
1975 TokenKind::Semicolon
1976 | TokenKind::RBrace
1977 | TokenKind::RParen
1978 | TokenKind::RBracket
1979 | TokenKind::Colon
1980 | TokenKind::Comma
1981 | TokenKind::Eof
1982 ) {
1983 Some(Box::new(self.parse_assignment_expression()?))
1984 } else {
1985 None
1986 };
1987 Ok(Expr {
1988 kind: ExprKind::Yield { argument, delegate },
1989 span: self.span_from(start),
1990 })
1991 }
1992 TokenKind::Super => {
1993 self.advance();
1994 Ok(Expr {
1995 kind: ExprKind::Identifier("super".into()),
1996 span: self.span_from(start),
1997 })
1998 }
1999 TokenKind::Import => {
2000 // import() call expression
2001 self.advance();
2002 Ok(Expr {
2003 kind: ExprKind::Identifier("import".into()),
2004 span: self.span_from(start),
2005 })
2006 }
2007 _ => Err(self.error(format!("unexpected token {:?}", self.peek_kind()))),
2008 }
2009 }
2010
2011 fn parse_parenthesized_expression(&mut self) -> Result<Expr, ParseError> {
2012 let start = self.start_span();
2013 self.expect(&TokenKind::LParen)?;
2014
2015 // Empty parens: `() => ...`
2016 if self.at(&TokenKind::RParen) {
2017 self.advance();
2018 // Must be arrow
2019 if !matches!(self.peek_kind(), TokenKind::Arrow) {
2020 return Err(self.error("unexpected empty parentheses".into()));
2021 }
2022 // Arrow will be handled by caller
2023 return Ok(Expr {
2024 kind: ExprKind::Sequence(vec![]),
2025 span: self.span_from(start),
2026 });
2027 }
2028
2029 // `(...rest) => ...`
2030 if self.at(&TokenKind::Ellipsis) {
2031 // This must be an arrow parameter list with rest
2032 let rest_start = self.start_span();
2033 self.advance();
2034 let rest_pat = self.parse_binding_pattern()?;
2035 self.expect(&TokenKind::RParen)?;
2036 // Must be followed by =>
2037 if !matches!(self.peek_kind(), TokenKind::Arrow) {
2038 return Err(self.error("expected '=>'".into()));
2039 }
2040 let _ = rest_pat; // Will be handled as pattern
2041 // Return a marker that the arrow handler will convert
2042 return Ok(Expr {
2043 kind: ExprKind::Spread(Box::new(Expr {
2044 kind: match rest_pat.kind {
2045 PatternKind::Identifier(name) => ExprKind::Identifier(name),
2046 _ => {
2047 return Err(ParseError {
2048 message: "complex rest pattern in arrow".into(),
2049 pos: rest_start,
2050 })
2051 }
2052 },
2053 span: rest_pat.span,
2054 })),
2055 span: self.span_from(start),
2056 });
2057 }
2058
2059 let expr = self.parse_expression()?;
2060 self.expect(&TokenKind::RParen)?;
2061 Ok(expr)
2062 }
2063
2064 fn parse_array_expression(&mut self) -> Result<Expr, ParseError> {
2065 let start = self.start_span();
2066 self.expect(&TokenKind::LBracket)?;
2067 let mut elements = Vec::new();
2068 while !self.at(&TokenKind::RBracket) && !self.at_eof() {
2069 if self.eat(&TokenKind::Comma) {
2070 elements.push(None);
2071 continue;
2072 }
2073 if self.at(&TokenKind::Ellipsis) {
2074 let spread_start = self.start_span();
2075 self.advance();
2076 let arg = self.parse_assignment_expression()?;
2077 elements.push(Some(ArrayElement::Spread(Expr {
2078 kind: ExprKind::Spread(Box::new(arg)),
2079 span: self.span_from(spread_start),
2080 })));
2081 } else {
2082 let elem = self.parse_assignment_expression()?;
2083 elements.push(Some(ArrayElement::Expr(elem)));
2084 }
2085 if !self.eat(&TokenKind::Comma) {
2086 break;
2087 }
2088 }
2089 self.expect(&TokenKind::RBracket)?;
2090 Ok(Expr {
2091 kind: ExprKind::Array(elements),
2092 span: self.span_from(start),
2093 })
2094 }
2095
2096 fn parse_object_expression(&mut self) -> Result<Expr, ParseError> {
2097 let start = self.start_span();
2098 self.expect(&TokenKind::LBrace)?;
2099 let mut properties = Vec::new();
2100 while !self.at(&TokenKind::RBrace) && !self.at_eof() {
2101 let prop = self.parse_object_property()?;
2102 properties.push(prop);
2103 if !self.eat(&TokenKind::Comma) {
2104 break;
2105 }
2106 }
2107 self.expect(&TokenKind::RBrace)?;
2108 Ok(Expr {
2109 kind: ExprKind::Object(properties),
2110 span: self.span_from(start),
2111 })
2112 }
2113
2114 fn parse_object_property(&mut self) -> Result<Property, ParseError> {
2115 let prop_start = self.start_span();
2116
2117 // Spread: `...expr`
2118 if self.at(&TokenKind::Ellipsis) {
2119 self.advance();
2120 let arg = self.parse_assignment_expression()?;
2121 return Ok(Property {
2122 key: PropertyKey::Identifier("".into()),
2123 value: Some(arg),
2124 kind: PropertyKind::Init,
2125 computed: false,
2126 shorthand: false,
2127 method: false,
2128 span: self.span_from(prop_start),
2129 });
2130 }
2131
2132 // Getter/setter: `get name() {}` or `set name(v) {}`
2133 if let TokenKind::Identifier(ref name) = self.peek_kind().clone() {
2134 if (name == "get" || name == "set")
2135 && !matches!(
2136 self.peek_ahead(1),
2137 TokenKind::Colon
2138 | TokenKind::Comma
2139 | TokenKind::RBrace
2140 | TokenKind::LParen
2141 | TokenKind::Assign
2142 )
2143 {
2144 let kind = if name == "get" {
2145 PropertyKind::Get
2146 } else {
2147 PropertyKind::Set
2148 };
2149 self.advance();
2150 let (key, computed) = self.parse_property_name()?;
2151 let (params, body) = self.parse_function_params_and_body()?;
2152 return Ok(Property {
2153 key,
2154 value: Some(Expr {
2155 kind: ExprKind::Function(FunctionDef {
2156 id: None,
2157 params,
2158 body,
2159 is_async: false,
2160 is_generator: false,
2161 }),
2162 span: self.span_from(prop_start),
2163 }),
2164 kind,
2165 computed,
2166 shorthand: false,
2167 method: true,
2168 span: self.span_from(prop_start),
2169 });
2170 }
2171 }
2172
2173 // Generator method: `*name() {}`
2174 if self.eat(&TokenKind::Star) {
2175 let (key, computed) = self.parse_property_name()?;
2176 let (params, body) = self.parse_function_params_and_body()?;
2177 return Ok(Property {
2178 key,
2179 value: Some(Expr {
2180 kind: ExprKind::Function(FunctionDef {
2181 id: None,
2182 params,
2183 body,
2184 is_async: false,
2185 is_generator: true,
2186 }),
2187 span: self.span_from(prop_start),
2188 }),
2189 kind: PropertyKind::Init,
2190 computed,
2191 shorthand: false,
2192 method: true,
2193 span: self.span_from(prop_start),
2194 });
2195 }
2196
2197 // Async method: `async name() {}`
2198 let is_async = if matches!(self.peek_kind(), TokenKind::Async)
2199 && !matches!(
2200 self.peek_ahead(1),
2201 TokenKind::Colon | TokenKind::Comma | TokenKind::RBrace | TokenKind::Assign
2202 )
2203 && !self
2204 .tokens
2205 .get(self.pos + 1)
2206 .is_none_or(|t| t.preceded_by_newline)
2207 {
2208 self.advance();
2209 true
2210 } else {
2211 false
2212 };
2213
2214 let is_generator = is_async && self.eat(&TokenKind::Star);
2215
2216 let (key, computed) = self.parse_property_name()?;
2217
2218 // Method shorthand: `name() {}` or `name(params) {}`
2219 if self.at(&TokenKind::LParen) {
2220 let (params, body) = self.parse_function_params_and_body()?;
2221 return Ok(Property {
2222 key,
2223 value: Some(Expr {
2224 kind: ExprKind::Function(FunctionDef {
2225 id: None,
2226 params,
2227 body,
2228 is_async,
2229 is_generator,
2230 }),
2231 span: self.span_from(prop_start),
2232 }),
2233 kind: PropertyKind::Init,
2234 computed,
2235 shorthand: false,
2236 method: true,
2237 span: self.span_from(prop_start),
2238 });
2239 }
2240
2241 // Shorthand: `{ name }` or `{ name = default }`
2242 if !computed
2243 && matches!(
2244 self.peek_kind(),
2245 TokenKind::Comma | TokenKind::RBrace | TokenKind::Assign
2246 )
2247 {
2248 let name = match &key {
2249 PropertyKey::Identifier(n) => n.clone(),
2250 _ => return Err(self.error("expected identifier for shorthand property".into())),
2251 };
2252 let value = if self.eat(&TokenKind::Assign) {
2253 let default = self.parse_assignment_expression()?;
2254 Some(Expr {
2255 kind: ExprKind::Assignment {
2256 op: AssignOp::Assign,
2257 left: Box::new(Expr {
2258 kind: ExprKind::Identifier(name.clone()),
2259 span: self.span_from(prop_start),
2260 }),
2261 right: Box::new(default),
2262 },
2263 span: self.span_from(prop_start),
2264 })
2265 } else {
2266 Some(Expr {
2267 kind: ExprKind::Identifier(name),
2268 span: self.span_from(prop_start),
2269 })
2270 };
2271 return Ok(Property {
2272 key,
2273 value,
2274 kind: PropertyKind::Init,
2275 computed,
2276 shorthand: true,
2277 method: false,
2278 span: self.span_from(prop_start),
2279 });
2280 }
2281
2282 // Regular: `key: value`
2283 self.expect(&TokenKind::Colon)?;
2284 let value = self.parse_assignment_expression()?;
2285 Ok(Property {
2286 key,
2287 value: Some(value),
2288 kind: PropertyKind::Init,
2289 computed,
2290 shorthand: false,
2291 method: false,
2292 span: self.span_from(prop_start),
2293 })
2294 }
2295
2296 fn parse_property_name(&mut self) -> Result<(PropertyKey, bool), ParseError> {
2297 match self.peek_kind().clone() {
2298 TokenKind::Identifier(name) => {
2299 self.advance();
2300 Ok((PropertyKey::Identifier(name), false))
2301 }
2302 TokenKind::String(s) => {
2303 self.advance();
2304 Ok((PropertyKey::String(s), false))
2305 }
2306 TokenKind::Number(n) => {
2307 self.advance();
2308 Ok((PropertyKey::Number(n), false))
2309 }
2310 TokenKind::LBracket => {
2311 self.advance();
2312 let expr = self.parse_assignment_expression()?;
2313 self.expect(&TokenKind::RBracket)?;
2314 Ok((PropertyKey::Computed(expr), true))
2315 }
2316 // Keywords can also be property names
2317 _ if is_keyword(self.peek_kind()) => {
2318 let name = format!("{}", self.peek_kind());
2319 self.advance();
2320 Ok((PropertyKey::Identifier(name), false))
2321 }
2322 _ => Err(self.error(format!(
2323 "expected property name, found {:?}",
2324 self.peek_kind()
2325 ))),
2326 }
2327 }
2328
2329 fn parse_function_expression(&mut self) -> Result<Expr, ParseError> {
2330 let start = self.start_span();
2331 self.expect(&TokenKind::Function)?;
2332 let is_generator = self.eat(&TokenKind::Star);
2333 let id = if let TokenKind::Identifier(_) = self.peek_kind() {
2334 Some(self.expect_identifier()?)
2335 } else {
2336 None
2337 };
2338 let (params, body) = self.parse_function_params_and_body()?;
2339 Ok(Expr {
2340 kind: ExprKind::Function(FunctionDef {
2341 id,
2342 params,
2343 body,
2344 is_async: false,
2345 is_generator,
2346 }),
2347 span: self.span_from(start),
2348 })
2349 }
2350
2351 fn parse_async_function_expression(&mut self) -> Result<Expr, ParseError> {
2352 let start = self.start_span();
2353 self.expect(&TokenKind::Async)?;
2354 self.expect(&TokenKind::Function)?;
2355 let is_generator = self.eat(&TokenKind::Star);
2356 let id = if let TokenKind::Identifier(_) = self.peek_kind() {
2357 Some(self.expect_identifier()?)
2358 } else {
2359 None
2360 };
2361 let (params, body) = self.parse_function_params_and_body()?;
2362 Ok(Expr {
2363 kind: ExprKind::Function(FunctionDef {
2364 id,
2365 params,
2366 body,
2367 is_async: true,
2368 is_generator,
2369 }),
2370 span: self.span_from(start),
2371 })
2372 }
2373
2374 fn parse_class_expression(&mut self) -> Result<Expr, ParseError> {
2375 let start = self.start_span();
2376 let class_def = self.parse_class(false)?;
2377 Ok(Expr {
2378 kind: ExprKind::Class(class_def),
2379 span: self.span_from(start),
2380 })
2381 }
2382
2383 fn parse_template_literal(&mut self) -> Result<Expr, ParseError> {
2384 let start = self.start_span();
2385 match self.peek_kind().clone() {
2386 TokenKind::TemplateFull(s) => {
2387 self.advance();
2388 Ok(Expr {
2389 kind: ExprKind::TemplateLiteral {
2390 quasis: vec![s],
2391 expressions: vec![],
2392 },
2393 span: self.span_from(start),
2394 })
2395 }
2396 TokenKind::TemplateHead(s) => {
2397 self.advance();
2398 let mut quasis = vec![s];
2399 let mut expressions = Vec::new();
2400 loop {
2401 expressions.push(self.parse_expression()?);
2402 match self.peek_kind().clone() {
2403 TokenKind::TemplateMiddle(s) => {
2404 self.advance();
2405 quasis.push(s);
2406 }
2407 TokenKind::TemplateTail(s) => {
2408 self.advance();
2409 quasis.push(s);
2410 break;
2411 }
2412 _ => {
2413 return Err(self.error("expected template continuation or tail".into()));
2414 }
2415 }
2416 }
2417 Ok(Expr {
2418 kind: ExprKind::TemplateLiteral {
2419 quasis,
2420 expressions,
2421 },
2422 span: self.span_from(start),
2423 })
2424 }
2425 _ => Err(self.error("expected template literal".into())),
2426 }
2427 }
2428
2429 // ── Operator tables ─────────────────────────────────────
2430
2431 fn peek_binary_op(&self) -> Option<(BinOrLogical, u8, u8)> {
2432 let kind = self.peek_kind();
2433 let (op, left_bp, right_bp) = match kind {
2434 TokenKind::Or => (BinOrLogical::Logical(LogicalOp::Or), 2, 3),
2435 TokenKind::And => (BinOrLogical::Logical(LogicalOp::And), 4, 5),
2436 TokenKind::Nullish => (BinOrLogical::Logical(LogicalOp::Nullish), 6, 7),
2437 TokenKind::Pipe => (BinOrLogical::Binary(BinaryOp::BitOr), 8, 9),
2438 TokenKind::Caret => (BinOrLogical::Binary(BinaryOp::BitXor), 10, 11),
2439 TokenKind::Amp => (BinOrLogical::Binary(BinaryOp::BitAnd), 12, 13),
2440 TokenKind::Eq => (BinOrLogical::Binary(BinaryOp::Eq), 14, 15),
2441 TokenKind::Ne => (BinOrLogical::Binary(BinaryOp::Ne), 14, 15),
2442 TokenKind::StrictEq => (BinOrLogical::Binary(BinaryOp::StrictEq), 14, 15),
2443 TokenKind::StrictNe => (BinOrLogical::Binary(BinaryOp::StrictNe), 14, 15),
2444 TokenKind::Lt => (BinOrLogical::Binary(BinaryOp::Lt), 16, 17),
2445 TokenKind::Gt => (BinOrLogical::Binary(BinaryOp::Gt), 16, 17),
2446 TokenKind::Le => (BinOrLogical::Binary(BinaryOp::Le), 16, 17),
2447 TokenKind::Ge => (BinOrLogical::Binary(BinaryOp::Ge), 16, 17),
2448 TokenKind::Instanceof => (BinOrLogical::Binary(BinaryOp::Instanceof), 16, 17),
2449 TokenKind::In if self.allow_in => (BinOrLogical::Binary(BinaryOp::In), 16, 17),
2450 TokenKind::Shl => (BinOrLogical::Binary(BinaryOp::Shl), 18, 19),
2451 TokenKind::Shr => (BinOrLogical::Binary(BinaryOp::Shr), 18, 19),
2452 TokenKind::Ushr => (BinOrLogical::Binary(BinaryOp::Ushr), 18, 19),
2453 TokenKind::Plus => (BinOrLogical::Binary(BinaryOp::Add), 20, 21),
2454 TokenKind::Minus => (BinOrLogical::Binary(BinaryOp::Sub), 20, 21),
2455 TokenKind::Star => (BinOrLogical::Binary(BinaryOp::Mul), 22, 23),
2456 TokenKind::Slash => (BinOrLogical::Binary(BinaryOp::Div), 22, 23),
2457 TokenKind::Percent => (BinOrLogical::Binary(BinaryOp::Rem), 22, 23),
2458 TokenKind::Exp => (BinOrLogical::Binary(BinaryOp::Exp), 25, 24), // right-assoc
2459 _ => return None,
2460 };
2461 Some((op, left_bp, right_bp))
2462 }
2463
2464 fn peek_assign_op(&self) -> Option<AssignOp> {
2465 match self.peek_kind() {
2466 TokenKind::Assign => Some(AssignOp::Assign),
2467 TokenKind::PlusAssign => Some(AssignOp::AddAssign),
2468 TokenKind::MinusAssign => Some(AssignOp::SubAssign),
2469 TokenKind::StarAssign => Some(AssignOp::MulAssign),
2470 TokenKind::SlashAssign => Some(AssignOp::DivAssign),
2471 TokenKind::PercentAssign => Some(AssignOp::RemAssign),
2472 TokenKind::ExpAssign => Some(AssignOp::ExpAssign),
2473 TokenKind::ShlAssign => Some(AssignOp::ShlAssign),
2474 TokenKind::ShrAssign => Some(AssignOp::ShrAssign),
2475 TokenKind::UshrAssign => Some(AssignOp::UshrAssign),
2476 TokenKind::AmpAssign => Some(AssignOp::BitAndAssign),
2477 TokenKind::PipeAssign => Some(AssignOp::BitOrAssign),
2478 TokenKind::CaretAssign => Some(AssignOp::BitXorAssign),
2479 TokenKind::AndAssign => Some(AssignOp::AndAssign),
2480 TokenKind::OrAssign => Some(AssignOp::OrAssign),
2481 TokenKind::NullishAssign => Some(AssignOp::NullishAssign),
2482 _ => None,
2483 }
2484 }
2485
2486 // ── Expression ↔ Pattern conversion ─────────────────────
2487
2488 fn expr_to_pattern(&self, expr: &Expr) -> Result<Pattern, ParseError> {
2489 let span = expr.span;
2490 match &expr.kind {
2491 ExprKind::Identifier(name) => Ok(Pattern {
2492 kind: PatternKind::Identifier(name.clone()),
2493 span,
2494 }),
2495 ExprKind::Array(elements) => {
2496 let mut pats = Vec::new();
2497 let mut rest = None;
2498 for elem in elements {
2499 match elem {
2500 None => pats.push(None),
2501 Some(ArrayElement::Spread(e)) => {
2502 if let ExprKind::Spread(inner) = &e.kind {
2503 rest = Some(Box::new(self.expr_to_pattern(inner)?));
2504 } else {
2505 rest = Some(Box::new(self.expr_to_pattern(e)?));
2506 }
2507 }
2508 Some(ArrayElement::Expr(e)) => {
2509 pats.push(Some(self.expr_to_pattern(e)?));
2510 }
2511 }
2512 }
2513 Ok(Pattern {
2514 kind: PatternKind::Array {
2515 elements: pats,
2516 rest,
2517 },
2518 span,
2519 })
2520 }
2521 ExprKind::Object(properties) => {
2522 let mut pats = Vec::new();
2523 let mut rest = None;
2524 for prop in properties {
2525 if prop.key == PropertyKey::Identifier("".into()) {
2526 if let Some(val) = &prop.value {
2527 // Spread property
2528 rest = Some(Box::new(self.expr_to_pattern(val)?));
2529 }
2530 continue;
2531 }
2532 let value = if let Some(val) = &prop.value {
2533 self.expr_to_pattern(val)?
2534 } else {
2535 continue;
2536 };
2537 pats.push(ObjectPatternProp {
2538 key: prop.key.clone(),
2539 value,
2540 computed: prop.computed,
2541 shorthand: prop.shorthand,
2542 span: prop.span,
2543 });
2544 }
2545 Ok(Pattern {
2546 kind: PatternKind::Object {
2547 properties: pats,
2548 rest,
2549 },
2550 span,
2551 })
2552 }
2553 ExprKind::Assignment {
2554 op: AssignOp::Assign,
2555 left,
2556 right,
2557 } => {
2558 let left_pat = self.expr_to_pattern(left)?;
2559 Ok(Pattern {
2560 kind: PatternKind::Assign {
2561 left: Box::new(left_pat),
2562 right: right.clone(),
2563 },
2564 span,
2565 })
2566 }
2567 ExprKind::Spread(inner) => self.expr_to_pattern(inner),
2568 _ => Err(ParseError {
2569 message: "invalid destructuring pattern".into(),
2570 pos: span.start,
2571 }),
2572 }
2573 }
2574
2575 fn expr_to_params(&self, expr: &Expr) -> Result<Vec<Pattern>, ParseError> {
2576 match &expr.kind {
2577 ExprKind::Sequence(exprs) if exprs.is_empty() => Ok(vec![]),
2578 ExprKind::Sequence(exprs) => {
2579 let mut params = Vec::new();
2580 for e in exprs {
2581 params.push(self.expr_to_pattern(e)?);
2582 }
2583 Ok(params)
2584 }
2585 ExprKind::Spread(inner) => {
2586 let pat = self.expr_to_pattern(inner)?;
2587 Ok(vec![pat])
2588 }
2589 _ => {
2590 // Single expression as single parameter
2591 Ok(vec![self.expr_to_pattern(expr)?])
2592 }
2593 }
2594 }
2595}
2596
2597// ── Helpers ─────────────────────────────────────────────────
2598
2599/// Distinguishes binary operators from logical operators in Pratt parsing.
2600enum BinOrLogical {
2601 Binary(BinaryOp),
2602 Logical(LogicalOp),
2603}
2604
2605/// Returns true if the token kind is a keyword (used for property name parsing).
2606fn is_keyword(kind: &TokenKind) -> bool {
2607 matches!(
2608 kind,
2609 TokenKind::Await
2610 | TokenKind::Break
2611 | TokenKind::Case
2612 | TokenKind::Catch
2613 | TokenKind::Class
2614 | TokenKind::Const
2615 | TokenKind::Continue
2616 | TokenKind::Debugger
2617 | TokenKind::Default
2618 | TokenKind::Delete
2619 | TokenKind::Do
2620 | TokenKind::Else
2621 | TokenKind::Export
2622 | TokenKind::Extends
2623 | TokenKind::Finally
2624 | TokenKind::For
2625 | TokenKind::Function
2626 | TokenKind::If
2627 | TokenKind::Import
2628 | TokenKind::In
2629 | TokenKind::Instanceof
2630 | TokenKind::Let
2631 | TokenKind::New
2632 | TokenKind::Of
2633 | TokenKind::Return
2634 | TokenKind::Static
2635 | TokenKind::Super
2636 | TokenKind::Switch
2637 | TokenKind::This
2638 | TokenKind::Throw
2639 | TokenKind::Try
2640 | TokenKind::Typeof
2641 | TokenKind::Var
2642 | TokenKind::Void
2643 | TokenKind::While
2644 | TokenKind::With
2645 | TokenKind::Yield
2646 | TokenKind::Async
2647 | TokenKind::True
2648 | TokenKind::False
2649 | TokenKind::Null
2650 )
2651}
2652
2653// ── Tests ───────────────────────────────────────────────────
2654
2655#[cfg(test)]
2656mod tests {
2657 use super::*;
2658
2659 fn parse(src: &str) -> Program {
2660 Parser::parse(src).unwrap()
2661 }
2662
2663 fn parse_expr(src: &str) -> Expr {
2664 let prog = parse(src);
2665 match &prog.body[0].kind {
2666 StmtKind::Expr(e) => e.clone(),
2667 _ => panic!("expected expression statement, got {:?}", prog.body[0].kind),
2668 }
2669 }
2670
2671 fn parse_stmt(src: &str) -> Stmt {
2672 let prog = parse(src);
2673 prog.body[0].clone()
2674 }
2675
2676 // ── Literals ────────────────────────────────────────
2677
2678 #[test]
2679 fn test_number_literal() {
2680 let expr = parse_expr("42");
2681 assert_eq!(expr.kind, ExprKind::Number(42.0));
2682 }
2683
2684 #[test]
2685 fn test_string_literal() {
2686 let expr = parse_expr("\"hello\"");
2687 assert_eq!(expr.kind, ExprKind::String("hello".into()));
2688 }
2689
2690 #[test]
2691 fn test_boolean_literals() {
2692 assert_eq!(parse_expr("true").kind, ExprKind::Bool(true));
2693 assert_eq!(parse_expr("false").kind, ExprKind::Bool(false));
2694 }
2695
2696 #[test]
2697 fn test_null_literal() {
2698 assert_eq!(parse_expr("null").kind, ExprKind::Null);
2699 }
2700
2701 #[test]
2702 fn test_this() {
2703 assert_eq!(parse_expr("this").kind, ExprKind::This);
2704 }
2705
2706 #[test]
2707 fn test_identifier() {
2708 assert_eq!(parse_expr("foo").kind, ExprKind::Identifier("foo".into()));
2709 }
2710
2711 #[test]
2712 fn test_regexp() {
2713 let expr = parse_expr("x = /test/gi");
2714 match &expr.kind {
2715 ExprKind::Assignment { right, .. } => {
2716 assert_eq!(
2717 right.kind,
2718 ExprKind::RegExp {
2719 pattern: "test".into(),
2720 flags: "gi".into()
2721 }
2722 );
2723 }
2724 _ => panic!("expected assignment"),
2725 }
2726 }
2727
2728 // ── Binary expressions ──────────────────────────────
2729
2730 #[test]
2731 fn test_addition() {
2732 let expr = parse_expr("1 + 2");
2733 match expr.kind {
2734 ExprKind::Binary { op, left, right } => {
2735 assert_eq!(op, BinaryOp::Add);
2736 assert_eq!(left.kind, ExprKind::Number(1.0));
2737 assert_eq!(right.kind, ExprKind::Number(2.0));
2738 }
2739 _ => panic!("expected binary"),
2740 }
2741 }
2742
2743 #[test]
2744 fn test_precedence() {
2745 // 1 + 2 * 3 should be 1 + (2 * 3)
2746 let expr = parse_expr("1 + 2 * 3");
2747 match expr.kind {
2748 ExprKind::Binary {
2749 op: BinaryOp::Add,
2750 left,
2751 right,
2752 } => {
2753 assert_eq!(left.kind, ExprKind::Number(1.0));
2754 match right.kind {
2755 ExprKind::Binary {
2756 op: BinaryOp::Mul, ..
2757 } => {}
2758 _ => panic!("expected multiply on right"),
2759 }
2760 }
2761 _ => panic!("expected binary add"),
2762 }
2763 }
2764
2765 #[test]
2766 fn test_exponentiation_right_assoc() {
2767 // 2 ** 3 ** 2 should be 2 ** (3 ** 2)
2768 let expr = parse_expr("2 ** 3 ** 2");
2769 match expr.kind {
2770 ExprKind::Binary {
2771 op: BinaryOp::Exp,
2772 left,
2773 right,
2774 } => {
2775 assert_eq!(left.kind, ExprKind::Number(2.0));
2776 match right.kind {
2777 ExprKind::Binary {
2778 op: BinaryOp::Exp, ..
2779 } => {}
2780 _ => panic!("expected exp on right"),
2781 }
2782 }
2783 _ => panic!("expected binary exp"),
2784 }
2785 }
2786
2787 #[test]
2788 fn test_comparison() {
2789 let expr = parse_expr("a === b");
2790 match expr.kind {
2791 ExprKind::Binary {
2792 op: BinaryOp::StrictEq,
2793 ..
2794 } => {}
2795 _ => panic!("expected strict eq"),
2796 }
2797 }
2798
2799 #[test]
2800 fn test_logical_operators() {
2801 let expr = parse_expr("a && b || c");
2802 // Should be (a && b) || c because && has higher precedence
2803 match expr.kind {
2804 ExprKind::Logical {
2805 op: LogicalOp::Or, ..
2806 } => {}
2807 _ => panic!("expected logical or"),
2808 }
2809 }
2810
2811 // ── Unary expressions ───────────────────────────────
2812
2813 #[test]
2814 fn test_unary_minus() {
2815 let expr = parse_expr("-x");
2816 match expr.kind {
2817 ExprKind::Unary {
2818 op: UnaryOp::Minus,
2819 argument,
2820 } => {
2821 assert_eq!(argument.kind, ExprKind::Identifier("x".into()));
2822 }
2823 _ => panic!("expected unary minus"),
2824 }
2825 }
2826
2827 #[test]
2828 fn test_typeof() {
2829 let expr = parse_expr("typeof x");
2830 match expr.kind {
2831 ExprKind::Unary {
2832 op: UnaryOp::Typeof,
2833 ..
2834 } => {}
2835 _ => panic!("expected typeof"),
2836 }
2837 }
2838
2839 #[test]
2840 fn test_prefix_increment() {
2841 let expr = parse_expr("++x");
2842 match expr.kind {
2843 ExprKind::Update {
2844 op: UpdateOp::Increment,
2845 prefix: true,
2846 ..
2847 } => {}
2848 _ => panic!("expected prefix increment"),
2849 }
2850 }
2851
2852 #[test]
2853 fn test_postfix_decrement() {
2854 let expr = parse_expr("x--");
2855 match expr.kind {
2856 ExprKind::Update {
2857 op: UpdateOp::Decrement,
2858 prefix: false,
2859 ..
2860 } => {}
2861 _ => panic!("expected postfix decrement"),
2862 }
2863 }
2864
2865 // ── Conditional expression ──────────────────────────
2866
2867 #[test]
2868 fn test_ternary() {
2869 let expr = parse_expr("a ? b : c");
2870 match expr.kind {
2871 ExprKind::Conditional {
2872 test,
2873 consequent,
2874 alternate,
2875 } => {
2876 assert_eq!(test.kind, ExprKind::Identifier("a".into()));
2877 assert_eq!(consequent.kind, ExprKind::Identifier("b".into()));
2878 assert_eq!(alternate.kind, ExprKind::Identifier("c".into()));
2879 }
2880 _ => panic!("expected conditional"),
2881 }
2882 }
2883
2884 // ── Assignment ──────────────────────────────────────
2885
2886 #[test]
2887 fn test_assignment() {
2888 let expr = parse_expr("x = 42");
2889 match expr.kind {
2890 ExprKind::Assignment {
2891 op: AssignOp::Assign,
2892 left,
2893 right,
2894 } => {
2895 assert_eq!(left.kind, ExprKind::Identifier("x".into()));
2896 assert_eq!(right.kind, ExprKind::Number(42.0));
2897 }
2898 _ => panic!("expected assignment"),
2899 }
2900 }
2901
2902 #[test]
2903 fn test_compound_assignment() {
2904 let expr = parse_expr("x += 1");
2905 match expr.kind {
2906 ExprKind::Assignment {
2907 op: AssignOp::AddAssign,
2908 ..
2909 } => {}
2910 _ => panic!("expected add-assign"),
2911 }
2912 }
2913
2914 // ── Member expressions ──────────────────────────────
2915
2916 #[test]
2917 fn test_dot_access() {
2918 let expr = parse_expr("a.b");
2919 match expr.kind {
2920 ExprKind::Member {
2921 computed: false, ..
2922 } => {}
2923 _ => panic!("expected member access"),
2924 }
2925 }
2926
2927 #[test]
2928 fn test_bracket_access() {
2929 let expr = parse_expr("a[0]");
2930 match expr.kind {
2931 ExprKind::Member { computed: true, .. } => {}
2932 _ => panic!("expected computed member"),
2933 }
2934 }
2935
2936 // ── Call expressions ────────────────────────────────
2937
2938 #[test]
2939 fn test_function_call() {
2940 let expr = parse_expr("foo(1, 2)");
2941 match expr.kind {
2942 ExprKind::Call {
2943 callee, arguments, ..
2944 } => {
2945 assert_eq!(callee.kind, ExprKind::Identifier("foo".into()));
2946 assert_eq!(arguments.len(), 2);
2947 }
2948 _ => panic!("expected call"),
2949 }
2950 }
2951
2952 #[test]
2953 fn test_method_call() {
2954 let expr = parse_expr("obj.method()");
2955 match expr.kind {
2956 ExprKind::Call { callee, .. } => match callee.kind {
2957 ExprKind::Member { .. } => {}
2958 _ => panic!("expected member callee"),
2959 },
2960 _ => panic!("expected call"),
2961 }
2962 }
2963
2964 #[test]
2965 fn test_new_expression() {
2966 let expr = parse_expr("new Foo(1)");
2967 match expr.kind {
2968 ExprKind::New {
2969 callee, arguments, ..
2970 } => {
2971 assert_eq!(callee.kind, ExprKind::Identifier("Foo".into()));
2972 assert_eq!(arguments.len(), 1);
2973 }
2974 _ => panic!("expected new"),
2975 }
2976 }
2977
2978 // ── Array and object literals ───────────────────────
2979
2980 #[test]
2981 fn test_array_literal() {
2982 let expr = parse_expr("[1, 2, 3]");
2983 match expr.kind {
2984 ExprKind::Array(elements) => {
2985 assert_eq!(elements.len(), 3);
2986 }
2987 _ => panic!("expected array"),
2988 }
2989 }
2990
2991 #[test]
2992 fn test_object_literal() {
2993 let expr = parse_expr("({a: 1, b: 2})");
2994 match expr.kind {
2995 ExprKind::Object(props) => {
2996 assert_eq!(props.len(), 2);
2997 assert_eq!(props[0].key, PropertyKey::Identifier("a".into()));
2998 }
2999 _ => panic!("expected object"),
3000 }
3001 }
3002
3003 #[test]
3004 fn test_shorthand_property() {
3005 let expr = parse_expr("({x, y})");
3006 match expr.kind {
3007 ExprKind::Object(props) => {
3008 assert!(props[0].shorthand);
3009 assert!(props[1].shorthand);
3010 }
3011 _ => panic!("expected object"),
3012 }
3013 }
3014
3015 #[test]
3016 fn test_computed_property() {
3017 let expr = parse_expr("({[key]: value})");
3018 match expr.kind {
3019 ExprKind::Object(props) => {
3020 assert!(props[0].computed);
3021 }
3022 _ => panic!("expected object"),
3023 }
3024 }
3025
3026 // ── Arrow functions ─────────────────────────────────
3027
3028 #[test]
3029 fn test_arrow_single_param() {
3030 let expr = parse_expr("x => x + 1");
3031 match expr.kind {
3032 ExprKind::Arrow {
3033 params,
3034 body: ArrowBody::Expr(_),
3035 is_async: false,
3036 } => {
3037 assert_eq!(params.len(), 1);
3038 }
3039 _ => panic!("expected arrow"),
3040 }
3041 }
3042
3043 #[test]
3044 fn test_arrow_multi_param() {
3045 let expr = parse_expr("(a, b) => a + b");
3046 match expr.kind {
3047 ExprKind::Arrow { params, .. } => {
3048 assert_eq!(params.len(), 2);
3049 }
3050 _ => panic!("expected arrow"),
3051 }
3052 }
3053
3054 #[test]
3055 fn test_arrow_body_block() {
3056 let expr = parse_expr("() => { return 1; }");
3057 match expr.kind {
3058 ExprKind::Arrow {
3059 body: ArrowBody::Block(stmts),
3060 ..
3061 } => {
3062 assert_eq!(stmts.len(), 1);
3063 }
3064 _ => panic!("expected arrow with block body"),
3065 }
3066 }
3067
3068 // ── Template literals ───────────────────────────────
3069
3070 #[test]
3071 fn test_template_no_subst() {
3072 let expr = parse_expr("`hello`");
3073 match expr.kind {
3074 ExprKind::TemplateLiteral {
3075 quasis,
3076 expressions,
3077 } => {
3078 assert_eq!(quasis, vec!["hello"]);
3079 assert!(expressions.is_empty());
3080 }
3081 _ => panic!("expected template literal"),
3082 }
3083 }
3084
3085 #[test]
3086 fn test_template_with_subst() {
3087 let expr = parse_expr("`hello ${name}!`");
3088 match expr.kind {
3089 ExprKind::TemplateLiteral {
3090 quasis,
3091 expressions,
3092 } => {
3093 assert_eq!(quasis, vec!["hello ", "!"]);
3094 assert_eq!(expressions.len(), 1);
3095 }
3096 _ => panic!("expected template literal"),
3097 }
3098 }
3099
3100 // ── Spread ──────────────────────────────────────────
3101
3102 #[test]
3103 fn test_spread_in_call() {
3104 let expr = parse_expr("foo(...args)");
3105 match expr.kind {
3106 ExprKind::Call { arguments, .. } => {
3107 assert_eq!(arguments.len(), 1);
3108 assert!(matches!(arguments[0].kind, ExprKind::Spread(_)));
3109 }
3110 _ => panic!("expected call"),
3111 }
3112 }
3113
3114 // ── Variable declarations ───────────────────────────
3115
3116 #[test]
3117 fn test_var_decl() {
3118 let stmt = parse_stmt("var x = 42;");
3119 match stmt.kind {
3120 StmtKind::VarDecl { kind, declarators } => {
3121 assert_eq!(kind, VarKind::Var);
3122 assert_eq!(declarators.len(), 1);
3123 assert!(matches!(
3124 declarators[0].pattern.kind,
3125 PatternKind::Identifier(ref n) if n == "x"
3126 ));
3127 assert!(declarators[0].init.is_some());
3128 }
3129 _ => panic!("expected var decl"),
3130 }
3131 }
3132
3133 #[test]
3134 fn test_const_decl() {
3135 let stmt = parse_stmt("const [a, b] = arr;");
3136 match stmt.kind {
3137 StmtKind::VarDecl {
3138 kind: VarKind::Const,
3139 declarators,
3140 } => {
3141 assert!(matches!(
3142 declarators[0].pattern.kind,
3143 PatternKind::Array { .. }
3144 ));
3145 }
3146 _ => panic!("expected const decl"),
3147 }
3148 }
3149
3150 #[test]
3151 fn test_destructuring_object() {
3152 let stmt = parse_stmt("let { a, b: c } = obj;");
3153 match stmt.kind {
3154 StmtKind::VarDecl { declarators, .. } => match &declarators[0].pattern.kind {
3155 PatternKind::Object { properties, .. } => {
3156 assert_eq!(properties.len(), 2);
3157 assert!(properties[0].shorthand);
3158 assert!(!properties[1].shorthand);
3159 }
3160 _ => panic!("expected object pattern"),
3161 },
3162 _ => panic!("expected var decl"),
3163 }
3164 }
3165
3166 // ── Function declaration ────────────────────────────
3167
3168 #[test]
3169 fn test_function_decl() {
3170 let stmt = parse_stmt("function add(a, b) { return a + b; }");
3171 match stmt.kind {
3172 StmtKind::FunctionDecl(def) => {
3173 assert_eq!(def.id, Some("add".into()));
3174 assert_eq!(def.params.len(), 2);
3175 assert!(!def.is_async);
3176 assert!(!def.is_generator);
3177 assert_eq!(def.body.len(), 1);
3178 }
3179 _ => panic!("expected function decl"),
3180 }
3181 }
3182
3183 #[test]
3184 fn test_generator_function() {
3185 let stmt = parse_stmt("function* gen() { yield 1; }");
3186 match stmt.kind {
3187 StmtKind::FunctionDecl(def) => {
3188 assert!(def.is_generator);
3189 }
3190 _ => panic!("expected function decl"),
3191 }
3192 }
3193
3194 #[test]
3195 fn test_async_function() {
3196 let stmt = parse_stmt("async function fetch() { await get(); }");
3197 match stmt.kind {
3198 StmtKind::FunctionDecl(def) => {
3199 assert!(def.is_async);
3200 }
3201 _ => panic!("expected function decl"),
3202 }
3203 }
3204
3205 #[test]
3206 fn test_default_params() {
3207 let stmt = parse_stmt("function f(a, b = 10) {}");
3208 match stmt.kind {
3209 StmtKind::FunctionDecl(def) => {
3210 assert_eq!(def.params.len(), 2);
3211 assert!(matches!(def.params[1].kind, PatternKind::Assign { .. }));
3212 }
3213 _ => panic!("expected function decl"),
3214 }
3215 }
3216
3217 #[test]
3218 fn test_rest_params() {
3219 let stmt = parse_stmt("function f(...args) {}");
3220 match stmt.kind {
3221 StmtKind::FunctionDecl(def) => {
3222 assert_eq!(def.params.len(), 1);
3223 assert!(matches!(
3224 def.params[0].kind,
3225 PatternKind::Identifier(ref n) if n == "args"
3226 ));
3227 }
3228 _ => panic!("expected function decl"),
3229 }
3230 }
3231
3232 // ── Class declaration ───────────────────────────────
3233
3234 #[test]
3235 fn test_class_decl() {
3236 let stmt = parse_stmt("class Foo { constructor() {} method() {} }");
3237 match stmt.kind {
3238 StmtKind::ClassDecl(def) => {
3239 assert_eq!(def.id, Some("Foo".into()));
3240 assert_eq!(def.body.len(), 2);
3241 }
3242 _ => panic!("expected class decl"),
3243 }
3244 }
3245
3246 #[test]
3247 fn test_class_extends() {
3248 let stmt = parse_stmt("class Bar extends Foo {}");
3249 match stmt.kind {
3250 StmtKind::ClassDecl(def) => {
3251 assert!(def.super_class.is_some());
3252 }
3253 _ => panic!("expected class decl"),
3254 }
3255 }
3256
3257 #[test]
3258 fn test_class_getter_setter() {
3259 let stmt = parse_stmt("class C { get x() { return 1; } set x(v) {} }");
3260 match stmt.kind {
3261 StmtKind::ClassDecl(def) => {
3262 assert_eq!(def.body.len(), 2);
3263 match &def.body[0].kind {
3264 ClassMemberKind::Method { kind, .. } => {
3265 assert_eq!(*kind, MethodKind::Get);
3266 }
3267 _ => panic!("expected getter"),
3268 }
3269 }
3270 _ => panic!("expected class decl"),
3271 }
3272 }
3273
3274 // ── Control flow statements ─────────────────────────
3275
3276 #[test]
3277 fn test_if_else() {
3278 let stmt = parse_stmt("if (x) { a(); } else { b(); }");
3279 match stmt.kind {
3280 StmtKind::If { alternate, .. } => {
3281 assert!(alternate.is_some());
3282 }
3283 _ => panic!("expected if"),
3284 }
3285 }
3286
3287 #[test]
3288 fn test_for_loop() {
3289 let stmt = parse_stmt("for (let i = 0; i < 10; i++) {}");
3290 match stmt.kind {
3291 StmtKind::For {
3292 init, test, update, ..
3293 } => {
3294 assert!(init.is_some());
3295 assert!(test.is_some());
3296 assert!(update.is_some());
3297 }
3298 _ => panic!("expected for"),
3299 }
3300 }
3301
3302 #[test]
3303 fn test_for_in() {
3304 let stmt = parse_stmt("for (const key in obj) {}");
3305 assert!(matches!(stmt.kind, StmtKind::ForIn { .. }));
3306 }
3307
3308 #[test]
3309 fn test_for_of() {
3310 let stmt = parse_stmt("for (const item of arr) {}");
3311 assert!(matches!(stmt.kind, StmtKind::ForOf { .. }));
3312 }
3313
3314 #[test]
3315 fn test_while_loop() {
3316 let stmt = parse_stmt("while (true) {}");
3317 assert!(matches!(stmt.kind, StmtKind::While { .. }));
3318 }
3319
3320 #[test]
3321 fn test_do_while() {
3322 let stmt = parse_stmt("do {} while (true);");
3323 assert!(matches!(stmt.kind, StmtKind::DoWhile { .. }));
3324 }
3325
3326 #[test]
3327 fn test_switch() {
3328 let stmt = parse_stmt("switch (x) { case 1: break; default: break; }");
3329 match stmt.kind {
3330 StmtKind::Switch { cases, .. } => {
3331 assert_eq!(cases.len(), 2);
3332 assert!(cases[0].test.is_some());
3333 assert!(cases[1].test.is_none()); // default
3334 }
3335 _ => panic!("expected switch"),
3336 }
3337 }
3338
3339 #[test]
3340 fn test_try_catch() {
3341 let stmt = parse_stmt("try { f(); } catch (e) { g(); }");
3342 match stmt.kind {
3343 StmtKind::Try {
3344 handler, finalizer, ..
3345 } => {
3346 assert!(handler.is_some());
3347 assert!(finalizer.is_none());
3348 }
3349 _ => panic!("expected try"),
3350 }
3351 }
3352
3353 #[test]
3354 fn test_try_catch_finally() {
3355 let stmt = parse_stmt("try {} catch (e) {} finally {}");
3356 match stmt.kind {
3357 StmtKind::Try {
3358 handler, finalizer, ..
3359 } => {
3360 assert!(handler.is_some());
3361 assert!(finalizer.is_some());
3362 }
3363 _ => panic!("expected try"),
3364 }
3365 }
3366
3367 #[test]
3368 fn test_return() {
3369 let stmt = parse_stmt("function f() { return 42; }");
3370 match stmt.kind {
3371 StmtKind::FunctionDecl(def) => match &def.body[0].kind {
3372 StmtKind::Return(Some(expr)) => {
3373 assert_eq!(expr.kind, ExprKind::Number(42.0));
3374 }
3375 _ => panic!("expected return"),
3376 },
3377 _ => panic!("expected function"),
3378 }
3379 }
3380
3381 #[test]
3382 fn test_throw() {
3383 let stmt = parse_stmt("function f() { throw new Error(); }");
3384 match stmt.kind {
3385 StmtKind::FunctionDecl(def) => {
3386 assert!(matches!(def.body[0].kind, StmtKind::Throw(_)));
3387 }
3388 _ => panic!("expected function"),
3389 }
3390 }
3391
3392 #[test]
3393 fn test_break_continue() {
3394 let prog = parse("while (true) { break; continue; }");
3395 let while_stmt = &prog.body[0];
3396 match &while_stmt.kind {
3397 StmtKind::While { body, .. } => match &body.kind {
3398 StmtKind::Block(stmts) => {
3399 assert!(matches!(stmts[0].kind, StmtKind::Break(None)));
3400 assert!(matches!(stmts[1].kind, StmtKind::Continue(None)));
3401 }
3402 _ => panic!("expected block"),
3403 },
3404 _ => panic!("expected while"),
3405 }
3406 }
3407
3408 #[test]
3409 fn test_labeled_statement() {
3410 let stmt = parse_stmt("outer: for (;;) {}");
3411 match stmt.kind {
3412 StmtKind::Labeled { label, .. } => {
3413 assert_eq!(label, "outer");
3414 }
3415 _ => panic!("expected labeled"),
3416 }
3417 }
3418
3419 // ── Import / Export ─────────────────────────────────
3420
3421 #[test]
3422 fn test_import_default() {
3423 let stmt = parse_stmt("import foo from \"mod\";");
3424 match stmt.kind {
3425 StmtKind::Import { specifiers, source } => {
3426 assert_eq!(source, "mod");
3427 assert_eq!(specifiers.len(), 1);
3428 assert!(matches!(&specifiers[0], ImportSpecifier::Default(n) if n == "foo"));
3429 }
3430 _ => panic!("expected import"),
3431 }
3432 }
3433
3434 #[test]
3435 fn test_import_named() {
3436 let prog = Parser::parse_module("import { a, b as c } from \"mod\";").unwrap();
3437 match &prog.body[0].kind {
3438 StmtKind::Import { specifiers, .. } => {
3439 assert_eq!(specifiers.len(), 2);
3440 }
3441 _ => panic!("expected import"),
3442 }
3443 }
3444
3445 #[test]
3446 fn test_import_namespace() {
3447 let prog = Parser::parse_module("import * as ns from \"mod\";").unwrap();
3448 match &prog.body[0].kind {
3449 StmtKind::Import { specifiers, .. } => {
3450 assert!(matches!(&specifiers[0], ImportSpecifier::Namespace(n) if n == "ns"));
3451 }
3452 _ => panic!("expected import"),
3453 }
3454 }
3455
3456 #[test]
3457 fn test_export_default() {
3458 let prog = Parser::parse_module("export default 42;").unwrap();
3459 match &prog.body[0].kind {
3460 StmtKind::Export(ExportDecl::Default(expr)) => {
3461 assert_eq!(expr.kind, ExprKind::Number(42.0));
3462 }
3463 _ => panic!("expected export default"),
3464 }
3465 }
3466
3467 #[test]
3468 fn test_export_named() {
3469 let prog = Parser::parse_module("export { a, b as c };").unwrap();
3470 match &prog.body[0].kind {
3471 StmtKind::Export(ExportDecl::Named { specifiers, .. }) => {
3472 assert_eq!(specifiers.len(), 2);
3473 }
3474 _ => panic!("expected export named"),
3475 }
3476 }
3477
3478 #[test]
3479 fn test_export_declaration() {
3480 let prog = Parser::parse_module("export const x = 1;").unwrap();
3481 match &prog.body[0].kind {
3482 StmtKind::Export(ExportDecl::Declaration(_)) => {}
3483 _ => panic!("expected export declaration"),
3484 }
3485 }
3486
3487 #[test]
3488 fn test_export_default_anonymous_function() {
3489 let prog = Parser::parse_module("export default function() {}").unwrap();
3490 match &prog.body[0].kind {
3491 StmtKind::Export(ExportDecl::Default(expr)) => {
3492 assert!(matches!(expr.kind, ExprKind::Function(ref def) if def.id.is_none()));
3493 }
3494 _ => panic!("expected export default anonymous function"),
3495 }
3496 }
3497
3498 #[test]
3499 fn test_export_default_anonymous_class() {
3500 let prog = Parser::parse_module("export default class {}").unwrap();
3501 match &prog.body[0].kind {
3502 StmtKind::Export(ExportDecl::Default(expr)) => {
3503 assert!(matches!(expr.kind, ExprKind::Class(ref def) if def.id.is_none()));
3504 }
3505 _ => panic!("expected export default anonymous class"),
3506 }
3507 }
3508
3509 #[test]
3510 fn test_export_default_anonymous_generator() {
3511 let prog = Parser::parse_module("export default function*() {}").unwrap();
3512 match &prog.body[0].kind {
3513 StmtKind::Export(ExportDecl::Default(expr)) => {
3514 assert!(matches!(
3515 expr.kind,
3516 ExprKind::Function(ref def) if def.id.is_none() && def.is_generator
3517 ));
3518 }
3519 _ => panic!("expected export default anonymous generator"),
3520 }
3521 }
3522
3523 // ── ASI (Automatic Semicolon Insertion) ─────────────
3524
3525 #[test]
3526 fn test_asi_newline() {
3527 let prog = parse("let x = 1\nlet y = 2");
3528 assert_eq!(prog.body.len(), 2);
3529 }
3530
3531 #[test]
3532 fn test_asi_before_rbrace() {
3533 let stmt = parse_stmt("function f() { return 1 }");
3534 match stmt.kind {
3535 StmtKind::FunctionDecl(def) => {
3536 assert_eq!(def.body.len(), 1);
3537 }
3538 _ => panic!("expected function"),
3539 }
3540 }
3541
3542 // ── Complex programs ────────────────────────────────
3543
3544 #[test]
3545 fn test_fibonacci() {
3546 let src = r#"
3547 function fib(n) {
3548 if (n <= 1) return n;
3549 return fib(n - 1) + fib(n - 2);
3550 }
3551 "#;
3552 let prog = parse(src);
3553 assert_eq!(prog.body.len(), 1);
3554 assert!(matches!(prog.body[0].kind, StmtKind::FunctionDecl(_)));
3555 }
3556
3557 #[test]
3558 fn test_class_with_methods() {
3559 let src = r#"
3560 class Animal {
3561 constructor(name) {
3562 this.name = name;
3563 }
3564 speak() {
3565 return this.name;
3566 }
3567 static create(name) {
3568 return new Animal(name);
3569 }
3570 }
3571 "#;
3572 let prog = parse(src);
3573 assert_eq!(prog.body.len(), 1);
3574 match &prog.body[0].kind {
3575 StmtKind::ClassDecl(def) => {
3576 assert_eq!(def.body.len(), 3);
3577 }
3578 _ => panic!("expected class"),
3579 }
3580 }
3581
3582 #[test]
3583 fn test_for_of_destructuring() {
3584 let stmt = parse_stmt("for (const [k, v] of map) {}");
3585 match stmt.kind {
3586 StmtKind::ForOf { left, .. } => match left {
3587 ForInOfLeft::VarDecl { pattern, .. } => {
3588 assert!(matches!(pattern.kind, PatternKind::Array { .. }));
3589 }
3590 _ => panic!("expected var decl"),
3591 },
3592 _ => panic!("expected for-of"),
3593 }
3594 }
3595
3596 #[test]
3597 fn test_multiple_statements() {
3598 let src = "let x = 1; let y = 2; x + y;";
3599 let prog = parse(src);
3600 assert_eq!(prog.body.len(), 3);
3601 }
3602
3603 // ── Error cases ─────────────────────────────────────
3604
3605 #[test]
3606 fn test_error_unexpected_token() {
3607 assert!(Parser::parse(")").is_err());
3608 }
3609
3610 #[test]
3611 fn test_error_unterminated_block() {
3612 assert!(Parser::parse("{ let x = 1;").is_err());
3613 }
3614
3615 #[test]
3616 fn test_error_missing_paren() {
3617 assert!(Parser::parse("if x {}").is_err());
3618 }
3619}