CODE-0006 · claude-haiku-4-5 (default)def eval_expr(s):
"""Evaluate an arithmetic expression given as a string."""
tokens = tokenize(s)
if not tokens:
raise ValueError("Empty expression")
parser = Parser(tokens)
result = parser.parse_expression()
if parser.pos < len(tokens):
raise ValueError("Unexpected token after expression")
# Convert to int if it's a whole number
if isinstance(result, float) and result == int(result):
return int(result)
return result
def tokenize(s):
"""Tokenize the input string into a list of tokens."""
tokens = []
i = 0
while i < len(s):
# Skip whitespace
if s[i].isspace():
i += 1
continue
# Check for operators and parentheses
if s[i] in '+-*/()':
tokens.append(s[i])
i += 1
# Check for numbers
elif s[i].isdigit() or (s[i] == '.' and i + 1 < len(s) and s[i + 1].isdigit()):
j = i
has_dot = False
while j < len(s) and (s[j].isdigit() or (s[j] == '.' and not has_dot)):
if s[j] == '.':
has_dot = True
j += 1
tokens.append(s[i:j])
i = j
else:
raise ValueError(f"Unknown token: {s[i]}")
return tokens
class Parser:
def __init__(self, tokens):
self.tokens = tokens
self.pos = 0
def parse_expression(self):
"""Parse addition and subtraction (lowest precedence)."""
left = self.parse_term()
while self.pos < len(self.tokens) and self.tokens[self.pos] in '+-':
op = self.tokens[self.pos]
self.pos += 1
right = self.parse_term()
if op == '+':
left = left + right
else:
left = left - right
return left
def parse_term(self):
"""Parse multiplication and division (higher precedence)."""
left = self.parse_unary()
while self.pos < len(self.tokens) and self.tokens[self.pos] in '*/':
op = self.tokens[self.pos]
self.pos += 1
right = self.parse_unary()
if op == '*':
left = left * right
else:
if right == 0:
raise ValueError("Division by zero")
left = left / right
return left
def parse_unary(self):
"""Parse unary operators and primary expressions."""
if self.pos < len(self.tokens) and self.tokens[self.pos] in '+-':
op = self.tokens[self.pos]
self.pos += 1
value = self.parse_unary()
if op == '-':
return -value
else:
return value
return self.parse_primary()
def parse_primary(self):
"""Parse primary expressions (numbers and parenthesized expressions)."""
if self.pos >= len(self.tokens):
raise ValueError("Unexpected end of expression")
token = self.tokens[self.pos]
# Handle parenthesized expressions
if token == '(':
self.pos += 1
result = self.parse_expression()
if self.pos >= len(self.tokens) or self.tokens[self.pos] != ')':
raise ValueError("Mismatched parentheses")
self.pos += 1
return result
# Handle numbers
if token[0].isdigit() or (token[0] == '.' and len(token) > 1):
self.pos += 1
try:
if '.' in token:
return float(token)
else:
return int(token)
except ValueError:
raise ValueError(f"Invalid number: {token}")
# Handle closing parenthesis or operator as error
if token in ')+-*/':
raise ValueError(f"Unexpected token: {token}")
raise ValueError(f"Unexpected token: {token}")