1use crate::formula::ast::*;
2use crate::formula::token::{tokenize, Token};
3use crate::model::CellError;
4
5struct Parser {
6 tokens: Vec<Token>,
7 pos: usize,
8}
9
10impl Parser {
11 fn new(tokens: Vec<Token>) -> Self {
12 Parser { tokens, pos: 0 }
13 }
14
15 fn peek(&self) -> Option<&Token> {
16 self.tokens.get(self.pos)
17 }
18
19 fn advance(&mut self) -> Option<&Token> {
20 let tok = self.tokens.get(self.pos);
21 self.pos += 1;
22 tok
23 }
24
25 fn expect(&mut self, expected: &Token) -> Result<(), CellError> {
26 match self.advance() {
27 Some(tok) if tok == expected => Ok(()),
28 _ => Err(CellError::Parse),
29 }
30 }
31
32 fn expression(&mut self) -> Result<Expr, CellError> {
33 self.comparison()
34 }
35
36 fn comparison(&mut self) -> Result<Expr, CellError> {
37 let mut left = self.addition()?;
38 if let Some(op) = self.peek().and_then(|t| match t {
39 Token::Gt => Some(Op::Gt),
40 Token::Gte => Some(Op::Gte),
41 Token::Lt => Some(Op::Lt),
42 Token::Lte => Some(Op::Lte),
43 Token::Eq => Some(Op::Eq),
44 Token::Neq => Some(Op::Neq),
45 _ => None,
46 }) {
47 self.advance();
48 let right = self.addition()?;
49 left = Expr::BinaryOp {
50 op,
51 left: Box::new(left),
52 right: Box::new(right),
53 };
54 }
55 Ok(left)
56 }
57
58 fn addition(&mut self) -> Result<Expr, CellError> {
59 let mut left = self.multiplication()?;
60 loop {
61 let op = match self.peek() {
62 Some(Token::Plus) => Op::Add,
63 Some(Token::Minus) => Op::Sub,
64 _ => break,
65 };
66 self.advance();
67 let right = self.multiplication()?;
68 left = Expr::BinaryOp {
69 op,
70 left: Box::new(left),
71 right: Box::new(right),
72 };
73 }
74 Ok(left)
75 }
76
77 fn multiplication(&mut self) -> Result<Expr, CellError> {
78 let mut left = self.unary()?;
79 loop {
80 let op = match self.peek() {
81 Some(Token::Star) => Op::Mul,
82 Some(Token::Slash) => Op::Div,
83 _ => break,
84 };
85 self.advance();
86 let right = self.unary()?;
87 left = Expr::BinaryOp {
88 op,
89 left: Box::new(left),
90 right: Box::new(right),
91 };
92 }
93 Ok(left)
94 }
95
96 fn unary(&mut self) -> Result<Expr, CellError> {
97 if let Some(Token::Minus) = self.peek() {
98 self.advance();
99 let expr = self.unary()?;
100 return Ok(Expr::UnaryNeg(Box::new(expr)));
101 }
102 self.primary()
103 }
104
105 fn primary(&mut self) -> Result<Expr, CellError> {
106 let tok = self.advance().ok_or(CellError::Parse)?.clone();
107 match tok {
108 Token::Number(n) => Ok(Expr::Number(n)),
109 Token::StringLit(s) => Ok(Expr::Text(s)),
110 Token::Bool(b) => Ok(Expr::Bool(b)),
111 Token::CellRef {
112 col,
113 row,
114 abs_col,
115 abs_row,
116 } => {
117 let cell_ref =
118 CellRef::from_display(&col, &row, abs_col, abs_row).ok_or(CellError::Ref)?;
119
120 if let Some(Token::Colon) = self.peek() {
121 self.advance();
122 let end_tok = self.advance().ok_or(CellError::Parse)?.clone();
123 if let Token::CellRef {
124 col: col2,
125 row: row2,
126 abs_col: ac2,
127 abs_row: ar2,
128 } = end_tok
129 {
130 let end_ref =
131 CellRef::from_display(&col2, &row2, ac2, ar2).ok_or(CellError::Ref)?;
132 Ok(Expr::Range {
133 start: cell_ref,
134 end: end_ref,
135 })
136 } else {
137 Err(CellError::Parse)
138 }
139 } else {
140 Ok(Expr::CellRef(cell_ref))
141 }
142 }
143 Token::Ident(name) => {
144 self.expect(&Token::LParen)?;
145 let mut args = Vec::new();
146 if self.peek() != Some(&Token::RParen) {
147 args.push(self.expression()?);
148 while let Some(Token::Comma) = self.peek() {
149 self.advance();
150 args.push(self.expression()?);
151 }
152 }
153 self.expect(&Token::RParen)?;
154 Ok(Expr::FnCall { name, args })
155 }
156 Token::LParen => {
157 let expr = self.expression()?;
158 self.expect(&Token::RParen)?;
159 Ok(expr)
160 }
161 _ => Err(CellError::Parse),
162 }
163 }
164}
165
166pub fn parse(input: &str) -> Result<Expr, CellError> {
167 let tokens = tokenize(input)?;
168 let mut parser = Parser::new(tokens);
169 let expr = parser.expression()?;
170 if parser.pos != parser.tokens.len() {
171 return Err(CellError::Parse);
172 }
173 Ok(expr)
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn parse_number() {
182 let expr = parse("42").unwrap();
183 assert_eq!(expr, Expr::Number(42.0));
184 }
185
186 #[test]
187 fn parse_string() {
188 let expr = parse("\"hello\"").unwrap();
189 assert_eq!(expr, Expr::Text("hello".into()));
190 }
191
192 #[test]
193 fn parse_cell_ref() {
194 let expr = parse("A1").unwrap();
195 assert_eq!(
196 expr,
197 Expr::CellRef(CellRef {
198 col: 0,
199 row: 0,
200 abs_col: false,
201 abs_row: false
202 })
203 );
204 }
205
206 #[test]
207 fn parse_addition() {
208 let expr = parse("1+2").unwrap();
209 assert_eq!(
210 expr,
211 Expr::BinaryOp {
212 op: Op::Add,
213 left: Box::new(Expr::Number(1.0)),
214 right: Box::new(Expr::Number(2.0)),
215 }
216 );
217 }
218
219 #[test]
220 fn parse_precedence_mul_before_add() {
221 let expr = parse("1+2*3").unwrap();
222 assert_eq!(
223 expr,
224 Expr::BinaryOp {
225 op: Op::Add,
226 left: Box::new(Expr::Number(1.0)),
227 right: Box::new(Expr::BinaryOp {
228 op: Op::Mul,
229 left: Box::new(Expr::Number(2.0)),
230 right: Box::new(Expr::Number(3.0)),
231 }),
232 }
233 );
234 }
235
236 #[test]
237 fn parse_parentheses() {
238 let expr = parse("(1+2)*3").unwrap();
239 assert_eq!(
240 expr,
241 Expr::BinaryOp {
242 op: Op::Mul,
243 left: Box::new(Expr::BinaryOp {
244 op: Op::Add,
245 left: Box::new(Expr::Number(1.0)),
246 right: Box::new(Expr::Number(2.0)),
247 }),
248 right: Box::new(Expr::Number(3.0)),
249 }
250 );
251 }
252
253 #[test]
254 fn parse_function_call() {
255 let expr = parse("SUM(A1:A3)").unwrap();
256 assert_eq!(
257 expr,
258 Expr::FnCall {
259 name: "SUM".into(),
260 args: vec![Expr::Range {
261 start: CellRef {
262 col: 0,
263 row: 0,
264 abs_col: false,
265 abs_row: false
266 },
267 end: CellRef {
268 col: 0,
269 row: 2,
270 abs_col: false,
271 abs_row: false
272 },
273 }],
274 }
275 );
276 }
277
278 #[test]
279 fn parse_function_multiple_args() {
280 let expr = parse("IF(A1>0,A1,0)").unwrap();
281 assert_eq!(
282 expr,
283 Expr::FnCall {
284 name: "IF".into(),
285 args: vec![
286 Expr::BinaryOp {
287 op: Op::Gt,
288 left: Box::new(Expr::CellRef(CellRef {
289 col: 0,
290 row: 0,
291 abs_col: false,
292 abs_row: false
293 })),
294 right: Box::new(Expr::Number(0.0)),
295 },
296 Expr::CellRef(CellRef {
297 col: 0,
298 row: 0,
299 abs_col: false,
300 abs_row: false
301 }),
302 Expr::Number(0.0),
303 ],
304 }
305 );
306 }
307
308 #[test]
309 fn parse_unary_negation() {
310 let expr = parse("-A1").unwrap();
311 assert_eq!(
312 expr,
313 Expr::UnaryNeg(Box::new(Expr::CellRef(CellRef {
314 col: 0,
315 row: 0,
316 abs_col: false,
317 abs_row: false
318 })))
319 );
320 }
321
322 #[test]
323 fn parse_comparison() {
324 let expr = parse("A1>=10").unwrap();
325 assert_eq!(
326 expr,
327 Expr::BinaryOp {
328 op: Op::Gte,
329 left: Box::new(Expr::CellRef(CellRef {
330 col: 0,
331 row: 0,
332 abs_col: false,
333 abs_row: false
334 })),
335 right: Box::new(Expr::Number(10.0)),
336 }
337 );
338 }
339
340 #[test]
341 fn parse_range() {
342 let expr = parse("A1:B3").unwrap();
343 assert_eq!(
344 expr,
345 Expr::Range {
346 start: CellRef {
347 col: 0,
348 row: 0,
349 abs_col: false,
350 abs_row: false
351 },
352 end: CellRef {
353 col: 1,
354 row: 2,
355 abs_col: false,
356 abs_row: false
357 },
358 }
359 );
360 }
361
362 #[test]
363 fn parse_bool() {
364 assert_eq!(parse("TRUE").unwrap(), Expr::Bool(true));
365 assert_eq!(parse("FALSE").unwrap(), Expr::Bool(false));
366 }
367
368 #[test]
369 fn parse_complex_formula() {
370 let expr = parse("SUM(A1:A3)+1").unwrap();
371 assert_eq!(
372 expr,
373 Expr::BinaryOp {
374 op: Op::Add,
375 left: Box::new(Expr::FnCall {
376 name: "SUM".into(),
377 args: vec![Expr::Range {
378 start: CellRef {
379 col: 0,
380 row: 0,
381 abs_col: false,
382 abs_row: false
383 },
384 end: CellRef {
385 col: 0,
386 row: 2,
387 abs_col: false,
388 abs_row: false
389 },
390 }],
391 }),
392 right: Box::new(Expr::Number(1.0)),
393 }
394 );
395 }
396}