expr_solver/
parser.rs

1use crate::ast::{BinOp, Expr, UnOp};
2use crate::lexer::Lexer;
3use crate::source::Source;
4use crate::span::{Span, SpanError};
5use crate::token::Token;
6use thiserror::Error;
7
8/// Expression parsing errors.
9#[derive(Error, Debug, Clone)]
10pub enum ParseError {
11    #[error("Unexpected token '{found}', expected '{expected}'")]
12    UnexpectedToken {
13        found: String,
14        expected: String,
15        span: Span,
16    },
17}
18
19impl SpanError for ParseError {
20    fn span(&self) -> Span {
21        match self {
22            ParseError::UnexpectedToken { span, .. } => *span,
23        }
24    }
25}
26
27pub type ParseResult<'src, 'sym> = Result<Expr<'src, 'sym>, ParseError>;
28
29pub struct Parser<'src> {
30    lexer: Lexer<'src>,
31    lookahead: Token<'src>,
32    span: Span,
33}
34
35impl<'src, 'sym> Parser<'src> {
36    pub fn new(source: &'src Source) -> Self {
37        let mut lexer = Lexer::new(source);
38        let lookahead = lexer.next();
39        let span = lexer.span();
40        Self {
41            lexer,
42            lookahead,
43            span,
44        }
45    }
46
47    pub fn parse(&mut self) -> Result<Option<Expr<'src, 'sym>>, ParseError> {
48        if self.lookahead == Token::EOF {
49            return Ok(None);
50        }
51        let expr = self.expression()?;
52        self.expect(&Token::EOF)?;
53        Ok(Some(expr))
54    }
55
56    fn expression(&mut self) -> ParseResult<'src, 'sym> {
57        let lhs = self.primary()?;
58        self.climb(lhs, 1)
59    }
60
61    fn primary(&mut self) -> ParseResult<'src, 'sym> {
62        let span = self.span;
63        match self.lookahead {
64            Token::Number(n) => {
65                self.advance();
66                Ok(Expr::literal(n, span))
67            }
68            Token::Ident(id) => {
69                self.advance();
70                if self.lookahead == Token::ParenOpen {
71                    return self.call(id, span);
72                }
73                Ok(Expr::ident(id, span))
74            }
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                found: self.lookahead.lexeme().to_string(),
90                expected: "an expression".to_string(),
91                span,
92            }),
93        }
94    }
95
96    fn call(&mut self, id: &'src str, span: Span) -> ParseResult<'src, 'sym> {
97        // assume lookahead is '('
98        self.advance();
99
100        let mut args: Vec<Expr<'src, 'sym>> = Vec::new();
101        while self.lookahead != Token::ParenClose {
102            let arg = self.expression()?;
103            args.push(arg);
104            if self.lookahead == Token::Comma {
105                self.advance();
106            } else {
107                break;
108            }
109        }
110        self.expect(&Token::ParenClose)?;
111
112        let span = span.merge(self.span);
113        Ok(Expr::call(id, args, span))
114    }
115
116    fn climb(&mut self, mut lhs: Expr<'src, 'sym>, min_prec: u8) -> ParseResult<'src, 'sym> {
117        let mut prec = self.lookahead.precedence();
118        while prec >= min_prec {
119            // Handle postfix unary operators
120            if self.lookahead.is_postfix_unary() {
121                let op = self.lookahead.clone();
122                let op_span = self.span;
123                self.advance();
124                prec = self.lookahead.precedence();
125
126                let unary_op = UnOp::from_token(&op);
127                let span = lhs.span.merge(op_span);
128                lhs = Expr::unary(unary_op, lhs, span);
129                continue;
130            }
131
132            let op = self.lookahead.clone();
133
134            self.advance();
135            let mut rhs = self.primary()?;
136            prec = self.lookahead.precedence();
137
138            while prec > op.precedence()
139                || (self.lookahead.is_right_associative() && prec == op.precedence())
140            {
141                rhs = self.climb(rhs, prec)?;
142                prec = self.lookahead.precedence();
143            }
144
145            let op = BinOp::from_token(&op);
146            let span = lhs.span.merge(rhs.span);
147            lhs = Expr::binary(op, lhs, rhs, span);
148        }
149        Ok(lhs)
150    }
151
152    fn advance(&mut self) {
153        self.lookahead = self.lexer.next();
154        self.span = self.lexer.span();
155    }
156
157    fn accept(&mut self, t: &Token<'src>) -> bool {
158        if self.lookahead == *t {
159            self.advance();
160            true
161        } else {
162            false
163        }
164    }
165
166    fn expect(&mut self, tkn: &Token<'src>) -> Result<(), ParseError> {
167        if !self.accept(tkn) {
168            return Err(ParseError::UnexpectedToken {
169                found: self.lookahead.lexeme().to_string(),
170                expected: tkn.lexeme().to_string(),
171                span: self.span,
172            });
173        }
174        Ok(())
175    }
176}