CODE-0002 · claude-haiku-4-5 (default)
import re

def parse_semver(s):
    """Parse a Semantic Versioning 2.0.0 version string.
    
    Returns a dict with keys 'major', 'minor', 'patch', 'prerelease', 'build'
    on success, or None if the string is not a valid SemVer version.
    """
    if not isinstance(s, str):
        return None
    
    # Pattern for a valid SemVer string
    # MAJOR.MINOR.PATCH[-prerelease][+build]
    pattern = r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*))?(?:\+([a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*))?$'
    
    match = re.match(pattern, s)
    if not match:
        return None
    
    major, minor, patch, prerelease, build = match.groups()
    
    # Validate prerelease identifiers if present
    if prerelease:
        identifiers = prerelease.split('.')
        for identifier in identifiers:
            if not identifier:  # Empty identifier
                return None
            # Check if numeric identifier has leading zeros
            if identifier.isdigit() and len(identifier) > 1 and identifier[0] == '0':
                return None
    
    # Build metadata identifiers are already validated by the regex
    # (leading zeros are allowed in build metadata)
    
    return {
        'major': int(major),
        'minor': int(minor),
        'patch': int(patch),
        'prerelease': prerelease if prerelease else None,
        'build': build if build else None
    }