Skip to main content

fiddler_script/
parser.rs

1//! Parser for FiddlerScript.
2//!
3//! This module implements a recursive descent parser with Pratt parsing
4//! for expression precedence handling.
5//!
6//! The parser transforms a token stream into an Abstract Syntax Tree (AST).
7
8use crate::ast::{BinaryOp, Block, ElseClause, Expression, Program, Statement, UnaryOp};
9use crate::error::ParseError;
10use crate::lexer::{Token, TokenKind};
11
12/// The parser for FiddlerScript.
13pub struct Parser {
14    /// The tokens to parse
15    tokens: Vec<Token>,
16    /// Current position in the token stream
17    current: usize,
18}
19
20impl Parser {
21    /// Create a new parser for the given tokens.
22    pub fn new(tokens: Vec<Token>) -> Self {
23        Self { tokens, current: 0 }
24    }
25
26    /// Parse a complete program.
27    pub fn parse(&mut self) -> Result<Program, ParseError> {
28        let mut statements = Vec::new();
29
30        while !self.is_at_end() {
31            statements.push(self.parse_statement()?);
32        }
33
34        Ok(Program::new(statements))
35    }
36
37    // === Helper methods ===
38
39    /// Check if we've reached the end of the token stream.
40    fn is_at_end(&self) -> bool {
41        self.peek().kind == TokenKind::Eof
42    }
43
44    /// Get the current token without consuming it.
45    fn peek(&self) -> &Token {
46        self.tokens.get(self.current).unwrap_or_else(|| {
47            self.tokens
48                .last()
49                .expect("Token stream should have at least EOF")
50        })
51    }
52
53    /// Get the previous token.
54    fn previous(&self) -> &Token {
55        &self.tokens[self.current.saturating_sub(1)]
56    }
57
58    /// Advance to the next token and return the current one.
59    fn advance(&mut self) -> &Token {
60        if !self.is_at_end() {
61            self.current += 1;
62        }
63        self.previous()
64    }
65
66    /// Check if the current token matches the given kind.
67    fn check(&self, kind: &TokenKind) -> bool {
68        if self.is_at_end() {
69            return false;
70        }
71        std::mem::discriminant(&self.peek().kind) == std::mem::discriminant(kind)
72    }
73
74    /// Consume the current token if it matches the given kind.
75    fn match_token(&mut self, kind: &TokenKind) -> bool {
76        if self.check(kind) {
77            self.advance();
78            true
79        } else {
80            false
81        }
82    }
83
84    /// Expect the current token to match the given kind, or return an error.
85    fn expect(&mut self, kind: &TokenKind, expected: &str) -> Result<&Token, ParseError> {
86        if self.check(kind) {
87            Ok(self.advance())
88        } else {
89            Err(ParseError::UnexpectedToken(
90                self.peek().kind.to_string(),
91                self.peek().position,
92                expected.to_string(),
93            ))
94        }
95    }
96
97    // === Statement parsing ===
98
99    /// Parse a statement.
100    fn parse_statement(&mut self) -> Result<Statement, ParseError> {
101        match &self.peek().kind {
102            TokenKind::Let => self.parse_let_statement(),
103            TokenKind::If => self.parse_if_statement(),
104            TokenKind::For => self.parse_for_statement(),
105            TokenKind::Return => self.parse_return_statement(),
106            TokenKind::Fn => self.parse_function_definition(),
107            TokenKind::LeftBrace => {
108                // Check if this is a dictionary literal (expression) or a block statement
109                if self.is_dictionary_literal() {
110                    self.parse_expression_statement()
111                } else {
112                    let block = self.parse_block()?;
113                    Ok(Statement::Block(block))
114                }
115            }
116            _ => self.parse_expression_statement(),
117        }
118    }
119
120    /// Parse a let statement: `let x = expr;`
121    fn parse_let_statement(&mut self) -> Result<Statement, ParseError> {
122        let position = self.peek().position;
123        self.advance(); // consume 'let'
124
125        let name = match &self.peek().kind {
126            TokenKind::Identifier(name) => name.clone(),
127            _ => return Err(ParseError::ExpectedIdentifier(self.peek().position)),
128        };
129        self.advance();
130
131        self.expect(&TokenKind::Assign, "=")?;
132        let value = self.parse_expression()?;
133        self.expect(&TokenKind::Semicolon, ";")?;
134
135        Ok(Statement::Let {
136            name,
137            value,
138            position,
139        })
140    }
141
142    /// Parse an if statement: `if (condition) { ... } else { ... }`
143    fn parse_if_statement(&mut self) -> Result<Statement, ParseError> {
144        let position = self.peek().position;
145        self.advance(); // consume 'if'
146
147        self.expect(&TokenKind::LeftParen, "(")?;
148        let condition = self.parse_expression()?;
149        self.expect(&TokenKind::RightParen, ")")?;
150
151        let then_block = self.parse_block()?;
152
153        let else_block = if self.match_token(&TokenKind::Else) {
154            if self.check(&TokenKind::If) {
155                // else if
156                Some(ElseClause::ElseIf(Box::new(self.parse_if_statement()?)))
157            } else {
158                // else block
159                Some(ElseClause::Block(self.parse_block()?))
160            }
161        } else {
162            None
163        };
164
165        Ok(Statement::If {
166            condition,
167            then_block,
168            else_block,
169            position,
170        })
171    }
172
173    /// Parse a for statement: `for (init; condition; update) { ... }`
174    fn parse_for_statement(&mut self) -> Result<Statement, ParseError> {
175        let position = self.peek().position;
176        self.advance(); // consume 'for'
177
178        self.expect(&TokenKind::LeftParen, "(")?;
179
180        // Init clause
181        let init = if self.match_token(&TokenKind::Semicolon) {
182            None
183        } else if self.check(&TokenKind::Let) {
184            Some(Box::new(self.parse_let_statement()?))
185        } else {
186            let expr = self.parse_expression()?;
187            let pos = expr.position();
188            self.expect(&TokenKind::Semicolon, ";")?;
189            Some(Box::new(Statement::Expression {
190                expression: expr,
191                position: pos,
192            }))
193        };
194
195        // Condition clause
196        let condition = if self.check(&TokenKind::Semicolon) {
197            None
198        } else {
199            Some(self.parse_expression()?)
200        };
201        self.expect(&TokenKind::Semicolon, ";")?;
202
203        // Update clause
204        let update = if self.check(&TokenKind::RightParen) {
205            None
206        } else {
207            Some(self.parse_expression()?)
208        };
209        self.expect(&TokenKind::RightParen, ")")?;
210
211        let body = self.parse_block()?;
212
213        Ok(Statement::For {
214            init,
215            condition,
216            update,
217            body,
218            position,
219        })
220    }
221
222    /// Parse a return statement: `return expr;`
223    fn parse_return_statement(&mut self) -> Result<Statement, ParseError> {
224        let position = self.peek().position;
225        self.advance(); // consume 'return'
226
227        let value = if self.check(&TokenKind::Semicolon) {
228            None
229        } else {
230            Some(self.parse_expression()?)
231        };
232
233        self.expect(&TokenKind::Semicolon, ";")?;
234
235        Ok(Statement::Return { value, position })
236    }
237
238    /// Parse a function definition: `fn name(params) { ... }`
239    fn parse_function_definition(&mut self) -> Result<Statement, ParseError> {
240        let position = self.peek().position;
241        self.advance(); // consume 'fn'
242
243        let name = match &self.peek().kind {
244            TokenKind::Identifier(name) => name.clone(),
245            _ => return Err(ParseError::ExpectedIdentifier(self.peek().position)),
246        };
247        self.advance();
248
249        self.expect(&TokenKind::LeftParen, "(")?;
250        let params = self.parse_parameters()?;
251        self.expect(&TokenKind::RightParen, ")")?;
252
253        let body = self.parse_block()?;
254
255        Ok(Statement::Function {
256            name,
257            params,
258            body,
259            position,
260        })
261    }
262
263    /// Parse function parameters.
264    fn parse_parameters(&mut self) -> Result<Vec<String>, ParseError> {
265        let mut params = Vec::new();
266
267        if !self.check(&TokenKind::RightParen) {
268            loop {
269                let pos = self.peek().position;
270                let name = match &self.peek().kind {
271                    TokenKind::Identifier(name) => name.clone(),
272                    _ => return Err(ParseError::ExpectedIdentifier(self.peek().position)),
273                };
274                self.advance();
275
276                // Check for duplicate parameter
277                if params.contains(&name) {
278                    return Err(ParseError::UnexpectedToken(
279                        name,
280                        pos,
281                        "unique parameter name (duplicate parameter)".to_string(),
282                    ));
283                }
284
285                params.push(name);
286
287                if !self.match_token(&TokenKind::Comma) {
288                    break;
289                }
290            }
291        }
292
293        Ok(params)
294    }
295
296    /// Parse an expression statement: `expr;`
297    fn parse_expression_statement(&mut self) -> Result<Statement, ParseError> {
298        let expression = self.parse_expression()?;
299        let position = expression.position();
300        self.expect(&TokenKind::Semicolon, ";")?;
301        Ok(Statement::Expression {
302            expression,
303            position,
304        })
305    }
306
307    /// Parse a block: `{ statements }`
308    fn parse_block(&mut self) -> Result<Block, ParseError> {
309        let position = self.peek().position;
310        self.expect(&TokenKind::LeftBrace, "{")?;
311
312        let mut statements = Vec::new();
313        while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
314            statements.push(self.parse_statement()?);
315        }
316
317        self.expect(&TokenKind::RightBrace, "}")?;
318        Ok(Block::new(statements, position))
319    }
320
321    // === Expression parsing (Pratt parsing) ===
322
323    /// Parse an expression.
324    pub fn parse_expression(&mut self) -> Result<Expression, ParseError> {
325        self.parse_assignment()
326    }
327
328    /// Parse assignment expression.
329    fn parse_assignment(&mut self) -> Result<Expression, ParseError> {
330        let expr = self.parse_or()?;
331
332        if self.match_token(&TokenKind::Assign) {
333            let position = self.previous().position;
334            let value = self.parse_assignment()?;
335
336            match expr {
337                Expression::Identifier { name, .. } => {
338                    return Ok(Expression::Assignment {
339                        name,
340                        value: Box::new(value),
341                        position,
342                    });
343                }
344                _ => return Err(ParseError::InvalidAssignmentTarget(position)),
345            }
346        }
347
348        Ok(expr)
349    }
350
351    /// Parse logical OR expression.
352    fn parse_or(&mut self) -> Result<Expression, ParseError> {
353        let mut left = self.parse_and()?;
354
355        while self.match_token(&TokenKind::Or) {
356            let position = self.previous().position;
357            let right = self.parse_and()?;
358            left = Expression::Binary {
359                left: Box::new(left),
360                operator: BinaryOp::Or,
361                right: Box::new(right),
362                position,
363            };
364        }
365
366        Ok(left)
367    }
368
369    /// Parse logical AND expression.
370    fn parse_and(&mut self) -> Result<Expression, ParseError> {
371        let mut left = self.parse_equality()?;
372
373        while self.match_token(&TokenKind::And) {
374            let position = self.previous().position;
375            let right = self.parse_equality()?;
376            left = Expression::Binary {
377                left: Box::new(left),
378                operator: BinaryOp::And,
379                right: Box::new(right),
380                position,
381            };
382        }
383
384        Ok(left)
385    }
386
387    /// Parse equality expression.
388    fn parse_equality(&mut self) -> Result<Expression, ParseError> {
389        let mut left = self.parse_comparison()?;
390
391        loop {
392            let op = if self.match_token(&TokenKind::Equal) {
393                BinaryOp::Equal
394            } else if self.match_token(&TokenKind::NotEqual) {
395                BinaryOp::NotEqual
396            } else {
397                break;
398            };
399
400            let position = self.previous().position;
401            let right = self.parse_comparison()?;
402            left = Expression::Binary {
403                left: Box::new(left),
404                operator: op,
405                right: Box::new(right),
406                position,
407            };
408        }
409
410        Ok(left)
411    }
412
413    /// Parse comparison expression.
414    fn parse_comparison(&mut self) -> Result<Expression, ParseError> {
415        let mut left = self.parse_addition()?;
416
417        loop {
418            let op = if self.match_token(&TokenKind::LessThan) {
419                BinaryOp::LessThan
420            } else if self.match_token(&TokenKind::LessEqual) {
421                BinaryOp::LessEqual
422            } else if self.match_token(&TokenKind::GreaterThan) {
423                BinaryOp::GreaterThan
424            } else if self.match_token(&TokenKind::GreaterEqual) {
425                BinaryOp::GreaterEqual
426            } else {
427                break;
428            };
429
430            let position = self.previous().position;
431            let right = self.parse_addition()?;
432            left = Expression::Binary {
433                left: Box::new(left),
434                operator: op,
435                right: Box::new(right),
436                position,
437            };
438        }
439
440        Ok(left)
441    }
442
443    /// Parse addition/subtraction expression.
444    fn parse_addition(&mut self) -> Result<Expression, ParseError> {
445        let mut left = self.parse_multiplication()?;
446
447        loop {
448            let op = if self.match_token(&TokenKind::Plus) {
449                BinaryOp::Add
450            } else if self.match_token(&TokenKind::Minus) {
451                BinaryOp::Subtract
452            } else {
453                break;
454            };
455
456            let position = self.previous().position;
457            let right = self.parse_multiplication()?;
458            left = Expression::Binary {
459                left: Box::new(left),
460                operator: op,
461                right: Box::new(right),
462                position,
463            };
464        }
465
466        Ok(left)
467    }
468
469    /// Parse multiplication/division/modulo expression.
470    fn parse_multiplication(&mut self) -> Result<Expression, ParseError> {
471        let mut left = self.parse_unary()?;
472
473        loop {
474            let op = if self.match_token(&TokenKind::Star) {
475                BinaryOp::Multiply
476            } else if self.match_token(&TokenKind::Slash) {
477                BinaryOp::Divide
478            } else if self.match_token(&TokenKind::Percent) {
479                BinaryOp::Modulo
480            } else {
481                break;
482            };
483
484            let position = self.previous().position;
485            let right = self.parse_unary()?;
486            left = Expression::Binary {
487                left: Box::new(left),
488                operator: op,
489                right: Box::new(right),
490                position,
491            };
492        }
493
494        Ok(left)
495    }
496
497    /// Parse unary expression.
498    fn parse_unary(&mut self) -> Result<Expression, ParseError> {
499        if self.match_token(&TokenKind::Bang) {
500            let position = self.previous().position;
501            let operand = self.parse_unary()?;
502            return Ok(Expression::Unary {
503                operator: UnaryOp::Not,
504                operand: Box::new(operand),
505                position,
506            });
507        }
508
509        if self.match_token(&TokenKind::Minus) {
510            let position = self.previous().position;
511            let operand = self.parse_unary()?;
512            return Ok(Expression::Unary {
513                operator: UnaryOp::Negate,
514                operand: Box::new(operand),
515                position,
516            });
517        }
518
519        self.parse_call()
520    }
521
522    /// Parse function call or method call.
523    ///
524    /// Handles both regular function calls `func(args)` and method calls `expr.method(args)`.
525    /// Method calls can be chained: `expr.method1().method2()`.
526    fn parse_call(&mut self) -> Result<Expression, ParseError> {
527        let mut expr = self.parse_primary()?;
528
529        loop {
530            if self.match_token(&TokenKind::Dot) {
531                // Parse method call: expr.method(args)
532                expr = self.parse_method_call_continuation(expr)?;
533            } else if self.is_function_call_start(&expr) {
534                // Parse function call: identifier(args)
535                expr = self.parse_function_call_continuation(expr)?;
536            } else {
537                // No more calls/method calls
538                break;
539            }
540        }
541
542        Ok(expr)
543    }
544
545    /// Check if the current position starts a function call on an identifier.
546    fn is_function_call_start(&self, expr: &Expression) -> bool {
547        matches!(expr, Expression::Identifier { .. }) && self.check(&TokenKind::LeftParen)
548    }
549
550    /// Parse the continuation of a method call after the dot has been consumed.
551    ///
552    /// Expects: `method(args)` where the dot has already been consumed.
553    fn parse_method_call_continuation(
554        &mut self,
555        receiver: Expression,
556    ) -> Result<Expression, ParseError> {
557        let method_pos = self.previous().position;
558
559        // Expect method name (identifier) with context-specific error
560        let method = match &self.peek().kind {
561            TokenKind::Identifier(name) => name.clone(),
562            _ => {
563                return Err(ParseError::UnexpectedToken(
564                    self.peek().kind.to_string(),
565                    self.peek().position,
566                    "method name".to_string(),
567                ))
568            }
569        };
570        self.advance();
571
572        // Expect opening parenthesis
573        self.expect(&TokenKind::LeftParen, "(")?;
574        let arguments = self.parse_arguments()?;
575        self.expect(&TokenKind::RightParen, ")")?;
576
577        Ok(Expression::MethodCall {
578            receiver: Box::new(receiver),
579            method,
580            arguments,
581            position: method_pos,
582        })
583    }
584
585    /// Parse the continuation of a function call on an identifier.
586    ///
587    /// Expects: `(args)` where the identifier has already been parsed.
588    fn parse_function_call_continuation(
589        &mut self,
590        expr: Expression,
591    ) -> Result<Expression, ParseError> {
592        let Expression::Identifier { name, position } = expr else {
593            // This should not happen if is_function_call_start was checked first
594            return Err(ParseError::ExpectedIdentifier(self.peek().position));
595        };
596
597        self.advance(); // consume LeftParen
598        let arguments = self.parse_arguments()?;
599        self.expect(&TokenKind::RightParen, ")")?;
600
601        Ok(Expression::Call {
602            function: name,
603            arguments,
604            position,
605        })
606    }
607
608    /// Parse function arguments.
609    fn parse_arguments(&mut self) -> Result<Vec<Expression>, ParseError> {
610        let mut args = Vec::new();
611
612        if !self.check(&TokenKind::RightParen) {
613            loop {
614                args.push(self.parse_expression()?);
615                if !self.match_token(&TokenKind::Comma) {
616                    break;
617                }
618            }
619        }
620
621        Ok(args)
622    }
623
624    /// Parse primary expression.
625    fn parse_primary(&mut self) -> Result<Expression, ParseError> {
626        let position = self.peek().position;
627
628        match &self.peek().kind {
629            TokenKind::Integer(value) => {
630                let value = *value;
631                self.advance();
632                Ok(Expression::Integer { value, position })
633            }
634            TokenKind::Float(value) => {
635                let value = *value;
636                self.advance();
637                Ok(Expression::Float { value, position })
638            }
639            TokenKind::String(value) => {
640                let value = value.clone();
641                self.advance();
642                Ok(Expression::String { value, position })
643            }
644            TokenKind::True => {
645                self.advance();
646                Ok(Expression::Boolean {
647                    value: true,
648                    position,
649                })
650            }
651            TokenKind::False => {
652                self.advance();
653                Ok(Expression::Boolean {
654                    value: false,
655                    position,
656                })
657            }
658            TokenKind::Null => {
659                self.advance();
660                Ok(Expression::Null { position })
661            }
662            TokenKind::Identifier(name) => {
663                let name = name.clone();
664                self.advance();
665                Ok(Expression::Identifier { name, position })
666            }
667            TokenKind::LeftParen => {
668                self.advance();
669                let expression = self.parse_expression()?;
670                self.expect(&TokenKind::RightParen, ")")?;
671                Ok(Expression::Grouped {
672                    expression: Box::new(expression),
673                    position,
674                })
675            }
676            TokenKind::LeftBracket => self.parse_array_literal(),
677            TokenKind::LeftBrace => {
678                // Check if this is a dictionary literal or a block
679                // Dictionary literals start with { followed by a string or }
680                // We need to peek ahead to distinguish
681                if self.is_dictionary_literal() {
682                    self.parse_dictionary_literal()
683                } else {
684                    Err(ParseError::ExpectedExpression(position))
685                }
686            }
687            TokenKind::Eof => Err(ParseError::UnexpectedEof(position)),
688            _ => Err(ParseError::ExpectedExpression(position)),
689        }
690    }
691
692    /// Check if the current position starts a dictionary literal.
693    /// Dictionary literals are `{` followed by `}` or a string/identifier then `:`.
694    fn is_dictionary_literal(&self) -> bool {
695        if !self.check(&TokenKind::LeftBrace) {
696            return false;
697        }
698
699        // Look ahead: { } is empty dict, { "key": or { identifier: is dict
700        let mut lookahead = self.current + 1;
701
702        // Skip the {
703        if lookahead >= self.tokens.len() {
704            return false;
705        }
706
707        // Empty dict: {}
708        if matches!(
709            self.tokens.get(lookahead).map(|t| &t.kind),
710            Some(TokenKind::RightBrace)
711        ) {
712            return true;
713        }
714
715        // Check for string/identifier followed by colon
716        match self.tokens.get(lookahead).map(|t| &t.kind) {
717            Some(TokenKind::String(_)) | Some(TokenKind::Identifier(_)) => {
718                lookahead += 1;
719                matches!(
720                    self.tokens.get(lookahead).map(|t| &t.kind),
721                    Some(TokenKind::Colon)
722                )
723            }
724            _ => false,
725        }
726    }
727
728    /// Parse array literal: `[expr, expr, ...]`
729    fn parse_array_literal(&mut self) -> Result<Expression, ParseError> {
730        let position = self.peek().position;
731        self.expect(&TokenKind::LeftBracket, "[")?;
732
733        let mut elements = Vec::new();
734
735        if !self.check(&TokenKind::RightBracket) {
736            loop {
737                elements.push(self.parse_expression()?);
738                if !self.match_token(&TokenKind::Comma) {
739                    break;
740                }
741                // Allow trailing comma
742                if self.check(&TokenKind::RightBracket) {
743                    break;
744                }
745            }
746        }
747
748        self.expect(&TokenKind::RightBracket, "]")?;
749        Ok(Expression::ArrayLiteral { elements, position })
750    }
751
752    /// Parse dictionary literal: `{"key": value, "key2": value2, ...}`
753    fn parse_dictionary_literal(&mut self) -> Result<Expression, ParseError> {
754        let position = self.peek().position;
755        self.expect(&TokenKind::LeftBrace, "{")?;
756
757        let mut pairs = Vec::new();
758
759        if !self.check(&TokenKind::RightBrace) {
760            loop {
761                // Key must be a string or identifier
762                let key = match &self.peek().kind {
763                    TokenKind::String(s) => {
764                        let key_pos = self.peek().position;
765                        let s = s.clone();
766                        self.advance();
767                        Expression::String {
768                            value: s,
769                            position: key_pos,
770                        }
771                    }
772                    TokenKind::Identifier(name) => {
773                        // Allow identifier as shorthand for string key
774                        let key_pos = self.peek().position;
775                        let name = name.clone();
776                        self.advance();
777                        Expression::String {
778                            value: name,
779                            position: key_pos,
780                        }
781                    }
782                    _ => {
783                        return Err(ParseError::UnexpectedToken(
784                            self.peek().kind.to_string(),
785                            self.peek().position,
786                            "string key".to_string(),
787                        ))
788                    }
789                };
790
791                self.expect(&TokenKind::Colon, ":")?;
792                let value = self.parse_expression()?;
793                pairs.push((key, value));
794
795                if !self.match_token(&TokenKind::Comma) {
796                    break;
797                }
798                // Allow trailing comma
799                if self.check(&TokenKind::RightBrace) {
800                    break;
801                }
802            }
803        }
804
805        self.expect(&TokenKind::RightBrace, "}")?;
806        Ok(Expression::DictionaryLiteral { pairs, position })
807    }
808}
809
810#[cfg(test)]
811mod tests {
812    use super::*;
813    use crate::lexer::Lexer;
814
815    fn parse(source: &str) -> Result<Program, ParseError> {
816        let mut lexer = Lexer::new(source);
817        let tokens = lexer.tokenize().expect("Lexer error");
818        let mut parser = Parser::new(tokens);
819        parser.parse()
820    }
821
822    #[test]
823    fn test_let_statement() {
824        let program = parse("let x = 10;").unwrap();
825        assert_eq!(program.statements.len(), 1);
826        assert!(matches!(
827            &program.statements[0],
828            Statement::Let { name, .. } if name == "x"
829        ));
830    }
831
832    #[test]
833    fn test_expression_statement() {
834        let program = parse("42;").unwrap();
835        assert_eq!(program.statements.len(), 1);
836        assert!(matches!(
837            &program.statements[0],
838            Statement::Expression { .. }
839        ));
840    }
841
842    #[test]
843    fn test_binary_expression() {
844        let program = parse("1 + 2 * 3;").unwrap();
845        // Should parse as 1 + (2 * 3) due to precedence
846        if let Statement::Expression { expression, .. } = &program.statements[0] {
847            assert!(matches!(
848                expression,
849                Expression::Binary {
850                    operator: BinaryOp::Add,
851                    ..
852                }
853            ));
854        } else {
855            panic!("Expected expression statement");
856        }
857    }
858
859    #[test]
860    fn test_if_statement() {
861        let program = parse("if (x > 0) { let y = 1; }").unwrap();
862        assert!(matches!(&program.statements[0], Statement::If { .. }));
863    }
864
865    #[test]
866    fn test_if_else_statement() {
867        let program = parse("if (x > 0) { let y = 1; } else { let y = 2; }").unwrap();
868        if let Statement::If { else_block, .. } = &program.statements[0] {
869            assert!(else_block.is_some());
870        } else {
871            panic!("Expected if statement");
872        }
873    }
874
875    #[test]
876    fn test_for_statement() {
877        let program = parse("for (let i = 0; i < 10; i = i + 1) { print(i); }").unwrap();
878        assert!(matches!(&program.statements[0], Statement::For { .. }));
879    }
880
881    #[test]
882    fn test_function_definition() {
883        let program = parse("fn add(a, b) { return a + b; }").unwrap();
884        if let Statement::Function { name, params, .. } = &program.statements[0] {
885            assert_eq!(name, "add");
886            assert_eq!(params, &["a", "b"]);
887        } else {
888            panic!("Expected function definition");
889        }
890    }
891
892    #[test]
893    fn test_function_call() {
894        let program = parse("print(42);").unwrap();
895        if let Statement::Expression { expression, .. } = &program.statements[0] {
896            assert!(matches!(expression, Expression::Call { function, .. } if function == "print"));
897        } else {
898            panic!("Expected expression statement");
899        }
900    }
901
902    #[test]
903    fn test_unary_expression() {
904        let program = parse("-42;").unwrap();
905        if let Statement::Expression { expression, .. } = &program.statements[0] {
906            assert!(matches!(
907                expression,
908                Expression::Unary {
909                    operator: UnaryOp::Negate,
910                    ..
911                }
912            ));
913        } else {
914            panic!("Expected expression statement");
915        }
916    }
917
918    #[test]
919    fn test_grouped_expression() {
920        let program = parse("(1 + 2) * 3;").unwrap();
921        if let Statement::Expression { expression, .. } = &program.statements[0] {
922            if let Expression::Binary {
923                left,
924                operator: BinaryOp::Multiply,
925                ..
926            } = expression
927            {
928                assert!(matches!(left.as_ref(), Expression::Grouped { .. }));
929            } else {
930                panic!("Expected multiply expression");
931            }
932        } else {
933            panic!("Expected expression statement");
934        }
935    }
936
937    #[test]
938    fn test_assignment_expression() {
939        let program = parse("x = 10;").unwrap();
940        if let Statement::Expression { expression, .. } = &program.statements[0] {
941            assert!(matches!(expression, Expression::Assignment { name, .. } if name == "x"));
942        } else {
943            panic!("Expected expression statement");
944        }
945    }
946
947    #[test]
948    fn test_return_statement() {
949        let program = parse("return 42;").unwrap();
950        assert!(matches!(
951            &program.statements[0],
952            Statement::Return { value: Some(_), .. }
953        ));
954    }
955
956    #[test]
957    fn test_empty_return() {
958        let program = parse("return;").unwrap();
959        assert!(matches!(
960            &program.statements[0],
961            Statement::Return { value: None, .. }
962        ));
963    }
964
965    #[test]
966    fn test_method_call() {
967        let program = parse(r#""hello".len();"#).unwrap();
968        if let Statement::Expression { expression, .. } = &program.statements[0] {
969            assert!(matches!(
970                expression,
971                Expression::MethodCall { method, .. } if method == "len"
972            ));
973        } else {
974            panic!("Expected expression statement with method call");
975        }
976    }
977
978    #[test]
979    fn test_method_call_with_args() {
980        let program = parse(r#"arr.push(1);"#).unwrap();
981        if let Statement::Expression { expression, .. } = &program.statements[0] {
982            if let Expression::MethodCall {
983                method, arguments, ..
984            } = expression
985            {
986                assert_eq!(method, "push");
987                assert_eq!(arguments.len(), 1);
988            } else {
989                panic!("Expected method call");
990            }
991        } else {
992            panic!("Expected expression statement");
993        }
994    }
995
996    #[test]
997    fn test_chained_method_calls() {
998        let program = parse(r#"arr.push(1).len();"#).unwrap();
999        if let Statement::Expression { expression, .. } = &program.statements[0] {
1000            // The outer call should be .len()
1001            if let Expression::MethodCall {
1002                method, receiver, ..
1003            } = expression
1004            {
1005                assert_eq!(method, "len");
1006                // The receiver should be .push(1)
1007                assert!(matches!(
1008                    receiver.as_ref(),
1009                    Expression::MethodCall { method, .. } if method == "push"
1010                ));
1011            } else {
1012                panic!("Expected method call");
1013            }
1014        } else {
1015            panic!("Expected expression statement");
1016        }
1017    }
1018
1019    #[test]
1020    fn test_method_call_on_literal() {
1021        let program = parse(r#"[1, 2, 3].len();"#).unwrap();
1022        if let Statement::Expression { expression, .. } = &program.statements[0] {
1023            if let Expression::MethodCall {
1024                method, receiver, ..
1025            } = expression
1026            {
1027                assert_eq!(method, "len");
1028                assert!(matches!(receiver.as_ref(), Expression::ArrayLiteral { .. }));
1029            } else {
1030                panic!("Expected method call");
1031            }
1032        } else {
1033            panic!("Expected expression statement");
1034        }
1035    }
1036
1037    #[test]
1038    fn test_method_call_invalid_method_name_error() {
1039        // Test that invalid method name gives helpful error message
1040        let result = parse(r#""hello".123();"#);
1041        assert!(matches!(
1042            result,
1043            Err(ParseError::UnexpectedToken(_, _, expected)) if expected == "method name"
1044        ));
1045    }
1046
1047    #[test]
1048    fn test_method_call_missing_parens_error() {
1049        // Test that missing parentheses gives error
1050        let result = parse(r#""hello".len;"#);
1051        assert!(matches!(result, Err(ParseError::UnexpectedToken(_, _, _))));
1052    }
1053}