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

def parse_semver(s):
    if not isinstance(s, str):
        return None
    
    # Main pattern: MAJOR.MINOR.PATCH[-prerelease][+build]
    # We need to validate leading zeros separately for numeric parts
    pattern = r'^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$'
    match = re.match(pattern, s)
    if not match:
        return None
    
    major_str, minor_str, patch_str, prerelease, build = match.groups()
    
    # Validate no leading zeros for major, minor, patch
    for num_str in (major_str, minor_str, patch_str):
        if len(num_str) > 1 and num_str[0] == '0':
            return None
    
    # Validate prerelease identifiers
    if prerelease is not None:
        prerelease_ids = prerelease.split('.')
        for pid in prerelease_ids:
            if not pid:  # empty identifier (e.g., consecutive dots)
                return None
            # Check if numeric identifier has leading zeros
            if pid.isdigit():
                if len(pid) > 1 and pid[0] == '0':
                    return None
            # else: non-numeric, valid characters already checked by regex
    
    # Validate build identifiers (just check non-empty, regex already checks chars)
    if build is not None:
        build_ids = build.split('.')
        for bid in build_ids:
            if not bid:  # empty identifier
                return None
    
    return {
        "major": int(major_str),
        "minor": int(minor_str),
        "patch": int(patch_str),
        "prerelease": prerelease,
        "build": build
    }