1use crate::ast::{BinOp, Expr, UnaryOp};
5use crate::tokenizer::{Token, tokenize};
6
7pub struct Parser {
8 tokens: Vec<Token>,
9 pos: usize,
10}
11
12impl Parser {
13 pub fn new(tokens: Vec<Token>) -> Self {
14 Parser { tokens, pos: 0 }
15 }
16
17 fn peek(&self) -> Option<&Token> {
18 self.tokens.get(self.pos)
19 }
20
21 fn advance(&mut self) -> Option<Token> {
22 if self.pos < self.tokens.len() {
23 let t = self.tokens[self.pos].clone();
24 self.pos += 1;
25 Some(t)
26 } else {
27 None
28 }
29 }
30
31 fn expect(&mut self, expected: &Token) -> Result<(), String> {
32 let t = self.advance().ok_or("Unexpected end of input")?;
33 if &t != expected {
34 return Err(format!("Expected {:?}, got {:?}", expected, t));
35 }
36 Ok(())
37 }
38
39 pub fn parse_formula(input: &str) -> Result<Expr, String> {
41 let trimmed = input.trim();
42 let formula = if trimmed.starts_with('=') { &trimmed[1..] } else { trimmed };
44 let tokens = tokenize(formula)?;
45 let mut parser = Parser::new(tokens);
46 let expr = parser.parse_comparison()?;
47 if parser.pos < parser.tokens.len() {
48 return Err(format!("Unexpected token at position {}", parser.pos));
49 }
50 Ok(expr)
51 }
52
53 fn parse_comparison(&mut self) -> Result<Expr, String> {
64 let mut left = self.parse_concat()?;
65 loop {
66 let op = match self.peek() {
67 Some(Token::Eq) => BinOp::Eq,
68 Some(Token::Neq) => BinOp::Neq,
69 Some(Token::Lt) => BinOp::Lt,
70 Some(Token::Gt) => BinOp::Gt,
71 Some(Token::Lte) => BinOp::Lte,
72 Some(Token::Gte) => BinOp::Gte,
73 _ => break,
74 };
75 self.advance();
76 let right = self.parse_concat()?;
77 left = Expr::BinaryOp {
78 op,
79 left: Box::new(left),
80 right: Box::new(right),
81 };
82 }
83 Ok(left)
84 }
85
86 fn parse_concat(&mut self) -> Result<Expr, String> {
87 let mut left = self.parse_addition()?;
88 loop {
89 if matches!(self.peek(), Some(Token::Amp)) {
90 self.advance();
91 let right = self.parse_addition()?;
92 left = Expr::BinaryOp {
93 op: BinOp::Concat,
94 left: Box::new(left),
95 right: Box::new(right),
96 };
97 } else {
98 break;
99 }
100 }
101 Ok(left)
102 }
103
104 fn parse_addition(&mut self) -> Result<Expr, String> {
105 let mut left = self.parse_multiplication()?;
106 loop {
107 let op = match self.peek() {
108 Some(Token::Plus) => BinOp::Add,
109 Some(Token::Minus) => BinOp::Sub,
110 _ => break,
111 };
112 self.advance();
113 let right = self.parse_multiplication()?;
114 left = Expr::BinaryOp {
115 op,
116 left: Box::new(left),
117 right: Box::new(right),
118 };
119 }
120 Ok(left)
121 }
122
123 fn parse_multiplication(&mut self) -> Result<Expr, String> {
124 let mut left = self.parse_power()?;
125 loop {
126 let op = match self.peek() {
127 Some(Token::Star) => BinOp::Mul,
128 Some(Token::Slash) => BinOp::Div,
129 _ => break,
130 };
131 self.advance();
132 let right = self.parse_power()?;
133 left = Expr::BinaryOp {
134 op,
135 left: Box::new(left),
136 right: Box::new(right),
137 };
138 }
139 Ok(left)
140 }
141
142 fn parse_power(&mut self) -> Result<Expr, String> {
143 let mut left = self.parse_unary()?;
144 if matches!(self.peek(), Some(Token::Caret)) {
145 self.advance();
146 let right = self.parse_unary()?; left = Expr::BinaryOp {
148 op: BinOp::Pow,
149 left: Box::new(left),
150 right: Box::new(right),
151 };
152 }
153 Ok(left)
154 }
155
156 fn parse_unary(&mut self) -> Result<Expr, String> {
157 if matches!(self.peek(), Some(Token::Minus)) {
158 self.advance();
159 let operand = self.parse_unary()?;
160 return Ok(Expr::UnaryOp {
161 op: UnaryOp::Negate,
162 operand: Box::new(operand),
163 });
164 }
165 self.parse_percent()
166 }
167
168 fn parse_percent(&mut self) -> Result<Expr, String> {
169 let mut expr = self.parse_primary()?;
170 while matches!(self.peek(), Some(Token::Percent)) {
171 self.advance();
172 expr = Expr::Percent(Box::new(expr));
173 }
174 Ok(expr)
175 }
176
177 fn parse_primary(&mut self) -> Result<Expr, String> {
178 let token = self.advance().ok_or("Unexpected end of input")?;
179 match token {
180 Token::Number(n) => Ok(Expr::Number(n)),
181 Token::String(s) => Ok(Expr::String(s)),
182 Token::CellRef(c) => Ok(Expr::CellRef(c)),
183 Token::Range(r) => Ok(Expr::Range(r)),
184 Token::LParen => {
185 let expr = self.parse_comparison()?;
186 self.expect(&Token::RParen).map_err(|e| format!("{} (expected closing paren)", e))?;
187 Ok(expr)
188 }
189 Token::Ident(name) => {
190 if matches!(self.peek(), Some(Token::LParen)) {
192 self.advance(); let mut args = Vec::new();
194 if !matches!(self.peek(), Some(Token::RParen)) {
195 args.push(self.parse_comparison()?);
196 while matches!(self.peek(), Some(Token::Comma)) {
197 self.advance();
198 args.push(self.parse_comparison()?);
199 }
200 }
201 self.expect(&Token::RParen).map_err(|e| format!("{} (in function {})", e, name))?;
202 Ok(Expr::FunctionCall { name, args })
203 } else {
204 if name == "TRUE" {
206 Ok(Expr::Boolean(true))
207 } else if name == "FALSE" {
208 Ok(Expr::Boolean(false))
209 } else {
210 Err(format!("Unknown identifier: {}", name))
211 }
212 }
213 }
214 _ => Err(format!("Unexpected token: {:?}", token)),
215 }
216 }
217}
218
219#[cfg(test)]
220mod tests {
221 use super::*;
222
223 #[test]
224 fn parse_number() {
225 let expr = Parser::parse_formula("42").unwrap();
226 assert_eq!(expr, Expr::Number(42.0));
227 }
228
229 #[test]
230 fn parse_string() {
231 let expr = Parser::parse_formula("\"hello\"").unwrap();
232 assert_eq!(expr, Expr::String("hello".into()));
233 }
234
235 #[test]
236 fn parse_binary_op() {
237 let expr = Parser::parse_formula("1+2").unwrap();
238 if let Expr::BinaryOp { op, .. } = &expr {
239 assert_eq!(*op, BinOp::Add);
240 } else {
241 panic!("Expected BinaryOp");
242 }
243 }
244
245 #[test]
246 fn parse_precedence() {
247 let expr = Parser::parse_formula("1+2*3").unwrap();
249 if let Expr::BinaryOp { op, left, right } = &expr {
250 assert_eq!(*op, BinOp::Add);
251 assert!(matches!(**left, Expr::Number(1.0)));
252 assert!(matches!(**right, Expr::BinaryOp { op: BinOp::Mul, .. }));
253 } else {
254 panic!("Expected BinaryOp");
255 }
256 }
257
258 #[test]
259 fn parse_function_call() {
260 let expr = Parser::parse_formula("SUM(A1:A10)").unwrap();
261 if let Expr::FunctionCall { name, args } = &expr {
262 assert_eq!(name, "SUM");
263 assert_eq!(args.len(), 1);
264 } else {
265 panic!("Expected FunctionCall");
266 }
267 }
268
269 #[test]
270 fn parse_nested_function() {
271 let expr = Parser::parse_formula("EVOLVE(A1:A10, 100)").unwrap();
272 if let Expr::FunctionCall { name, args } = &expr {
273 assert_eq!(name, "EVOLVE");
274 assert_eq!(args.len(), 2);
275 } else {
276 panic!("Expected FunctionCall");
277 }
278 }
279
280 #[test]
281 fn parse_cell_ref() {
282 let expr = Parser::parse_formula("A1").unwrap();
283 assert!(matches!(expr, Expr::CellRef(_)));
284 }
285
286 #[test]
287 fn parse_range() {
288 let expr = Parser::parse_formula("A1:B5").unwrap();
289 assert!(matches!(expr, Expr::Range(_)));
290 }
291
292 #[test]
293 fn parse_unary_negate() {
294 let expr = Parser::parse_formula("-5").unwrap();
295 assert!(matches!(expr, Expr::UnaryOp { op: UnaryOp::Negate, .. }));
296 }
297
298 #[test]
299 fn parse_percent() {
300 let expr = Parser::parse_formula("50%").unwrap();
301 assert!(matches!(expr, Expr::Percent(_)));
302 }
303
304 #[test]
305 fn parse_with_leading_equals() {
306 let expr = Parser::parse_formula("=SUM(A1:A10)").unwrap();
307 assert!(matches!(expr, Expr::FunctionCall { .. }));
308 }
309
310 #[test]
311 fn parse_boolean() {
312 assert_eq!(Parser::parse_formula("TRUE").unwrap(), Expr::Boolean(true));
313 assert_eq!(Parser::parse_formula("FALSE").unwrap(), Expr::Boolean(false));
314 }
315
316 #[test]
317 fn parse_comparison() {
318 let expr = Parser::parse_formula("A1>5").unwrap();
319 if let Expr::BinaryOp { op, .. } = &expr {
320 assert_eq!(*op, BinOp::Gt);
321 } else {
322 panic!("Expected BinaryOp");
323 }
324 }
325
326 #[test]
327 fn parse_power() {
328 let expr = Parser::parse_formula("2^3").unwrap();
329 if let Expr::BinaryOp { op, .. } = &expr {
330 assert_eq!(*op, BinOp::Pow);
331 } else {
332 panic!("Expected BinaryOp");
333 }
334 }
335}