初始提交,未完全测试
This commit is contained in:
172
template/expr/ast/Arith.py
Normal file
172
template/expr/ast/Arith.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal Arith - Arithmetic Expression
|
||||
"""
|
||||
|
||||
from .Expr import Expr
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
|
||||
class Arith(Expr):
|
||||
"""Arithmetic expression"""
|
||||
|
||||
ADD = "+"
|
||||
SUB = "-"
|
||||
MUL = "*"
|
||||
DIV = "/"
|
||||
MOD = "%"
|
||||
|
||||
_rounding_mode = ROUND_HALF_UP
|
||||
|
||||
def __init__(self, left: Expr, operator: str, right: Expr):
|
||||
"""
|
||||
Initialize arithmetic expression
|
||||
|
||||
Args:
|
||||
left: Left expression
|
||||
operator: Arithmetic operator
|
||||
right: Right expression
|
||||
"""
|
||||
self._left = left
|
||||
self._operator = operator
|
||||
self._right = right
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate arithmetic expression"""
|
||||
left_val = self._left.eval(scope)
|
||||
right_val = self._right.eval(scope)
|
||||
|
||||
# Handle None values
|
||||
if left_val is None or right_val is None:
|
||||
return None
|
||||
|
||||
# Convert to appropriate numeric types
|
||||
left_num = self._to_number(left_val)
|
||||
right_num = self._to_number(right_val)
|
||||
|
||||
if left_num is None or right_num is None:
|
||||
return None
|
||||
|
||||
# Perform operation
|
||||
if self._operator == Arith.ADD:
|
||||
return left_num + right_num
|
||||
elif self._operator == Arith.SUB:
|
||||
return left_num - right_num
|
||||
elif self._operator == Arith.MUL:
|
||||
return left_num * right_num
|
||||
elif self._operator == Arith.DIV:
|
||||
if right_num == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
return self._divide(left_num, right_num)
|
||||
elif self._operator == Arith.MOD:
|
||||
return left_num % right_num
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
def _to_number(self, value):
|
||||
"""Convert value to number"""
|
||||
if isinstance(value, (int, float)):
|
||||
return value
|
||||
if isinstance(value, Decimal):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
if '.' in value:
|
||||
return float(value)
|
||||
else:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return None
|
||||
return None
|
||||
|
||||
def _divide(self, left, right):
|
||||
"""Handle division with proper rounding"""
|
||||
if isinstance(left, Decimal) or isinstance(right, Decimal):
|
||||
result = Decimal(str(left)) / Decimal(str(right))
|
||||
return result.quantize(Decimal('0.00000001'), rounding=self._rounding_mode)
|
||||
else:
|
||||
return left / right
|
||||
|
||||
@classmethod
|
||||
def set_big_decimal_divide_rounding_mode(cls, rounding_mode):
|
||||
"""Set rounding mode for decimal division"""
|
||||
cls._rounding_mode = rounding_mode
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Arith({self._left} {self._operator} {self._right})"
|
||||
|
||||
|
||||
class Unary(Expr):
|
||||
"""Unary expression (positive, negative, increment, decrement)"""
|
||||
|
||||
POSITIVE = "+"
|
||||
NEGATIVE = "-"
|
||||
NOT = "!"
|
||||
|
||||
def __init__(self, operator: str, expr: Expr):
|
||||
"""
|
||||
Initialize unary expression
|
||||
|
||||
Args:
|
||||
operator: Unary operator
|
||||
expr: Expression to operate on
|
||||
"""
|
||||
self._operator = operator
|
||||
self._expr = expr
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate unary expression"""
|
||||
val = self._expr.eval(scope)
|
||||
|
||||
if self._operator == Unary.POSITIVE:
|
||||
return +val if isinstance(val, (int, float)) else val
|
||||
elif self._operator == Unary.NEGATIVE:
|
||||
return -val if isinstance(val, (int, float)) else val
|
||||
elif self._operator == Unary.NOT:
|
||||
return not val
|
||||
else:
|
||||
raise ValueError(f"Unknown operator: {self._operator}")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Unary({self._operator}{self._expr})"
|
||||
|
||||
|
||||
class IncDec(Expr):
|
||||
"""Increment/Decrement expression"""
|
||||
|
||||
INC = "++"
|
||||
DEC = "--"
|
||||
|
||||
def __init__(self, expr: Expr, operator: str, is_prefix: bool = True):
|
||||
"""
|
||||
Initialize increment/decrement
|
||||
|
||||
Args:
|
||||
expr: Expression to increment/decrement
|
||||
operator: INC or DEC
|
||||
is_prefix: Whether this is prefix (++x) or postfix (x++)
|
||||
"""
|
||||
self._expr = expr
|
||||
self._operator = operator
|
||||
self._is_prefix = is_prefix
|
||||
|
||||
def eval(self, scope):
|
||||
"""Evaluate increment/decrement"""
|
||||
# This is a simplified implementation
|
||||
# In a real implementation, this would modify the variable
|
||||
current_val = self._expr.eval(scope)
|
||||
|
||||
if isinstance(current_val, int):
|
||||
if self._operator == IncDec.INC:
|
||||
return current_val + 1
|
||||
else:
|
||||
return current_val - 1
|
||||
|
||||
return current_val
|
||||
|
||||
def __repr__(self) -> str:
|
||||
op_str = self._operator
|
||||
if self._is_prefix:
|
||||
return f"IncDec({op_str}{self._expr})"
|
||||
else:
|
||||
return f"IncDec({self._expr}{op_str})"
|
||||
Reference in New Issue
Block a user