CODE-0006 · claude-opus-4-8 (low)
A recursive descent / shunting parser. I'll write a tokenizer plus a recursive descent parser.

import re

def eval_expr(s):
    if not isinstance(s, str):
        raise ValueError("expression must be a string")

    tokens = _tokenize(s)
    parser = _Parser(tokens)
    value = parser.parse()
    return _normalize(value)


_NUMBER_RE = re.compile(r'(?:\d+\.\d*|\.\d+|\d+)')


def _tokenize(s):
    tokens = []
    i = 0
    n = len(s)
    while i < n:
        c = s[i]
        if c.isspace():
            i += 1
            continue
        if c in '+-*/()':
            tokens.append((c, c))
            i += 1
            continue
        if c.isdigit() or c == '.':
            m = _NUMBER_RE.match(s, i)
            if not m:
                raise ValueError("malformed number at position %d" % i)
            text = m.group(0)
            if text == '.':
                raise ValueError("malformed number at position %d" % i)
            tokens.append(('num', float(text)))
            i = m.end()
            continue
        raise ValueError("unknown token %r at position %d" % (c, i))
    return tokens


class _Parser:
    def __init__(self, tokens):
        self.tokens = tokens
        self.pos = 0

    def _peek(self):
        if self.pos < len(self.tokens):
            return self.tokens[self.pos]
        return (None, None)

    def _advance(self):
        tok = self.tokens[self.pos]
        self.pos += 1
        return tok

    def parse(self):
        if not self.tokens:
            raise ValueError("empty expression")
        value = self._expr()
        if self.pos != len(self.tokens):
            raise ValueError("unexpected trailing tokens")
        return value

    def _expr(self):
        # handles + and -
        value = self._term()
        while True:
            kind, _ = self._peek()
            if kind == '+':
                self._advance()
                value = value + self._term()
            elif kind == '-':
                self._advance()
                value = value - self._term()
            else:
                break
        return value

    def _term(self):
        # handles * and /
        value = self._factor()
        while True:
            kind, _ = self._peek()
            if kind == '*':
                self._advance()
                value = value * self._factor()
            elif kind == '/':
                self._advance()
                divisor = self._factor()
                if divisor == 0:
                    raise ValueError("division by zero")
                value = value / divisor
            else:
                break
        return value

    def _factor(self):
        # handles unary + and -
        kind, _ = self._peek()
        if kind == '+':
            self._advance()
            return self._factor()
        if kind == '-':
            self._advance()
            return -self._factor()
        return self._primary()

    def _primary(self):
        kind, value = self._peek()
        if kind == 'num':
            self._advance()
            return value
        if kind == '(':
            self._advance()
            inner = self._expr()
            close_kind, _ = self._peek()
            if close_kind != ')':
                raise ValueError("mismatched parentheses: expected ')'")
            self._advance()
            return inner
        if kind is None:
            raise ValueError("unexpected end of expression")
        raise ValueError("unexpected token %r" % (kind,))


def _normalize(value):
    if isinstance(value, float):
        if value != value or value in (float('inf'), float('-inf')):
            return value
        if value.is_integer():
            return int(value)
        return value
    return value