<?php
\\FastRoute\RouteParser\Std;
 
class Std implements RouteParser
{
    const VARIABLE_REGEX = <<<'REGEX'
\{
    \s* ([a-zA-Z_][a-zA-Z0-9_-]*) \s*
    (?:
        : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
    )?
\}
REGEX;
    const DEFAULT_DISPATCH_REGEX = '[^/]+';
 
    public function parse($route)
    {
        $routeWithoutClosingOptionals = rtrim($route, ']');  
        $numOptionals = strlen($route) - strlen($routeWithoutClosingOptionals);  
        // Split on [ while skipping placeholders
        $segments = preg_split('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \[~x', $routeWithoutClosingOptionals);  
        if ($numOptionals !== count($segments) - 1) {             // If there are any ] in the middle of the route, throw a more specific error message
            if (preg_match('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \]~x', $routeWithoutClosingOptionals)) {                 throw new BadRouteException('Optional segments can only occur at the end of a route');
            }
            throw new BadRouteException("Number of opening '[' and closing ']' does not match");
        }
 
        $currentRoute = '';
        $routeDatas = [];
        foreach ($segments as $n => $segment) {
 
            if ($segment === '' && $n !== 0) {
                throw new BadRouteException('Empty optional part');
            }
 
            $currentRoute .= $segment;
            $routeDatas[] = $this->parsePlaceholders($currentRoute);
 
        }
 
        return $routeDatas;
    }
}
				PD9waHAKXFxGYXN0Um91dGVcUm91dGVQYXJzZXJcU3RkOwoKY2xhc3MgU3RkIGltcGxlbWVudHMgUm91dGVQYXJzZXIKewogICAgY29uc3QgVkFSSUFCTEVfUkVHRVggPSA8PDwnUkVHRVgnClx7CiAgICBccyogKFthLXpBLVpfXVthLXpBLVowLTlfLV0qKSBccyoKICAgICg/OgogICAgICAgIDogXHMqIChbXnt9XSooPzpceyg/LTEpXH1bXnt9XSopKikKICAgICk/Clx9ClJFR0VYOwogICAgY29uc3QgREVGQVVMVF9ESVNQQVRDSF9SRUdFWCA9ICdbXi9dKyc7CgogICAgcHVibGljIGZ1bmN0aW9uIHBhcnNlKCRyb3V0ZSkKICAgIHsKICAgICAgICAkcm91dGVXaXRob3V0Q2xvc2luZ09wdGlvbmFscyA9IHJ0cmltKCRyb3V0ZSwgJ10nKTsKICAgICAKICAgICAgICAkbnVtT3B0aW9uYWxzID0gc3RybGVuKCRyb3V0ZSkgLSBzdHJsZW4oJHJvdXRlV2l0aG91dENsb3NpbmdPcHRpb25hbHMpOwogICAKICAgICAgICAvLyBTcGxpdCBvbiBbIHdoaWxlIHNraXBwaW5nIHBsYWNlaG9sZGVycwogICAgICAgICRzZWdtZW50cyA9IHByZWdfc3BsaXQoJ34nIC4gc2VsZjo6VkFSSUFCTEVfUkVHRVggLiAnKCpTS0lQKSgqRikgfCBcW354JywgJHJvdXRlV2l0aG91dENsb3NpbmdPcHRpb25hbHMpOwogICAgIAogICAgICAgIGlmICgkbnVtT3B0aW9uYWxzICE9PSBjb3VudCgkc2VnbWVudHMpIC0gMSkgewogICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYW55IF0gaW4gdGhlIG1pZGRsZSBvZiB0aGUgcm91dGUsIHRocm93IGEgbW9yZSBzcGVjaWZpYyBlcnJvciBtZXNzYWdlCiAgICAgICAgICAgIGlmIChwcmVnX21hdGNoKCd+JyAuIHNlbGY6OlZBUklBQkxFX1JFR0VYIC4gJygqU0tJUCkoKkYpIHwgXF1+eCcsICRyb3V0ZVdpdGhvdXRDbG9zaW5nT3B0aW9uYWxzKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEJhZFJvdXRlRXhjZXB0aW9uKCdPcHRpb25hbCBzZWdtZW50cyBjYW4gb25seSBvY2N1ciBhdCB0aGUgZW5kIG9mIGEgcm91dGUnKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBuZXcgQmFkUm91dGVFeGNlcHRpb24oIk51bWJlciBvZiBvcGVuaW5nICdbJyBhbmQgY2xvc2luZyAnXScgZG9lcyBub3QgbWF0Y2giKTsKICAgICAgICB9CgogICAgICAgICRjdXJyZW50Um91dGUgPSAnJzsKICAgICAgICAkcm91dGVEYXRhcyA9IFtdOwogICAgICAgIGZvcmVhY2ggKCRzZWdtZW50cyBhcyAkbiA9PiAkc2VnbWVudCkgewoKICAgICAgICAgICAgaWYgKCRzZWdtZW50ID09PSAnJyAmJiAkbiAhPT0gMCkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEJhZFJvdXRlRXhjZXB0aW9uKCdFbXB0eSBvcHRpb25hbCBwYXJ0Jyk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICRjdXJyZW50Um91dGUgLj0gJHNlZ21lbnQ7CiAgICAgICAgICAgICRyb3V0ZURhdGFzW10gPSAkdGhpcy0+cGFyc2VQbGFjZWhvbGRlcnMoJGN1cnJlbnRSb3V0ZSk7CiAgICAgICAgCiAgICAgICAgfQoKICAgICAgICByZXR1cm4gJHJvdXRlRGF0YXM7CiAgICB9Cn0=