expr_solver/
parser.rs

1//! Recursive descent parser for mathematical expressions.
2
3use super::ast::{Expr, UnOp};
4use super::error::ParseError;
5use super::lexer::Lexer;
6use crate::span::Span;
7use crate::token::Token;
8
9pub type ParseResult<'src> = Result<Expr<'src>, ParseError>;
10
11/// Recursive descent parser for mathematical expressions.
12///
13/// Uses operator precedence climbing for efficient binary operator parsing.
14///
15/// # Examples
16///
17/// ```
18/// use expr_solver::Parser;
19///
20/// let mut parser = Parser::new("2 + 3 * 4");
21/// let ast = parser.parse().unwrap();
22/// assert!(ast.is_some());
23/// ```
24pub struct Parser<'src> {
25    lexer: Lexer<'src>,
26    lookahead: Token<'src>,
27    span: Span,
28}
29
30impl<'src> Parser<'src> {
31    /// Creates a new parser from a string slice.
32    pub fn new(input: &'src str) -> Self {
33        let mut lexer = Lexer::new(input);
34        let lookahead = lexer.next();
35        let span = lexer.span();
36        Self {
37            lexer,
38            lookahead,
39            span,
40        }
41    }
42    /// Parses the source into an abstract syntax tree.
43    ///
44    /// Returns `None` for empty input, or an expression AST on success.
45    pub fn parse(&mut self) -> Result<Option<Expr<'src>>, ParseError> {
46        if self.lookahead == Token::Eof {
47            return Ok(None);
48        }
49        let expr = self.expression()?;
50        self.expect(&Token::Eof)?;
51        Ok(Some(expr))
52    }
53
54    fn expression(&mut self) -> ParseResult<'src> {
55        let lhs = self.primary()?;
56        self.climb(lhs, 1)
57    }
58
59    fn primary(&mut self) -> ParseResult<'src> {
60        let span = self.span;
61        match self.lookahead {
62            Token::Number(n) => {
63                self.advance();
64                Ok(Expr::literal(n, span))
65            }
66            Token::Ident(id) => {
67                self.advance();
68                if self.lookahead == Token::ParenOpen {
69                    return self.call(id, span);
70                }
71                Ok(Expr::ident(id, span))
72            }
73            Token::If => self.if_expr(span),
74            Token::Let => self.let_expr(span),
75            Token::Minus => {
76                self.advance();
77                let expr = self.primary()?;
78                let expr = self.climb(expr, Token::Negate.precedence())?;
79                let span = self.span.merge(expr.span);
80                Ok(Expr::unary(UnOp::Neg, expr, span))
81            }
82            Token::ParenOpen => {
83                self.advance();
84                let expr = self.expression()?;
85                self.expect(&Token::ParenClose)?;
86                Ok(expr)
87            }
88            _ => Err(ParseError::UnexpectedToken {
89                message: format!(
90                    "unexpected token '{}', expected an expression",
91                    self.lookahead.lexeme()
92                ),
93                span,
94            }),
95        }
96    }
97
98    fn call(&mut self, id: &'src str, span: Span) -> ParseResult<'src> {
99        // assume lookahead is '('
100        self.advance();
101
102        let mut args: Vec<Expr> = Vec::new();
103        while self.lookahead != Token::ParenClose {
104            let arg = self.expression()?;
105            args.push(arg);
106            if self.lookahead == Token::Comma {
107                self.advance();
108            } else {
109                break;
110            }
111        }
112        self.expect(&Token::ParenClose)?;
113
114        let span = span.merge(self.span);
115        Ok(Expr::call(id, args, span))
116    }
117
118    fn climb(&mut self, mut lhs: Expr<'src>, min_prec: u8) -> ParseResult<'src> {
119        let mut prec = self.lookahead.precedence();
120        while prec >= min_prec {
121            // Handle postfix unary operators
122            if self.lookahead.is_postfix_unary() {
123                let op = self.lookahead.clone();
124                let op_span = self.span;
125                self.advance();
126                prec = self.lookahead.precedence();
127
128                let span = lhs.span.merge(op_span);
129                lhs = Expr::unary(op.into(), lhs, span);
130                continue;
131            }
132
133            let op = self.lookahead.clone();
134
135            self.advance();
136            let mut rhs = self.primary()?;
137            prec = self.lookahead.precedence();
138
139            while prec > op.precedence()
140                || (self.lookahead.is_right_associative() && prec == op.precedence())
141            {
142                rhs = self.climb(rhs, prec)?;
143                prec = self.lookahead.precedence();
144            }
145
146            let span = lhs.span.merge(rhs.span);
147            lhs = Expr::binary(op.into(), lhs, rhs, span);
148        }
149        Ok(lhs)
150    }
151
152    fn if_expr(&mut self, span: Span) -> ParseResult<'src> {
153        // Expect: if(cond, then_branch, else_branch)
154
155        // assume lookahead is 'if'
156        self.advance();
157
158        // Self::expect_token(lexer, lookahead, span, &Token::ParenOpen)?;
159        self.expect(&Token::ParenOpen)?;
160
161        // Parse condition
162        let cond = self.expression()?;
163        self.expect(&Token::Comma)?;
164
165        // Parse then branch
166        let then_branch = self.expression()?;
167        self.expect(&Token::Comma)?;
168
169        // Parse else branch
170        let else_branch = self.expression()?;
171        self.expect(&Token::ParenClose)?;
172
173        let span = span.merge(self.span);
174        Ok(Expr::if_expr(cond, then_branch, else_branch, span))
175    }
176
177    fn let_expr(&mut self, span: Span) -> ParseResult<'src> {
178        // Expect: let name = expr, name = expr, ... then body
179        self.advance(); // consume 'let'
180
181        // Parse at least one declaration
182        let mut decls = vec![self.parse_let_decl()?];
183
184        // Parse remaining declarations separated by commas
185        while self.accept(&Token::Comma) {
186            decls.push(self.parse_let_decl()?);
187        }
188
189        // Expect 'then'
190        self.expect(&Token::Then)?;
191
192        // Parse body
193        let body = self.expression()?;
194
195        let span = span.merge(self.span);
196        Ok(Expr::let_expr(decls, body, span))
197    }
198
199    fn parse_let_decl(&mut self) -> Result<(&'src str, Expr<'src>), ParseError> {
200        // Parse: name = expr
201        let name = self.ident()?;
202        self.expect(&Token::Assign)?;
203        let expr = self.expression()?;
204        Ok((name, expr))
205    }
206
207    fn ident(&mut self) -> Result<&'src str, ParseError> {
208        match self.lookahead {
209            Token::Ident(id) => {
210                self.advance();
211                Ok(id)
212            }
213            _ => Err(ParseError::UnexpectedToken {
214                message: format!(
215                    "expected identifier in let declaration, found '{}'",
216                    self.lookahead.lexeme()
217                ),
218                span: self.span,
219            }),
220        }
221    }
222
223    fn advance(&mut self) {
224        self.lookahead = self.lexer.next();
225        self.span = self.lexer.span();
226    }
227
228    fn accept(&mut self, t: &Token<'src>) -> bool {
229        if self.lookahead == *t {
230            self.advance();
231            true
232        } else {
233            false
234        }
235    }
236
237    fn expect(&mut self, tkn: &Token<'src>) -> Result<(), ParseError> {
238        if !self.accept(tkn) {
239            return Err(ParseError::UnexpectedToken {
240                message: format!(
241                    "unexpected token '{}', expected '{}'",
242                    self.lookahead.lexeme(),
243                    tkn.lexeme()
244                ),
245                span: self.span,
246            });
247        }
248        Ok(())
249    }
250}