protected function compile($pattern)
    {
        if (isset($this->compileCache[$pattern])) {
            return $this->compileCache[$pattern];
        }

        $pcre = '(^';

        do {
            switch (true) {
                case preg_match('(^[^{]+)', $pattern, $match):
                    $pattern = substr($pattern, strlen($match[0]));
                    $pcre .= preg_quote($match[0]);
                    break;

                case preg_match('(^' . self::STANDARD_VARIABLE_REGEX . ')', $pattern, $match):
                    $pattern = substr($pattern, strlen($match[0]));
                    $pcre .= '(?P<' . $match[1] . '>[^/]+)';
                    break;

                case preg_match('(^' . self::SLASHES_VARIABLE_REGEX . ')', $pattern, $match):
                    $pattern = substr($pattern, strlen($match[0]));
                    $pcre .= '(?P<' . $match[1] . '>.+)';
                    break;

                default:
                    throw new Exceptions\InvalidArgumentException("Invalid pattern part: '$pattern'.");
            }
        } while ($pattern);

        $pcre .= '$)S';

        $this->compileCache[$pattern] = $pcre;

        return $pcre;
    }