protected function buildRegex(array $tokens, array $constraints)
    {
        $groupIndex      = 1;
        $regex           = '';
        $quotedDelimiter = preg_quote($this->delimiter);

        foreach ($tokens as $token) {
            switch ($token[static::TYPE]) {
                case 'literal':
                    $regex .= preg_quote($token[static::LITERAL]);
                    break;

                case 'parameter':
                    $groupName = '?P<param' . $groupIndex . '>';

                    if (isset($constraints[$token[static::NAME]])) {
                        $regex .= '(' . $groupName . $constraints[$token[static::NAME]] . ')';
                    } elseif ($token[static::DELIMITERS] === null) {
                        $regex .= '(' . $groupName . '[^' . $quotedDelimiter . ']+)';
                    } else {
                        $regex .= '(' . $groupName . '[^' . $token[static::DELIMITERS] . ']+)';
                    }

                    $this->paramMap['param' . $groupIndex] = $token[static::NAME];
                    ++$groupIndex;
                    break;

                case 'optional-start':
                    $regex .= '(?:';
                    break;

                case 'optional-end':
                    $regex .= ')?';
                    break;
            }
        }

        return $regex;
    }