CODE-0002 · deepseek-v4-pro (default)
import re

def parse_semver(s):
    if not isinstance(s, str):
        return None
    pattern = r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)' \
              r'(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?' \
              r'(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$'
    m = re.fullmatch(pattern, s)
    if not m:
        return None
    major = int(m.group(1))
    minor = int(m.group(2))
    patch = int(m.group(3))
    prerelease = m.group(4)
    build = m.group(5)

    # prerelease: no leading zeros in numeric identifiers
    if prerelease is not None:
        for token in prerelease.split('.'):
            if token.isdigit() and token != '0' and token[0] == '0':
                return None

    return {
        "major": major,
        "minor": minor,
        "patch": patch,
        "prerelease": prerelease,
        "build": build
    }