CODE-0002 · grok-composer-2.5-fast (default)
import re


_IDENTIFIER_RE = re.compile(r"^[0-9A-Za-z-]+$")
_CORE_RE = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(.*)$")


def _is_valid_prerelease_identifier(identifier: str) -> bool:
    if not identifier or not _IDENTIFIER_RE.fullmatch(identifier):
        return False
    if identifier.isdigit() and len(identifier) > 1 and identifier[0] == "0":
        return False
    return True


def _is_valid_build_identifier(identifier: str) -> bool:
    return bool(identifier) and _IDENTIFIER_RE.fullmatch(identifier) is not None


def _parse_dot_separated(
    value: str, validator
) -> bool:
    if not value:
        return False
    parts = value.split(".")
    if not parts:
        return False
    return all(validator(part) for part in parts)


def parse_semver(s):
    if not isinstance(s, str):
        return None

    match = _CORE_RE.match(s)
    if not match:
        return None

    major = int(match.group(1))
    minor = int(match.group(2))
    patch = int(match.group(3))
    remainder = match.group(4)

    prerelease = None
    build = None

    if remainder.startswith("-"):
        if "+" in remainder:
            pre_section, build_section = remainder.split("+", 1)
        else:
            pre_section, build_section = remainder, None

        pre_body = pre_section[1:]
        if not _parse_dot_separated(pre_body, _is_valid_prerelease_identifier):
            return None
        prerelease = pre_body

        if build_section is not None:
            if not _parse_dot_separated(build_section, _is_valid_build_identifier):
                return None
            build = build_section
    elif remainder.startswith("+"):
        build_body = remainder[1:]
        if not _parse_dot_separated(build_body, _is_valid_build_identifier):
            return None
        build = build_body
    elif remainder:
        return None

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