CODE-0006 · grok-4.20-reasoning (default)def eval_expr(s):
tokens = []
i = 0
while i < len(s):
if s[i].isspace():
i += 1
continue
if s[i] in '+-*/()':
tokens.append(s[i])
i += 1
continue
if s[i].isdigit() or s[i] == '.':
j = i + 1
while j < len(s) and (s[j].isdigit() or s[j] == '.'):
j += 1
num_str = s[i:j]
try:
if '.' in num_str:
num = float(num_str)
else:
num = int(num_str)
tokens.append(num)
except ValueError:
raise ValueError("Invalid number") from None
i = j
continue
raise ValueError("Unknown token")
if not tokens:
raise ValueError("Empty input")
pos = [0]
def peek():
if pos[0] < len(tokens):
return tokens[pos[0]]
return None
def consume():
tok = peek()
pos[0] += 1
return tok
def expr():
result = term()
while True:
op = peek()
if isinstance(op, str) and op in ('+', '-'):
consume()
right = term()
if op == '+':
result = result + right
else:
result = result - right
else:
break
return result
def term():
result = factor()
while True:
op = peek()
if isinstance(op, str) and op in ('*', '/'):
consume()
right = factor()
if op == '*':
result = result * right
else:
if right == 0:
raise ValueError("Division by zero")
result = result / right
else:
break
return result
def factor():
sign = 1
while True:
op = peek()
if isinstance(op, str) and op in ('+', '-'):
consume()
if op == '-':
sign = -sign
else:
break
atom_val = atom()
return sign * atom_val
def atom():
tok = peek()
if isinstance(tok, (int, float)):
consume()
return tok
if isinstance(tok, str) and tok == '(':
consume()
val = expr()
if peek() != ')':
raise ValueError("Mismatched parentheses")
consume()
return val
if tok is None:
raise ValueError("Unexpected end of input")
raise ValueError("Unexpected token")
result = expr()
if peek() is not None:
raise ValueError("Extra input after expression")
if isinstance(result, float) and result.is_integer():
return int(result)
return result