Skip to main content

elo_rust/parser/
mod.rs

1//! Parser for ELO expressions
2//!
3//! This module provides a recursive descent parser that converts ELO token streams
4//! into an Abstract Syntax Tree (AST).
5//!
6//! The parser implements correct operator precedence through a precedence cascade:
7//! pipe > logical_or > logical_and > equality > comparison > addition > multiplication > power > unary > postfix > primary
8
9pub mod error;
10pub mod lexer;
11
12pub use error::ParseError;
13pub use lexer::{LexError, Lexer, Token};
14
15use crate::ast::{BinaryOperator, Expr, Literal, TemporalKeyword, UnaryOperator};
16
17/// Parser for ELO expressions
18///
19/// Implements a recursive descent parser with correct operator precedence.
20#[derive(Debug)]
21pub struct Parser {
22    tokens: Vec<Token>,
23    current: usize,
24}
25
26impl Parser {
27    /// Create a new parser from a token stream
28    fn new(tokens: Vec<Token>) -> Self {
29        Parser { tokens, current: 0 }
30    }
31
32    /// Parse a complete ELO expression from a string
33    ///
34    /// # Example
35    ///
36    /// ```ignore
37    /// let expr = Parser::parse("age >= 18")?;
38    /// ```
39    pub fn parse(input: &str) -> Result<Expr, ParseError> {
40        let mut lexer = Lexer::new(input);
41        let tokens = lexer
42            .tokenize()
43            .map_err(|err| ParseError::new(err.message, err.line, err.column))?;
44        let mut parser = Parser::new(tokens);
45        parser.parse_expression()
46    }
47
48    /// Parse an expression
49    fn parse_expression(&mut self) -> Result<Expr, ParseError> {
50        self.parse_pipe()
51    }
52
53    /// Peek at the current token
54    fn peek(&self) -> &Token {
55        self.tokens.get(self.current).unwrap_or(&Token::Eof)
56    }
57
58    /// Advance to the next token
59    fn advance(&mut self) -> Token {
60        let token = self.peek().clone();
61        if self.current < self.tokens.len() {
62            self.current += 1;
63        }
64        token
65    }
66
67    /// Check if the current token matches a given token
68    fn check(&self, token: &Token) -> bool {
69        std::mem::discriminant(self.peek()) == std::mem::discriminant(token)
70    }
71
72    /// Consume a specific token or return an error
73    fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
74        if self.check(&expected) {
75            self.advance();
76            Ok(())
77        } else {
78            Err(ParseError::new(
79                format!("Expected {}, found {}", expected, self.peek()),
80                1,
81                1,
82            ))
83        }
84    }
85
86    /// Parse pipe operator expressions: expr |> func() |> ...
87    fn parse_pipe(&mut self) -> Result<Expr, ParseError> {
88        let mut expr = self.parse_logical_or()?;
89
90        while self.check(&Token::Pipe) {
91            self.advance();
92            let func = self.parse_logical_or()?;
93            expr = Expr::Pipe {
94                value: Box::new(expr),
95                functions: vec![func],
96            };
97        }
98
99        Ok(expr)
100    }
101
102    /// Parse logical OR: left || right
103    fn parse_logical_or(&mut self) -> Result<Expr, ParseError> {
104        let mut expr = self.parse_logical_and()?;
105
106        while self.check(&Token::OrOr) {
107            self.advance();
108            let right = self.parse_logical_and()?;
109            expr = Expr::BinaryOp {
110                op: BinaryOperator::Or,
111                left: Box::new(expr),
112                right: Box::new(right),
113            };
114        }
115
116        Ok(expr)
117    }
118
119    /// Parse logical AND: left && right
120    fn parse_logical_and(&mut self) -> Result<Expr, ParseError> {
121        let mut expr = self.parse_equality()?;
122
123        while self.check(&Token::AndAnd) {
124            self.advance();
125            let right = self.parse_equality()?;
126            expr = Expr::BinaryOp {
127                op: BinaryOperator::And,
128                left: Box::new(expr),
129                right: Box::new(right),
130            };
131        }
132
133        Ok(expr)
134    }
135
136    /// Parse equality operators: == !=
137    fn parse_equality(&mut self) -> Result<Expr, ParseError> {
138        let mut expr = self.parse_comparison()?;
139
140        loop {
141            let op = match self.peek() {
142                Token::EqualEqual => BinaryOperator::Eq,
143                Token::NotEqual => BinaryOperator::Neq,
144                _ => break,
145            };
146            self.advance();
147            let right = self.parse_comparison()?;
148            expr = Expr::BinaryOp {
149                op,
150                left: Box::new(expr),
151                right: Box::new(right),
152            };
153        }
154
155        Ok(expr)
156    }
157
158    /// Parse comparison operators: < > <= >=
159    fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
160        let mut expr = self.parse_addition()?;
161
162        loop {
163            let op = match self.peek() {
164                Token::Less => BinaryOperator::Lt,
165                Token::LessEqual => BinaryOperator::Lte,
166                Token::Greater => BinaryOperator::Gt,
167                Token::GreaterEqual => BinaryOperator::Gte,
168                _ => break,
169            };
170            self.advance();
171            let right = self.parse_addition()?;
172            expr = Expr::BinaryOp {
173                op,
174                left: Box::new(expr),
175                right: Box::new(right),
176            };
177        }
178
179        Ok(expr)
180    }
181
182    /// Parse addition and subtraction: + -
183    fn parse_addition(&mut self) -> Result<Expr, ParseError> {
184        let mut expr = self.parse_multiplication()?;
185
186        loop {
187            let op = match self.peek() {
188                Token::Plus => BinaryOperator::Add,
189                Token::Minus => BinaryOperator::Sub,
190                _ => break,
191            };
192            self.advance();
193            let right = self.parse_multiplication()?;
194            expr = Expr::BinaryOp {
195                op,
196                left: Box::new(expr),
197                right: Box::new(right),
198            };
199        }
200
201        Ok(expr)
202    }
203
204    /// Parse multiplication, division, modulo: * / %
205    fn parse_multiplication(&mut self) -> Result<Expr, ParseError> {
206        let mut expr = self.parse_power()?;
207
208        loop {
209            let op = match self.peek() {
210                Token::Star => BinaryOperator::Mul,
211                Token::Slash => BinaryOperator::Div,
212                Token::Percent => BinaryOperator::Mod,
213                _ => break,
214            };
215            self.advance();
216            let right = self.parse_power()?;
217            expr = Expr::BinaryOp {
218                op,
219                left: Box::new(expr),
220                right: Box::new(right),
221            };
222        }
223
224        Ok(expr)
225    }
226
227    /// Parse exponentiation: ^
228    fn parse_power(&mut self) -> Result<Expr, ParseError> {
229        let mut expr = self.parse_unary()?;
230
231        if self.check(&Token::Caret) {
232            self.advance();
233            let right = self.parse_power()?; // Right-associative
234            expr = Expr::BinaryOp {
235                op: BinaryOperator::Pow,
236                left: Box::new(expr),
237                right: Box::new(right),
238            };
239        }
240
241        Ok(expr)
242    }
243
244    /// Parse unary operators: ! - +
245    fn parse_unary(&mut self) -> Result<Expr, ParseError> {
246        match self.peek() {
247            Token::Bang => {
248                self.advance();
249                let operand = self.parse_unary()?;
250                Ok(Expr::UnaryOp {
251                    op: UnaryOperator::Not,
252                    operand: Box::new(operand),
253                })
254            }
255            Token::Minus => {
256                self.advance();
257                let operand = self.parse_unary()?;
258                Ok(Expr::UnaryOp {
259                    op: UnaryOperator::Neg,
260                    operand: Box::new(operand),
261                })
262            }
263            Token::Plus => {
264                self.advance();
265                let operand = self.parse_unary()?;
266                Ok(Expr::UnaryOp {
267                    op: UnaryOperator::Plus,
268                    operand: Box::new(operand),
269                })
270            }
271            _ => self.parse_postfix(),
272        }
273    }
274
275    /// Parse postfix expressions: field access, function calls, etc.
276    fn parse_postfix(&mut self) -> Result<Expr, ParseError> {
277        let mut expr = self.parse_primary()?;
278
279        loop {
280            match self.peek() {
281                Token::Dot => {
282                    self.advance();
283                    match self.advance() {
284                        Token::Identifier(field) => {
285                            expr = Expr::FieldAccess {
286                                receiver: Box::new(expr),
287                                field,
288                            };
289                        }
290                        _ => {
291                            return Err(ParseError::new("Expected field name after '.'", 1, 1));
292                        }
293                    }
294                }
295                Token::LeftBracket => {
296                    // Array access (not fully implemented in MVP)
297                    break;
298                }
299                Token::LeftParen if matches!(expr, Expr::Identifier(_)) => {
300                    // This is a function call - handle it in primary instead
301                    break;
302                }
303                _ => break,
304            }
305        }
306
307        Ok(expr)
308    }
309
310    /// Parse primary expressions: literals, identifiers, function calls, etc.
311    fn parse_primary(&mut self) -> Result<Expr, ParseError> {
312        match self.peek() {
313            Token::Integer(n) => {
314                let value = *n;
315                self.advance();
316                Ok(Expr::Literal(Literal::Integer(value)))
317            }
318            Token::Float(f) => {
319                let value = *f;
320                self.advance();
321                Ok(Expr::Literal(Literal::Float(value)))
322            }
323            Token::True => {
324                self.advance();
325                Ok(Expr::Literal(Literal::Boolean(true)))
326            }
327            Token::False => {
328                self.advance();
329                Ok(Expr::Literal(Literal::Boolean(false)))
330            }
331            Token::Null => {
332                self.advance();
333                Ok(Expr::Null)
334            }
335            Token::String(s) => {
336                let value = s.clone();
337                self.advance();
338                Ok(Expr::String(value))
339            }
340            Token::Identifier(name) => {
341                let name = name.clone();
342                self.advance();
343
344                // Check for function call
345                if self.check(&Token::LeftParen) {
346                    self.advance();
347                    let args = self.parse_function_args()?;
348                    self.expect(Token::RightParen)?;
349                    Ok(Expr::FunctionCall { name, args })
350                } else {
351                    Ok(Expr::Identifier(name))
352                }
353            }
354            Token::LeftParen => {
355                self.advance();
356                let expr = self.parse_expression()?;
357                self.expect(Token::RightParen)?;
358                Ok(expr)
359            }
360            Token::LeftBracket => {
361                self.advance();
362                let elements = self.parse_array_elements()?;
363                self.expect(Token::RightBracket)?;
364                Ok(Expr::Array(elements))
365            }
366            Token::LeftBrace => {
367                self.advance();
368                let fields = self.parse_object_fields()?;
369                self.expect(Token::RightBrace)?;
370                Ok(Expr::Object(fields))
371            }
372            Token::Let => self.parse_let(),
373            Token::If => self.parse_if(),
374            Token::Fn => self.parse_lambda(),
375            Token::Guard => self.parse_guard(),
376            Token::Now => {
377                self.advance();
378                Ok(Expr::TemporalKeyword(TemporalKeyword::Now))
379            }
380            Token::Today => {
381                self.advance();
382                Ok(Expr::TemporalKeyword(TemporalKeyword::Today))
383            }
384            Token::Tomorrow => {
385                self.advance();
386                Ok(Expr::TemporalKeyword(TemporalKeyword::Tomorrow))
387            }
388            Token::Yesterday => {
389                self.advance();
390                Ok(Expr::TemporalKeyword(TemporalKeyword::Yesterday))
391            }
392            Token::StartOfDay => {
393                self.advance();
394                Ok(Expr::TemporalKeyword(TemporalKeyword::StartOfDay))
395            }
396            Token::EndOfDay => {
397                self.advance();
398                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfDay))
399            }
400            Token::StartOfWeek => {
401                self.advance();
402                Ok(Expr::TemporalKeyword(TemporalKeyword::StartOfWeek))
403            }
404            Token::EndOfWeek => {
405                self.advance();
406                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfWeek))
407            }
408            Token::StartOfMonth => {
409                self.advance();
410                Ok(Expr::TemporalKeyword(TemporalKeyword::StartOfMonth))
411            }
412            Token::EndOfMonth => {
413                self.advance();
414                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfMonth))
415            }
416            Token::StartOfQuarter => {
417                self.advance();
418                Ok(Expr::TemporalKeyword(TemporalKeyword::StartOfQuarter))
419            }
420            Token::EndOfQuarter => {
421                self.advance();
422                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfQuarter))
423            }
424            Token::StartOfYear => {
425                self.advance();
426                Ok(Expr::TemporalKeyword(TemporalKeyword::StartOfYear))
427            }
428            Token::EndOfYear => {
429                self.advance();
430                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfYear))
431            }
432            Token::BeginningOfTime => {
433                self.advance();
434                Ok(Expr::TemporalKeyword(TemporalKeyword::BeginningOfTime))
435            }
436            Token::EndOfTime => {
437                self.advance();
438                Ok(Expr::TemporalKeyword(TemporalKeyword::EndOfTime))
439            }
440            _ => Err(ParseError::new(
441                format!("Unexpected token: {}", self.peek()),
442                1,
443                1,
444            )),
445        }
446    }
447
448    /// Parse function call arguments
449    fn parse_function_args(&mut self) -> Result<Vec<Expr>, ParseError> {
450        let mut args = Vec::new();
451
452        if !self.check(&Token::RightParen) {
453            loop {
454                args.push(self.parse_expression()?);
455                if !self.check(&Token::Comma) {
456                    break;
457                }
458                self.advance();
459            }
460        }
461
462        Ok(args)
463    }
464
465    /// Parse array literal elements
466    fn parse_array_elements(&mut self) -> Result<Vec<Expr>, ParseError> {
467        let mut elements = Vec::new();
468
469        if !self.check(&Token::RightBracket) {
470            loop {
471                elements.push(self.parse_expression()?);
472                if !self.check(&Token::Comma) {
473                    break;
474                }
475                self.advance();
476            }
477        }
478
479        Ok(elements)
480    }
481
482    /// Parse object literal fields
483    fn parse_object_fields(&mut self) -> Result<Vec<(String, Expr)>, ParseError> {
484        let mut fields = Vec::new();
485
486        if !self.check(&Token::RightBrace) {
487            loop {
488                let key = match self.advance() {
489                    Token::Identifier(name) => name,
490                    Token::String(s) => s,
491                    _ => {
492                        return Err(ParseError::new(
493                            "Expected field name in object literal",
494                            1,
495                            1,
496                        ))
497                    }
498                };
499
500                self.expect(Token::Colon)?;
501                let value = self.parse_expression()?;
502                fields.push((key, value));
503
504                if !self.check(&Token::Comma) {
505                    break;
506                }
507                self.advance();
508            }
509        }
510
511        Ok(fields)
512    }
513
514    /// Parse let expression: let name = value in body
515    fn parse_let(&mut self) -> Result<Expr, ParseError> {
516        self.expect(Token::Let)?;
517
518        let name = match self.advance() {
519            Token::Identifier(n) => n,
520            _ => return Err(ParseError::new("Expected variable name after 'let'", 1, 1)),
521        };
522
523        self.expect(Token::Equal)?;
524        let value = Box::new(self.parse_expression()?);
525
526        self.expect(Token::In)?;
527        let body = Box::new(self.parse_expression()?);
528
529        Ok(Expr::Let { name, value, body })
530    }
531
532    /// Parse if expression: if condition then branch_a else branch_b
533    fn parse_if(&mut self) -> Result<Expr, ParseError> {
534        self.expect(Token::If)?;
535        let condition = Box::new(self.parse_expression()?);
536        self.expect(Token::Then)?;
537        let then_branch = Box::new(self.parse_expression()?);
538        self.expect(Token::Else)?;
539        let else_branch = Box::new(self.parse_expression()?);
540
541        Ok(Expr::If {
542            condition,
543            then_branch,
544            else_branch,
545        })
546    }
547
548    /// Parse lambda expression: fn(param ~> body) or (param ~> body)
549    fn parse_lambda(&mut self) -> Result<Expr, ParseError> {
550        self.expect(Token::Fn)?;
551        self.expect(Token::LeftParen)?;
552
553        let param = match self.advance() {
554            Token::Identifier(p) => p,
555            _ => return Err(ParseError::new("Expected parameter name in lambda", 1, 1)),
556        };
557
558        self.expect(Token::LambdaArrow)?;
559        let body = Box::new(self.parse_expression()?);
560        self.expect(Token::RightParen)?;
561
562        Ok(Expr::Lambda { param, body })
563    }
564
565    /// Parse guard expression: guard condition in body
566    fn parse_guard(&mut self) -> Result<Expr, ParseError> {
567        self.expect(Token::Guard)?;
568        let condition = Box::new(self.parse_expression()?);
569        self.expect(Token::In)?;
570        let body = Box::new(self.parse_expression()?);
571
572        Ok(Expr::Guard { condition, body })
573    }
574}
575
576#[cfg(test)]
577mod tests {
578    use super::*;
579
580    #[test]
581    fn test_parse_integer() {
582        let expr = Parser::parse("42").unwrap();
583        assert_eq!(expr, Expr::Literal(Literal::Integer(42)));
584    }
585
586    #[test]
587    fn test_parse_float() {
588        let expr = Parser::parse("3.15").unwrap();
589        assert_eq!(expr, Expr::Literal(Literal::Float(3.15)));
590    }
591
592    #[test]
593    fn test_parse_boolean() {
594        let expr = Parser::parse("true").unwrap();
595        assert_eq!(expr, Expr::Literal(Literal::Boolean(true)));
596    }
597
598    #[test]
599    fn test_parse_identifier() {
600        let expr = Parser::parse("age").unwrap();
601        assert_eq!(expr, Expr::Identifier("age".to_string()));
602    }
603
604    #[test]
605    fn test_parse_binary_op() {
606        let expr = Parser::parse("1 + 2").unwrap();
607        match expr {
608            Expr::BinaryOp {
609                op: BinaryOperator::Add,
610                ..
611            } => {}
612            _ => panic!("Expected binary add operation"),
613        }
614    }
615
616    #[test]
617    fn test_parse_comparison() {
618        let expr = Parser::parse("age >= 18").unwrap();
619        match expr {
620            Expr::BinaryOp {
621                op: BinaryOperator::Gte,
622                ..
623            } => {}
624            _ => panic!("Expected >= operator"),
625        }
626    }
627
628    #[test]
629    fn test_parse_logical_and() {
630        let expr = Parser::parse("true && false").unwrap();
631        match expr {
632            Expr::BinaryOp {
633                op: BinaryOperator::And,
634                ..
635            } => {}
636            _ => panic!("Expected && operator"),
637        }
638    }
639
640    #[test]
641    fn test_parse_logical_or() {
642        let expr = Parser::parse("true || false").unwrap();
643        match expr {
644            Expr::BinaryOp {
645                op: BinaryOperator::Or,
646                ..
647            } => {}
648            _ => panic!("Expected || operator"),
649        }
650    }
651
652    #[test]
653    fn test_parse_field_access() {
654        let expr = Parser::parse("user.age").unwrap();
655        match expr {
656            Expr::FieldAccess { field, .. } => {
657                assert_eq!(field, "age");
658            }
659            _ => panic!("Expected field access"),
660        }
661    }
662
663    #[test]
664    fn test_parse_function_call() {
665        let expr = Parser::parse("length(name)").unwrap();
666        match expr {
667            Expr::FunctionCall { name, args } => {
668                assert_eq!(name, "length");
669                assert_eq!(args.len(), 1);
670            }
671            _ => panic!("Expected function call"),
672        }
673    }
674
675    #[test]
676    fn test_parse_function_multiple_args() {
677        let expr = Parser::parse("substring(name, 0, 5)").unwrap();
678        match expr {
679            Expr::FunctionCall { args, .. } => {
680                assert_eq!(args.len(), 3);
681            }
682            _ => panic!("Expected function call with 3 args"),
683        }
684    }
685
686    #[test]
687    fn test_parse_array_literal() {
688        let expr = Parser::parse("[1, 2, 3]").unwrap();
689        match expr {
690            Expr::Array(elements) => {
691                assert_eq!(elements.len(), 3);
692            }
693            _ => panic!("Expected array literal"),
694        }
695    }
696
697    #[test]
698    fn test_parse_object_literal() {
699        let expr = Parser::parse("{x: 1, y: 2}").unwrap();
700        match expr {
701            Expr::Object(fields) => {
702                assert_eq!(fields.len(), 2);
703            }
704            _ => panic!("Expected object literal"),
705        }
706    }
707
708    #[test]
709    fn test_parse_null() {
710        let expr = Parser::parse("null").unwrap();
711        assert_eq!(expr, Expr::Null);
712    }
713
714    #[test]
715    fn test_parse_string_literal() {
716        let expr = Parser::parse("'hello'").unwrap();
717        assert_eq!(expr, Expr::String("hello".to_string()));
718    }
719
720    #[test]
721    fn test_parse_temporal_keyword() {
722        let expr = Parser::parse("NOW").unwrap();
723        assert_eq!(expr, Expr::TemporalKeyword(TemporalKeyword::Now));
724    }
725
726    #[test]
727    fn test_operator_precedence_add_mul() {
728        let expr = Parser::parse("1 + 2 * 3").unwrap();
729        // Should be 1 + (2 * 3), not (1 + 2) * 3
730        match expr {
731            Expr::BinaryOp {
732                op: BinaryOperator::Add,
733                right,
734                ..
735            } => {
736                match *right {
737                    Expr::BinaryOp {
738                        op: BinaryOperator::Mul,
739                        ..
740                    } => {} // Correct
741                    _ => panic!("Expected multiplication to have higher precedence"),
742                }
743            }
744            _ => panic!("Expected addition at top level"),
745        }
746    }
747
748    #[test]
749    fn test_operator_precedence_pow() {
750        let expr = Parser::parse("2 ^ 3 ^ 2").unwrap();
751        // Power is right-associative: 2 ^ (3 ^ 2)
752        match expr {
753            Expr::BinaryOp {
754                op: BinaryOperator::Pow,
755                right,
756                ..
757            } => {
758                match *right {
759                    Expr::BinaryOp {
760                        op: BinaryOperator::Pow,
761                        ..
762                    } => {} // Correct (right-associative)
763                    _ => panic!("Expected power to be right-associative"),
764                }
765            }
766            _ => panic!("Expected power operation"),
767        }
768    }
769
770    #[test]
771    fn test_unary_not() {
772        let expr = Parser::parse("!true").unwrap();
773        match expr {
774            Expr::UnaryOp {
775                op: UnaryOperator::Not,
776                ..
777            } => {}
778            _ => panic!("Expected unary not"),
779        }
780    }
781
782    #[test]
783    fn test_unary_neg() {
784        let expr = Parser::parse("-42").unwrap();
785        match expr {
786            Expr::UnaryOp {
787                op: UnaryOperator::Neg,
788                ..
789            } => {}
790            _ => panic!("Expected unary negation"),
791        }
792    }
793
794    #[test]
795    fn test_parse_if_expression() {
796        let _expr = Parser::parse("if true then 1 else 0").unwrap();
797        // Just check it parses without error
798    }
799
800    #[test]
801    fn test_parse_temporal_keywords() {
802        let expr = Parser::parse("TODAY").unwrap();
803        assert_eq!(expr, Expr::TemporalKeyword(TemporalKeyword::Today));
804    }
805
806    #[test]
807    fn test_error_unexpected_token() {
808        let result = Parser::parse("@invalid");
809        assert!(result.is_err());
810    }
811
812    #[test]
813    fn test_parentheses() {
814        let expr = Parser::parse("(1 + 2) * 3").unwrap();
815        match expr {
816            Expr::BinaryOp {
817                op: BinaryOperator::Mul,
818                left,
819                ..
820            } => {
821                match *left {
822                    Expr::BinaryOp {
823                        op: BinaryOperator::Add,
824                        ..
825                    } => {} // Correct
826                    _ => panic!("Expected addition inside parentheses"),
827                }
828            }
829            _ => panic!("Expected multiplication at top level"),
830        }
831    }
832
833    #[test]
834    fn test_complex_expression() {
835        let expr = Parser::parse("user.age >= 18 && isActive").unwrap();
836        match expr {
837            Expr::BinaryOp {
838                op: BinaryOperator::And,
839                ..
840            } => {}
841            _ => panic!("Expected logical AND at top level"),
842        }
843    }
844}