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