CODE-0006 · kimi-k2.7-code (default)
import re
import math

def eval_expr(s):
    if not s or s.strip() == "":
        raise ValueError("Empty expression")
    
    # Tokenize
    tokens = tokenize(s)
    if not tokens:
        raise ValueError("Empty expression")
    
    # Parse and evaluate
    pos = [0]
    result = parse_expression(tokens, pos)
    
    # Check all tokens consumed
    if pos[0] != len(tokens):
        raise ValueError("Unexpected token after valid expression")
    
    # Convert to int if exact integer
    if isinstance(result, float):
        if math.isfinite(result) and result == int(result):
            return int(result)
    return result

def tokenize(s):
    tokens = []
    i = 0
    while i < len(s):
        c = s[i]
        if c.isspace():
            i += 1
            continue
        elif c in '+-*/()':
            tokens.append(c)
            i += 1
        elif c.isdigit() or c == '.':
            # Parse number
            start = i
            has_dot = (c == '.')
            i += 1
            while i < len(s) and (s[i].isdigit() or s[i] == '.'):
                if s[i] == '.':
                    if has_dot:
                        raise ValueError("Multiple dots in number")
                    has_dot = True
                i += 1
            num_str = s[start:i]
            if num_str == '.' or num_str.startswith('.') and num_str[1:] == '':
                raise ValueError("Invalid number")
            # Validate it's a proper number
            try:
                if has_dot:
                    float(num_str)  # validate
                else:
                    int(num_str)  # validate
            except ValueError:
                raise ValueError("Invalid number")
            tokens.append(num_str)
        else:
            raise ValueError(f"Unknown token: {c}")
    return tokens

def parse_expression(tokens, pos):
    # expression = term { ('+' | '-') term }
    left = parse_term(tokens, pos)
    while pos[0] < len(tokens) and tokens[pos[0]] in '+-':
        op = tokens[pos[0]]
        pos[0] += 1
        right = parse_term(tokens, pos)
        if op == '+':
            left = left + right
        else:
            left = left - right
    return left

def parse_term(tokens, pos):
    # term = factor { ('*' | '/') factor }
    left = parse_factor(tokens, pos)
    while pos[0] < len(tokens) and tokens[pos[0]] in '*/':
        op = tokens[pos[0]]
        pos[0] += 1
        right = parse_factor(tokens, pos)
        if op == '*':
            left = left * right
        else:
            if right == 0:
                raise ValueError("Division by zero")
            left = left / right
    return left

def parse_factor(tokens, pos):
    # factor = ('+' | '-')* primary
    sign = 1
    while pos[0] < len(tokens) and tokens[pos[0]] in '+-':
        if tokens[pos[0]] == '-':
            sign = -sign
        pos[0] += 1
    
    value = parse_primary(tokens, pos)
    return sign * value

def parse_primary(tokens, pos):
    if pos[0] >= len(tokens):
        raise ValueError("Unexpected end of expression")
    
    token = tokens[pos[0]]
    
    if token == '(':
        pos[0] += 1
        value = parse_expression(tokens, pos)
        if pos[0] >= len(tokens) or tokens[pos[0]] != ')':
            raise ValueError("Mismatched parentheses")
        pos[0] += 1
        return value
    elif token == ')':
        raise ValueError("Unexpected closing parenthesis")
    elif token in '+-*/':
        raise ValueError("Unexpected operator")
    else:
        # Number
        pos[0] += 1
        if '.' in token:
            return float(token)
        else:
            return int(token)