Rust · 42880 bytes Raw Blame History
1 use crate::context::Context;
2 use thiserror::Error;
3
4 #[derive(Error, Debug)]
5 pub enum ArithmeticError {
6 #[error("Parse error: {0}")]
7 ParseError(String),
8
9 #[error("Division by zero")]
10 DivisionByZero,
11
12 #[error("Invalid number: {0}")]
13 InvalidNumber(String),
14
15 #[error("Not an lvalue: cannot assign to expression")]
16 NotAnLvalue,
17 }
18
19 /// Represents either a concrete value or an lvalue (variable that can be assigned to)
20 #[derive(Debug, Clone)]
21 enum LValue {
22 /// A concrete value (result of an expression)
23 Value(i64),
24 /// A variable reference with its name and current value
25 Variable { name: String, value: i64 },
26 }
27
28 impl LValue {
29 /// Get the numeric value
30 fn value(&self) -> i64 {
31 match self {
32 LValue::Value(v) => *v,
33 LValue::Variable { value, .. } => *value,
34 }
35 }
36
37 /// Get the variable name if this is an lvalue, None otherwise
38 fn var_name(&self) -> Option<&str> {
39 match self {
40 LValue::Value(_) => None,
41 LValue::Variable { name, .. } => Some(name),
42 }
43 }
44 }
45
46 /// Evaluate an arithmetic expression
47 /// Supports: Full bash-compatible operators with proper precedence
48 pub fn evaluate_arithmetic(expr: &str, context: &mut Context) -> Result<i64, ArithmeticError> {
49 let tokens = tokenize(expr)?;
50 let mut parser = Parser::new(tokens, context);
51 parser.parse_expression()
52 }
53
54 #[derive(Debug, Clone, PartialEq)]
55 enum Token {
56 Number(i64),
57 Variable(String),
58
59 // Arithmetic operators
60 Plus,
61 Minus,
62 Multiply,
63 Divide,
64 Modulo,
65 Power, // **
66
67 // Assignment operators
68 Assign, // =
69 PlusAssign, // +=
70 MinusAssign, // -=
71 MultiplyAssign, // *=
72 DivideAssign, // /=
73 ModuloAssign, // %=
74 PowerAssign, // **=
75 AndAssign, // &=
76 OrAssign, // |=
77 XorAssign, // ^=
78 LeftShiftAssign, // <<=
79 RightShiftAssign, // >>=
80
81 // Bitwise operators
82 BitwiseAnd, // &
83 BitwiseOr, // |
84 BitwiseXor, // ^
85 BitwiseNot, // ~
86 LeftShift, // <<
87 RightShift, // >>
88
89 // Comparison operators
90 Less, // <
91 Greater, // >
92 LessEqual, // <=
93 GreaterEqual, // >=
94 Equal, // ==
95 NotEqual, // !=
96
97 // Logical operators
98 LogicalAnd, // &&
99 LogicalOr, // ||
100 LogicalNot, // !
101
102 // Increment/Decrement
103 Increment, // ++
104 Decrement, // --
105
106 // Ternary operator
107 Question, // ?
108 Colon, // :
109
110 // Comma operator
111 Comma, // ,
112
113 // Parentheses
114 LeftParen,
115 RightParen,
116 }
117
118 /// Tokenize an arithmetic expression with full bash operator support
119 fn tokenize(expr: &str) -> Result<Vec<Token>, ArithmeticError> {
120 let mut tokens = Vec::new();
121 let mut chars = expr.chars().peekable();
122
123 while let Some(&ch) = chars.peek() {
124 match ch {
125 ' ' | '\t' | '\n' => {
126 chars.next();
127 }
128 '+' => {
129 chars.next();
130 if chars.peek() == Some(&'+') {
131 chars.next();
132 tokens.push(Token::Increment);
133 } else if chars.peek() == Some(&'=') {
134 chars.next();
135 tokens.push(Token::PlusAssign);
136 } else {
137 tokens.push(Token::Plus);
138 }
139 }
140 '-' => {
141 chars.next();
142 if chars.peek() == Some(&'-') {
143 chars.next();
144 tokens.push(Token::Decrement);
145 } else if chars.peek() == Some(&'=') {
146 chars.next();
147 tokens.push(Token::MinusAssign);
148 } else {
149 // Check if it's a unary minus for a negative number
150 if tokens.is_empty() || is_unary_context(tokens.last()) {
151 // It's a unary minus
152 tokens.push(Token::Minus);
153 } else {
154 tokens.push(Token::Minus);
155 }
156 }
157 }
158 '*' => {
159 chars.next();
160 if chars.peek() == Some(&'*') {
161 chars.next();
162 // Could be ** or **=
163 if chars.peek() == Some(&'=') {
164 chars.next();
165 tokens.push(Token::PowerAssign);
166 } else {
167 tokens.push(Token::Power);
168 }
169 } else if chars.peek() == Some(&'=') {
170 chars.next();
171 tokens.push(Token::MultiplyAssign);
172 } else {
173 tokens.push(Token::Multiply);
174 }
175 }
176 '/' => {
177 chars.next();
178 if chars.peek() == Some(&'=') {
179 chars.next();
180 tokens.push(Token::DivideAssign);
181 } else {
182 tokens.push(Token::Divide);
183 }
184 }
185 '%' => {
186 chars.next();
187 if chars.peek() == Some(&'=') {
188 chars.next();
189 tokens.push(Token::ModuloAssign);
190 } else {
191 tokens.push(Token::Modulo);
192 }
193 }
194 '&' => {
195 chars.next();
196 if chars.peek() == Some(&'&') {
197 chars.next();
198 tokens.push(Token::LogicalAnd);
199 } else if chars.peek() == Some(&'=') {
200 chars.next();
201 tokens.push(Token::AndAssign);
202 } else {
203 tokens.push(Token::BitwiseAnd);
204 }
205 }
206 '|' => {
207 chars.next();
208 if chars.peek() == Some(&'|') {
209 chars.next();
210 tokens.push(Token::LogicalOr);
211 } else if chars.peek() == Some(&'=') {
212 chars.next();
213 tokens.push(Token::OrAssign);
214 } else {
215 tokens.push(Token::BitwiseOr);
216 }
217 }
218 '^' => {
219 chars.next();
220 if chars.peek() == Some(&'=') {
221 chars.next();
222 tokens.push(Token::XorAssign);
223 } else {
224 tokens.push(Token::BitwiseXor);
225 }
226 }
227 '~' => {
228 chars.next();
229 tokens.push(Token::BitwiseNot);
230 }
231 '<' => {
232 chars.next();
233 if chars.peek() == Some(&'<') {
234 chars.next();
235 // Could be << or <<=
236 if chars.peek() == Some(&'=') {
237 chars.next();
238 tokens.push(Token::LeftShiftAssign);
239 } else {
240 tokens.push(Token::LeftShift);
241 }
242 } else if chars.peek() == Some(&'=') {
243 chars.next();
244 tokens.push(Token::LessEqual);
245 } else {
246 tokens.push(Token::Less);
247 }
248 }
249 '>' => {
250 chars.next();
251 if chars.peek() == Some(&'>') {
252 chars.next();
253 // Could be >> or >>=
254 if chars.peek() == Some(&'=') {
255 chars.next();
256 tokens.push(Token::RightShiftAssign);
257 } else {
258 tokens.push(Token::RightShift);
259 }
260 } else if chars.peek() == Some(&'=') {
261 chars.next();
262 tokens.push(Token::GreaterEqual);
263 } else {
264 tokens.push(Token::Greater);
265 }
266 }
267 '=' => {
268 chars.next();
269 if chars.peek() == Some(&'=') {
270 chars.next();
271 tokens.push(Token::Equal);
272 } else {
273 tokens.push(Token::Assign);
274 }
275 }
276 '!' => {
277 chars.next();
278 if chars.peek() == Some(&'=') {
279 chars.next();
280 tokens.push(Token::NotEqual);
281 } else {
282 tokens.push(Token::LogicalNot);
283 }
284 }
285 '?' => {
286 chars.next();
287 tokens.push(Token::Question);
288 }
289 ':' => {
290 chars.next();
291 tokens.push(Token::Colon);
292 }
293 '(' => {
294 chars.next();
295 tokens.push(Token::LeftParen);
296 }
297 ')' => {
298 chars.next();
299 tokens.push(Token::RightParen);
300 }
301 ',' => {
302 chars.next();
303 tokens.push(Token::Comma);
304 }
305 '0'..='9' => {
306 let num = parse_number(&mut chars)?;
307 tokens.push(Token::Number(num));
308 }
309 'a'..='z' | 'A'..='Z' | '_' => {
310 let var = parse_variable(&mut chars);
311 tokens.push(Token::Variable(var));
312 }
313 _ => {
314 return Err(ArithmeticError::ParseError(format!("Unexpected character: {}", ch)));
315 }
316 }
317 }
318
319 Ok(tokens)
320 }
321
322 /// Check if the previous token indicates a unary context (for unary minus/plus)
323 fn is_unary_context(token: Option<&Token>) -> bool {
324 matches!(
325 token,
326 None | Some(Token::LeftParen)
327 | Some(Token::Plus)
328 | Some(Token::Minus)
329 | Some(Token::Multiply)
330 | Some(Token::Divide)
331 | Some(Token::Modulo)
332 | Some(Token::Power)
333 | Some(Token::Assign)
334 | Some(Token::PlusAssign)
335 | Some(Token::MinusAssign)
336 | Some(Token::MultiplyAssign)
337 | Some(Token::DivideAssign)
338 | Some(Token::ModuloAssign)
339 | Some(Token::PowerAssign)
340 | Some(Token::BitwiseAnd)
341 | Some(Token::BitwiseOr)
342 | Some(Token::BitwiseXor)
343 | Some(Token::LeftShift)
344 | Some(Token::RightShift)
345 | Some(Token::Less)
346 | Some(Token::Greater)
347 | Some(Token::LessEqual)
348 | Some(Token::GreaterEqual)
349 | Some(Token::Equal)
350 | Some(Token::NotEqual)
351 | Some(Token::LogicalAnd)
352 | Some(Token::LogicalOr)
353 | Some(Token::LogicalNot)
354 | Some(Token::Question)
355 | Some(Token::Colon)
356 | Some(Token::Comma)
357 )
358 }
359
360 fn parse_number(chars: &mut std::iter::Peekable<std::str::Chars>) -> Result<i64, ArithmeticError> {
361 let mut num_str = String::new();
362
363 while let Some(&ch) = chars.peek() {
364 if ch.is_ascii_digit() {
365 num_str.push(ch);
366 chars.next();
367 } else {
368 break;
369 }
370 }
371
372 num_str.parse::<i64>()
373 .map_err(|_| ArithmeticError::InvalidNumber(num_str))
374 }
375
376 fn parse_variable(chars: &mut std::iter::Peekable<std::str::Chars>) -> String {
377 let mut var_name = String::new();
378
379 while let Some(&ch) = chars.peek() {
380 if ch.is_alphanumeric() || ch == '_' {
381 var_name.push(ch);
382 chars.next();
383 } else {
384 break;
385 }
386 }
387
388 var_name
389 }
390
391 struct Parser<'a> {
392 tokens: Vec<Token>,
393 pos: usize,
394 context: &'a mut Context,
395 }
396
397 impl<'a> Parser<'a> {
398 fn new(tokens: Vec<Token>, context: &'a mut Context) -> Self {
399 Self { tokens, pos: 0, context }
400 }
401
402 fn current(&self) -> Option<&Token> {
403 self.tokens.get(self.pos)
404 }
405
406 fn advance(&mut self) {
407 self.pos += 1;
408 }
409
410 /// Set a variable in the context and return the new value
411 fn set_var(&mut self, name: &str, value: i64) -> i64 {
412 let _ = self.context.set_var(name, value.to_string());
413 value
414 }
415
416 /// Get variable value from context
417 fn get_var(&self, name: &str) -> i64 {
418 self.context.get_var(name)
419 .unwrap_or("0")
420 .parse::<i64>()
421 .unwrap_or(0)
422 }
423
424 /// Entry point: parse full expression
425 fn parse_expression(&mut self) -> Result<i64, ArithmeticError> {
426 Ok(self.parse_comma()?.value())
427 }
428
429 /// Parse expression returning LValue (for internal use)
430 fn parse_expression_lvalue(&mut self) -> Result<LValue, ArithmeticError> {
431 self.parse_comma()
432 }
433
434 /// Level 0: Comma operator (,) - lowest precedence
435 /// Evaluates all expressions from left to right and returns the last value
436 fn parse_comma(&mut self) -> Result<LValue, ArithmeticError> {
437 let mut result = self.parse_ternary()?;
438
439 while matches!(self.current(), Some(Token::Comma)) {
440 self.advance();
441 // Evaluate the next expression; previous result is discarded
442 result = self.parse_ternary()?;
443 }
444
445 Ok(result)
446 }
447
448 /// Level 1: Ternary conditional (? :)
449 fn parse_ternary(&mut self) -> Result<LValue, ArithmeticError> {
450 let condition = self.parse_assignment()?;
451
452 if matches!(self.current(), Some(Token::Question)) {
453 self.advance();
454 let true_value = self.parse_assignment()?;
455 if !matches!(self.current(), Some(Token::Colon)) {
456 return Err(ArithmeticError::ParseError("Expected ':' in ternary operator".to_string()));
457 }
458 self.advance();
459 let false_value = self.parse_ternary()?;
460 // Ternary result is not an lvalue
461 Ok(LValue::Value(if condition.value() != 0 {
462 true_value.value()
463 } else {
464 false_value.value()
465 }))
466 } else {
467 Ok(condition)
468 }
469 }
470
471 /// Level 2: Assignment operators (=, +=, -=, etc.) - right associative
472 fn parse_assignment(&mut self) -> Result<LValue, ArithmeticError> {
473 let left = self.parse_logical_or()?;
474
475 // Check for assignment operators
476 if let Some(token) = self.current().cloned() {
477 let op = match &token {
478 Token::Assign => Some("="),
479 Token::PlusAssign => Some("+="),
480 Token::MinusAssign => Some("-="),
481 Token::MultiplyAssign => Some("*="),
482 Token::DivideAssign => Some("/="),
483 Token::ModuloAssign => Some("%="),
484 Token::PowerAssign => Some("**="),
485 Token::AndAssign => Some("&="),
486 Token::OrAssign => Some("|="),
487 Token::XorAssign => Some("^="),
488 Token::LeftShiftAssign => Some("<<="),
489 Token::RightShiftAssign => Some(">>="),
490 _ => None,
491 };
492
493 if let Some(op_str) = op {
494 // Check that left is an lvalue (variable)
495 let var_name = match left.var_name() {
496 Some(name) => name.to_string(),
497 None => return Err(ArithmeticError::NotAnLvalue),
498 };
499
500 self.advance();
501
502 // For assignment, we need the right side value (right associative)
503 let right = self.parse_assignment()?.value();
504 let left_val = left.value();
505
506 // Compute the result
507 let result = match op_str {
508 "=" => right,
509 "+=" => left_val + right,
510 "-=" => left_val - right,
511 "*=" => left_val * right,
512 "/=" => {
513 if right == 0 {
514 return Err(ArithmeticError::DivisionByZero);
515 }
516 left_val / right
517 }
518 "%=" => {
519 if right == 0 {
520 return Err(ArithmeticError::DivisionByZero);
521 }
522 left_val % right
523 }
524 "**=" => left_val.pow(right.max(0) as u32),
525 "&=" => left_val & right,
526 "|=" => left_val | right,
527 "^=" => left_val ^ right,
528 "<<=" => left_val.wrapping_shl(right.max(0) as u32),
529 ">>=" => left_val.wrapping_shr(right.max(0) as u32),
530 _ => unreachable!(),
531 };
532
533 // Store result back to variable
534 self.set_var(&var_name, result);
535
536 // Return as a new lvalue pointing to the same variable with updated value
537 return Ok(LValue::Variable { name: var_name, value: result });
538 }
539 }
540
541 Ok(left)
542 }
543
544 /// Level 3: Logical OR (||)
545 fn parse_logical_or(&mut self) -> Result<LValue, ArithmeticError> {
546 let left = self.parse_logical_and()?;
547
548 if matches!(self.current(), Some(Token::LogicalOr)) {
549 let mut result = left.value();
550 while matches!(self.current(), Some(Token::LogicalOr)) {
551 self.advance();
552 // Short-circuit: if left is true (non-zero), don't evaluate right
553 if result != 0 {
554 // Still need to parse right side but ignore result
555 let _ = self.parse_logical_and()?;
556 result = 1;
557 } else {
558 let right = self.parse_logical_and()?.value();
559 result = if right != 0 { 1 } else { 0 };
560 }
561 }
562 Ok(LValue::Value(result))
563 } else {
564 Ok(left)
565 }
566 }
567
568 /// Level 4: Logical AND (&&)
569 fn parse_logical_and(&mut self) -> Result<LValue, ArithmeticError> {
570 let left = self.parse_bitwise_or()?;
571
572 if matches!(self.current(), Some(Token::LogicalAnd)) {
573 let mut result = left.value();
574 while matches!(self.current(), Some(Token::LogicalAnd)) {
575 self.advance();
576 // Short-circuit: if left is false (zero), don't evaluate right
577 if result == 0 {
578 // Still need to parse right side but ignore result
579 let _ = self.parse_bitwise_or()?;
580 result = 0;
581 } else {
582 let right = self.parse_bitwise_or()?.value();
583 result = if right != 0 { 1 } else { 0 };
584 }
585 }
586 Ok(LValue::Value(result))
587 } else {
588 Ok(left)
589 }
590 }
591
592 /// Level 5: Bitwise OR (|)
593 fn parse_bitwise_or(&mut self) -> Result<LValue, ArithmeticError> {
594 let left = self.parse_bitwise_xor()?;
595
596 if matches!(self.current(), Some(Token::BitwiseOr)) {
597 let mut result = left.value();
598 while matches!(self.current(), Some(Token::BitwiseOr)) {
599 self.advance();
600 result |= self.parse_bitwise_xor()?.value();
601 }
602 Ok(LValue::Value(result))
603 } else {
604 Ok(left)
605 }
606 }
607
608 /// Level 6: Bitwise XOR (^)
609 fn parse_bitwise_xor(&mut self) -> Result<LValue, ArithmeticError> {
610 let left = self.parse_bitwise_and()?;
611
612 if matches!(self.current(), Some(Token::BitwiseXor)) {
613 let mut result = left.value();
614 while matches!(self.current(), Some(Token::BitwiseXor)) {
615 self.advance();
616 result ^= self.parse_bitwise_and()?.value();
617 }
618 Ok(LValue::Value(result))
619 } else {
620 Ok(left)
621 }
622 }
623
624 /// Level 7: Bitwise AND (&)
625 fn parse_bitwise_and(&mut self) -> Result<LValue, ArithmeticError> {
626 let left = self.parse_equality()?;
627
628 if matches!(self.current(), Some(Token::BitwiseAnd)) {
629 let mut result = left.value();
630 while matches!(self.current(), Some(Token::BitwiseAnd)) {
631 self.advance();
632 result &= self.parse_equality()?.value();
633 }
634 Ok(LValue::Value(result))
635 } else {
636 Ok(left)
637 }
638 }
639
640 /// Level 8: Equality (==, !=)
641 fn parse_equality(&mut self) -> Result<LValue, ArithmeticError> {
642 let left = self.parse_relational()?;
643
644 if matches!(self.current(), Some(Token::Equal) | Some(Token::NotEqual)) {
645 let mut result = left.value();
646 while let Some(token) = self.current().cloned() {
647 match token {
648 Token::Equal => {
649 self.advance();
650 let right = self.parse_relational()?.value();
651 result = if result == right { 1 } else { 0 };
652 }
653 Token::NotEqual => {
654 self.advance();
655 let right = self.parse_relational()?.value();
656 result = if result != right { 1 } else { 0 };
657 }
658 _ => break,
659 }
660 }
661 Ok(LValue::Value(result))
662 } else {
663 Ok(left)
664 }
665 }
666
667 /// Level 9: Relational (<, >, <=, >=)
668 fn parse_relational(&mut self) -> Result<LValue, ArithmeticError> {
669 let left = self.parse_shift()?;
670
671 if matches!(self.current(), Some(Token::Less) | Some(Token::Greater) | Some(Token::LessEqual) | Some(Token::GreaterEqual)) {
672 let mut result = left.value();
673 while let Some(token) = self.current().cloned() {
674 match token {
675 Token::Less => {
676 self.advance();
677 let right = self.parse_shift()?.value();
678 result = if result < right { 1 } else { 0 };
679 }
680 Token::Greater => {
681 self.advance();
682 let right = self.parse_shift()?.value();
683 result = if result > right { 1 } else { 0 };
684 }
685 Token::LessEqual => {
686 self.advance();
687 let right = self.parse_shift()?.value();
688 result = if result <= right { 1 } else { 0 };
689 }
690 Token::GreaterEqual => {
691 self.advance();
692 let right = self.parse_shift()?.value();
693 result = if result >= right { 1 } else { 0 };
694 }
695 _ => break,
696 }
697 }
698 Ok(LValue::Value(result))
699 } else {
700 Ok(left)
701 }
702 }
703
704 /// Level 10: Bitwise shift (<<, >>)
705 fn parse_shift(&mut self) -> Result<LValue, ArithmeticError> {
706 let left = self.parse_additive()?;
707
708 if matches!(self.current(), Some(Token::LeftShift) | Some(Token::RightShift)) {
709 let mut result = left.value();
710 while let Some(token) = self.current().cloned() {
711 match token {
712 Token::LeftShift => {
713 self.advance();
714 let right = self.parse_additive()?.value();
715 result = result.wrapping_shl(right.max(0) as u32);
716 }
717 Token::RightShift => {
718 self.advance();
719 let right = self.parse_additive()?.value();
720 result = result.wrapping_shr(right.max(0) as u32);
721 }
722 _ => break,
723 }
724 }
725 Ok(LValue::Value(result))
726 } else {
727 Ok(left)
728 }
729 }
730
731 /// Level 11: Addition and subtraction (+, -)
732 fn parse_additive(&mut self) -> Result<LValue, ArithmeticError> {
733 let left = self.parse_multiplicative()?;
734
735 if matches!(self.current(), Some(Token::Plus) | Some(Token::Minus)) {
736 let mut result = left.value();
737 while let Some(token) = self.current().cloned() {
738 match token {
739 Token::Plus => {
740 self.advance();
741 result += self.parse_multiplicative()?.value();
742 }
743 Token::Minus => {
744 self.advance();
745 result -= self.parse_multiplicative()?.value();
746 }
747 _ => break,
748 }
749 }
750 Ok(LValue::Value(result))
751 } else {
752 Ok(left)
753 }
754 }
755
756 /// Level 12: Multiplication, division, modulo (*, /, %)
757 fn parse_multiplicative(&mut self) -> Result<LValue, ArithmeticError> {
758 let left = self.parse_power()?;
759
760 if matches!(self.current(), Some(Token::Multiply) | Some(Token::Divide) | Some(Token::Modulo)) {
761 let mut result = left.value();
762 while let Some(token) = self.current().cloned() {
763 match token {
764 Token::Multiply => {
765 self.advance();
766 result *= self.parse_power()?.value();
767 }
768 Token::Divide => {
769 self.advance();
770 let divisor = self.parse_power()?.value();
771 if divisor == 0 {
772 return Err(ArithmeticError::DivisionByZero);
773 }
774 result /= divisor;
775 }
776 Token::Modulo => {
777 self.advance();
778 let divisor = self.parse_power()?.value();
779 if divisor == 0 {
780 return Err(ArithmeticError::DivisionByZero);
781 }
782 result %= divisor;
783 }
784 _ => break,
785 }
786 }
787 Ok(LValue::Value(result))
788 } else {
789 Ok(left)
790 }
791 }
792
793 /// Level 13: Power (**) - right associative
794 fn parse_power(&mut self) -> Result<LValue, ArithmeticError> {
795 let base = self.parse_unary()?;
796
797 if matches!(self.current(), Some(Token::Power)) {
798 self.advance();
799 let exponent = self.parse_power()?.value(); // Right associative
800 Ok(LValue::Value(base.value().pow(exponent.max(0) as u32)))
801 } else {
802 Ok(base)
803 }
804 }
805
806 /// Level 14: Unary operators (!, ~, unary +, unary -)
807 fn parse_unary(&mut self) -> Result<LValue, ArithmeticError> {
808 match self.current().cloned() {
809 Some(Token::LogicalNot) => {
810 self.advance();
811 let operand = self.parse_unary()?.value();
812 Ok(LValue::Value(if operand == 0 { 1 } else { 0 }))
813 }
814 Some(Token::BitwiseNot) => {
815 self.advance();
816 let operand = self.parse_unary()?.value();
817 Ok(LValue::Value(!operand))
818 }
819 Some(Token::Plus) => {
820 self.advance();
821 self.parse_unary() // Unary plus doesn't change value
822 }
823 Some(Token::Minus) => {
824 self.advance();
825 let operand = self.parse_unary()?.value();
826 Ok(LValue::Value(-operand))
827 }
828 Some(Token::Increment) => {
829 // Pre-increment: ++x returns x+1 and stores x+1
830 self.advance();
831 let operand = self.parse_postfix()?;
832 match operand.var_name() {
833 Some(name) => {
834 let new_value = operand.value() + 1;
835 self.set_var(name, new_value);
836 Ok(LValue::Variable { name: name.to_string(), value: new_value })
837 }
838 None => Err(ArithmeticError::NotAnLvalue),
839 }
840 }
841 Some(Token::Decrement) => {
842 // Pre-decrement: --x returns x-1 and stores x-1
843 self.advance();
844 let operand = self.parse_postfix()?;
845 match operand.var_name() {
846 Some(name) => {
847 let new_value = operand.value() - 1;
848 self.set_var(name, new_value);
849 Ok(LValue::Variable { name: name.to_string(), value: new_value })
850 }
851 None => Err(ArithmeticError::NotAnLvalue),
852 }
853 }
854 _ => self.parse_postfix(),
855 }
856 }
857
858 /// Level 15: Postfix operators (++, --)
859 fn parse_postfix(&mut self) -> Result<LValue, ArithmeticError> {
860 let operand = self.parse_primary()?;
861
862 // Check for postfix operators
863 match self.current() {
864 Some(Token::Increment) => {
865 self.advance();
866 // Post-increment: x++ returns old value, stores x+1
867 match operand.var_name() {
868 Some(name) => {
869 let old_value = operand.value();
870 self.set_var(name, old_value + 1);
871 // Return the old value (as a non-lvalue since it's the pre-increment value)
872 Ok(LValue::Value(old_value))
873 }
874 None => Err(ArithmeticError::NotAnLvalue),
875 }
876 }
877 Some(Token::Decrement) => {
878 self.advance();
879 // Post-decrement: x-- returns old value, stores x-1
880 match operand.var_name() {
881 Some(name) => {
882 let old_value = operand.value();
883 self.set_var(name, old_value - 1);
884 // Return the old value (as a non-lvalue since it's the pre-decrement value)
885 Ok(LValue::Value(old_value))
886 }
887 None => Err(ArithmeticError::NotAnLvalue),
888 }
889 }
890 _ => Ok(operand),
891 }
892 }
893
894 /// Level 16: Primary expressions (numbers, variables, parenthesized expressions)
895 fn parse_primary(&mut self) -> Result<LValue, ArithmeticError> {
896 match self.current().cloned() {
897 Some(Token::Number(n)) => {
898 self.advance();
899 Ok(LValue::Value(n))
900 }
901 Some(Token::Variable(name)) => {
902 self.advance();
903 // Look up variable value
904 let value = self.get_var(&name);
905 Ok(LValue::Variable { name, value })
906 }
907 Some(Token::LeftParen) => {
908 self.advance();
909 let result = self.parse_expression_lvalue()?;
910 if !matches!(self.current(), Some(Token::RightParen)) {
911 return Err(ArithmeticError::ParseError("Expected ')'".to_string()));
912 }
913 self.advance();
914 // Parenthesized expressions are not lvalues (even if they contain a single variable)
915 Ok(LValue::Value(result.value()))
916 }
917 _ => Err(ArithmeticError::ParseError("Unexpected token".to_string())),
918 }
919 }
920 }
921
922 #[cfg(test)]
923 mod tests {
924 use super::*;
925
926 #[test]
927 fn test_simple_addition() {
928 let mut ctx = Context::empty();
929 assert_eq!(evaluate_arithmetic("2 + 3", &mut ctx).unwrap(), 5);
930 }
931
932 #[test]
933 fn test_multiplication() {
934 let mut ctx = Context::empty();
935 assert_eq!(evaluate_arithmetic("4 * 5", &mut ctx).unwrap(), 20);
936 }
937
938 #[test]
939 fn test_complex_expression() {
940 let mut ctx = Context::empty();
941 assert_eq!(evaluate_arithmetic("(2 + 3) * 4", &mut ctx).unwrap(), 20);
942 }
943
944 #[test]
945 fn test_with_variable() {
946 let mut ctx = Context::empty();
947 ctx.set_var("x", "10").unwrap();
948 assert_eq!(evaluate_arithmetic("x * 2", &mut ctx).unwrap(), 20);
949 }
950
951 #[test]
952 fn test_division() {
953 let mut ctx = Context::empty();
954 assert_eq!(evaluate_arithmetic("10 / 2", &mut ctx).unwrap(), 5);
955 }
956
957 #[test]
958 fn test_modulo() {
959 let mut ctx = Context::empty();
960 assert_eq!(evaluate_arithmetic("10 % 3", &mut ctx).unwrap(), 1);
961 }
962
963 #[test]
964 fn test_negative_numbers() {
965 let mut ctx = Context::empty();
966 assert_eq!(evaluate_arithmetic("-5 + 3", &mut ctx).unwrap(), -2);
967 }
968
969 #[test]
970 fn test_precedence() {
971 let mut ctx = Context::empty();
972 assert_eq!(evaluate_arithmetic("2 + 3 * 4", &mut ctx).unwrap(), 14);
973 }
974
975 // Lvalue tests
976
977 #[test]
978 fn test_simple_assignment() {
979 let mut ctx = Context::empty();
980 // x = 5 should set x to 5 and return 5
981 assert_eq!(evaluate_arithmetic("x = 5", &mut ctx).unwrap(), 5);
982 assert_eq!(ctx.get_var("x"), Some("5"));
983 }
984
985 #[test]
986 fn test_compound_assignment_add() {
987 let mut ctx = Context::empty();
988 ctx.set_var("x", "10").unwrap();
989 // x += 3 should set x to 13 and return 13
990 assert_eq!(evaluate_arithmetic("x += 3", &mut ctx).unwrap(), 13);
991 assert_eq!(ctx.get_var("x"), Some("13"));
992 }
993
994 #[test]
995 fn test_compound_assignment_sub() {
996 let mut ctx = Context::empty();
997 ctx.set_var("x", "10").unwrap();
998 assert_eq!(evaluate_arithmetic("x -= 3", &mut ctx).unwrap(), 7);
999 assert_eq!(ctx.get_var("x"), Some("7"));
1000 }
1001
1002 #[test]
1003 fn test_compound_assignment_mul() {
1004 let mut ctx = Context::empty();
1005 ctx.set_var("x", "10").unwrap();
1006 assert_eq!(evaluate_arithmetic("x *= 3", &mut ctx).unwrap(), 30);
1007 assert_eq!(ctx.get_var("x"), Some("30"));
1008 }
1009
1010 #[test]
1011 fn test_compound_assignment_div() {
1012 let mut ctx = Context::empty();
1013 ctx.set_var("x", "10").unwrap();
1014 assert_eq!(evaluate_arithmetic("x /= 2", &mut ctx).unwrap(), 5);
1015 assert_eq!(ctx.get_var("x"), Some("5"));
1016 }
1017
1018 #[test]
1019 fn test_compound_assignment_mod() {
1020 let mut ctx = Context::empty();
1021 ctx.set_var("x", "10").unwrap();
1022 assert_eq!(evaluate_arithmetic("x %= 3", &mut ctx).unwrap(), 1);
1023 assert_eq!(ctx.get_var("x"), Some("1"));
1024 }
1025
1026 #[test]
1027 fn test_pre_increment() {
1028 let mut ctx = Context::empty();
1029 ctx.set_var("x", "5").unwrap();
1030 // ++x should increment x and return the new value
1031 assert_eq!(evaluate_arithmetic("++x", &mut ctx).unwrap(), 6);
1032 assert_eq!(ctx.get_var("x"), Some("6"));
1033 }
1034
1035 #[test]
1036 fn test_pre_decrement() {
1037 let mut ctx = Context::empty();
1038 ctx.set_var("x", "5").unwrap();
1039 // --x should decrement x and return the new value
1040 assert_eq!(evaluate_arithmetic("--x", &mut ctx).unwrap(), 4);
1041 assert_eq!(ctx.get_var("x"), Some("4"));
1042 }
1043
1044 #[test]
1045 fn test_post_increment() {
1046 let mut ctx = Context::empty();
1047 ctx.set_var("x", "5").unwrap();
1048 // x++ should return the old value but increment x
1049 assert_eq!(evaluate_arithmetic("x++", &mut ctx).unwrap(), 5);
1050 assert_eq!(ctx.get_var("x"), Some("6"));
1051 }
1052
1053 #[test]
1054 fn test_post_decrement() {
1055 let mut ctx = Context::empty();
1056 ctx.set_var("x", "5").unwrap();
1057 // x-- should return the old value but decrement x
1058 assert_eq!(evaluate_arithmetic("x--", &mut ctx).unwrap(), 5);
1059 assert_eq!(ctx.get_var("x"), Some("4"));
1060 }
1061
1062 #[test]
1063 fn test_chained_assignment() {
1064 let mut ctx = Context::empty();
1065 // a = b = c = 5 should set all three to 5
1066 assert_eq!(evaluate_arithmetic("a = b = c = 5", &mut ctx).unwrap(), 5);
1067 assert_eq!(ctx.get_var("a"), Some("5"));
1068 assert_eq!(ctx.get_var("b"), Some("5"));
1069 assert_eq!(ctx.get_var("c"), Some("5"));
1070 }
1071
1072 #[test]
1073 fn test_increment_in_expression() {
1074 let mut ctx = Context::empty();
1075 ctx.set_var("x", "5").unwrap();
1076 // 2 + ++x should be 2 + 6 = 8
1077 assert_eq!(evaluate_arithmetic("2 + ++x", &mut ctx).unwrap(), 8);
1078 assert_eq!(ctx.get_var("x"), Some("6"));
1079 }
1080
1081 #[test]
1082 fn test_post_increment_in_expression() {
1083 let mut ctx = Context::empty();
1084 ctx.set_var("x", "5").unwrap();
1085 // 2 + x++ should be 2 + 5 = 7 (x becomes 6 after)
1086 assert_eq!(evaluate_arithmetic("2 + x++", &mut ctx).unwrap(), 7);
1087 assert_eq!(ctx.get_var("x"), Some("6"));
1088 }
1089
1090 #[test]
1091 fn test_assignment_not_lvalue_error() {
1092 let mut ctx = Context::empty();
1093 // (x) is not an lvalue, so (x) = 5 should fail
1094 let result = evaluate_arithmetic("(x) = 5", &mut ctx);
1095 assert!(result.is_err());
1096 }
1097
1098 #[test]
1099 fn test_increment_not_lvalue_error() {
1100 let mut ctx = Context::empty();
1101 // ++5 should fail (5 is not an lvalue)
1102 let result = evaluate_arithmetic("++5", &mut ctx);
1103 assert!(result.is_err());
1104 }
1105
1106 #[test]
1107 fn test_power_assignment() {
1108 let mut ctx = Context::empty();
1109 ctx.set_var("x", "2").unwrap();
1110 assert_eq!(evaluate_arithmetic("x **= 3", &mut ctx).unwrap(), 8);
1111 assert_eq!(ctx.get_var("x"), Some("8"));
1112 }
1113
1114 #[test]
1115 fn test_ternary_operator() {
1116 let mut ctx = Context::empty();
1117 assert_eq!(evaluate_arithmetic("1 ? 10 : 20", &mut ctx).unwrap(), 10);
1118 assert_eq!(evaluate_arithmetic("0 ? 10 : 20", &mut ctx).unwrap(), 20);
1119 }
1120
1121 #[test]
1122 fn test_comparison_operators() {
1123 let mut ctx = Context::empty();
1124 assert_eq!(evaluate_arithmetic("5 < 10", &mut ctx).unwrap(), 1);
1125 assert_eq!(evaluate_arithmetic("10 < 5", &mut ctx).unwrap(), 0);
1126 assert_eq!(evaluate_arithmetic("5 == 5", &mut ctx).unwrap(), 1);
1127 assert_eq!(evaluate_arithmetic("5 != 5", &mut ctx).unwrap(), 0);
1128 assert_eq!(evaluate_arithmetic("5 <= 5", &mut ctx).unwrap(), 1);
1129 assert_eq!(evaluate_arithmetic("5 >= 5", &mut ctx).unwrap(), 1);
1130 }
1131
1132 #[test]
1133 fn test_logical_operators() {
1134 let mut ctx = Context::empty();
1135 assert_eq!(evaluate_arithmetic("1 && 1", &mut ctx).unwrap(), 1);
1136 assert_eq!(evaluate_arithmetic("1 && 0", &mut ctx).unwrap(), 0);
1137 assert_eq!(evaluate_arithmetic("0 || 1", &mut ctx).unwrap(), 1);
1138 assert_eq!(evaluate_arithmetic("0 || 0", &mut ctx).unwrap(), 0);
1139 assert_eq!(evaluate_arithmetic("!0", &mut ctx).unwrap(), 1);
1140 assert_eq!(evaluate_arithmetic("!1", &mut ctx).unwrap(), 0);
1141 }
1142
1143 #[test]
1144 fn test_bitwise_operators() {
1145 let mut ctx = Context::empty();
1146 assert_eq!(evaluate_arithmetic("5 & 3", &mut ctx).unwrap(), 1);
1147 assert_eq!(evaluate_arithmetic("5 | 3", &mut ctx).unwrap(), 7);
1148 assert_eq!(evaluate_arithmetic("5 ^ 3", &mut ctx).unwrap(), 6);
1149 assert_eq!(evaluate_arithmetic("~0", &mut ctx).unwrap(), -1);
1150 assert_eq!(evaluate_arithmetic("1 << 4", &mut ctx).unwrap(), 16);
1151 assert_eq!(evaluate_arithmetic("16 >> 2", &mut ctx).unwrap(), 4);
1152 }
1153
1154 #[test]
1155 fn test_bitwise_assignment_and() {
1156 let mut ctx = Context::empty();
1157 ctx.set_var("x", "7").unwrap(); // 0b111
1158 assert_eq!(evaluate_arithmetic("x &= 3", &mut ctx).unwrap(), 3); // 0b111 & 0b011 = 0b011
1159 assert_eq!(ctx.get_var("x"), Some("3"));
1160 }
1161
1162 #[test]
1163 fn test_bitwise_assignment_or() {
1164 let mut ctx = Context::empty();
1165 ctx.set_var("x", "5").unwrap(); // 0b101
1166 assert_eq!(evaluate_arithmetic("x |= 2", &mut ctx).unwrap(), 7); // 0b101 | 0b010 = 0b111
1167 assert_eq!(ctx.get_var("x"), Some("7"));
1168 }
1169
1170 #[test]
1171 fn test_bitwise_assignment_xor() {
1172 let mut ctx = Context::empty();
1173 ctx.set_var("x", "7").unwrap(); // 0b111
1174 assert_eq!(evaluate_arithmetic("x ^= 3", &mut ctx).unwrap(), 4); // 0b111 ^ 0b011 = 0b100
1175 assert_eq!(ctx.get_var("x"), Some("4"));
1176 }
1177
1178 #[test]
1179 fn test_bitwise_assignment_left_shift() {
1180 let mut ctx = Context::empty();
1181 ctx.set_var("x", "1").unwrap();
1182 assert_eq!(evaluate_arithmetic("x <<= 4", &mut ctx).unwrap(), 16);
1183 assert_eq!(ctx.get_var("x"), Some("16"));
1184 }
1185
1186 #[test]
1187 fn test_bitwise_assignment_right_shift() {
1188 let mut ctx = Context::empty();
1189 ctx.set_var("x", "16").unwrap();
1190 assert_eq!(evaluate_arithmetic("x >>= 2", &mut ctx).unwrap(), 4);
1191 assert_eq!(ctx.get_var("x"), Some("4"));
1192 }
1193
1194 #[test]
1195 fn test_power_operator() {
1196 let mut ctx = Context::empty();
1197 assert_eq!(evaluate_arithmetic("2 ** 10", &mut ctx).unwrap(), 1024);
1198 // Right associative: 2 ** 3 ** 2 = 2 ** 9 = 512
1199 assert_eq!(evaluate_arithmetic("2 ** 3 ** 2", &mut ctx).unwrap(), 512);
1200 }
1201
1202 // Comma operator tests
1203
1204 #[test]
1205 fn test_comma_operator_simple() {
1206 let mut ctx = Context::empty();
1207 // Comma operator evaluates left to right, returns last value
1208 assert_eq!(evaluate_arithmetic("1, 2, 3", &mut ctx).unwrap(), 3);
1209 }
1210
1211 #[test]
1212 fn test_comma_operator_with_assignments() {
1213 let mut ctx = Context::empty();
1214 // (a=1, b=2, a+b) sets a and b, returns sum
1215 assert_eq!(evaluate_arithmetic("a=1, b=2, a+b", &mut ctx).unwrap(), 3);
1216 assert_eq!(ctx.get_var("a"), Some("1"));
1217 assert_eq!(ctx.get_var("b"), Some("2"));
1218 }
1219
1220 #[test]
1221 fn test_comma_operator_side_effects() {
1222 let mut ctx = Context::empty();
1223 ctx.set_var("x", "0").unwrap();
1224 // All expressions should be evaluated for side effects
1225 assert_eq!(evaluate_arithmetic("x=1, x=2, x=3", &mut ctx).unwrap(), 3);
1226 assert_eq!(ctx.get_var("x"), Some("3"));
1227 }
1228
1229 #[test]
1230 fn test_comma_operator_with_increment() {
1231 let mut ctx = Context::empty();
1232 ctx.set_var("i", "0").unwrap();
1233 // Common for-loop style: init, condition check
1234 assert_eq!(evaluate_arithmetic("i++, i++, i++", &mut ctx).unwrap(), 2);
1235 assert_eq!(ctx.get_var("i"), Some("3"));
1236 }
1237
1238 #[test]
1239 fn test_comma_operator_in_parens() {
1240 let mut ctx = Context::empty();
1241 // Comma operator inside parentheses
1242 assert_eq!(evaluate_arithmetic("2 * (1, 2, 3)", &mut ctx).unwrap(), 6);
1243 }
1244 }
1245