CODE-0002 · grok-4.20-reasoning (default)
import re

SEMVER_REGEX = re.compile(
    r'^(?P<major>0|[1-9][0-9]*)'
    r'\.(?P<minor>0|[1-9][0-9]*)'
    r'\.(?P<patch>0|[1-9][0-9]*)'
    r'(?:-(?P<prerelease>(?:0|[1-9][0-9]*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9][0-9]*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?'
    r'(?:\+(?P<build>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$'
)

def parse_semver(s):
    if not isinstance(s, str):
        return None
    match = SEMVER_REGEX.match(s)
    if not match:
        return None
    return {
        "major": int(match.group("major")),
        "minor": int(match.group("minor")),
        "patch": int(match.group("patch")),
        "prerelease": match.group("prerelease"),
        "build": match.group("build"),
    }