public function parse(string $definition, TypeCollection $types): RoutePath
    {
        $definition = new Input($definition);

        try {
            $parsed = $this->parseRoute($definition, $types, []);
        } catch (UnexpectedChar $exception) {
            if ($definition->peek() === Input::END) {
                throw InvalidRoute::unexpectedEnd($definition);
            }

            $expected = $exception->getExpected();

            throw InvalidRoute::unexpectedCharacter($definition, $expected);
        }

        if (!$definition->atEnd()) {
            if ($definition->getLastTaken() === "]" && $definition->peek() !== "]") {
                throw InvalidRoute::optionalIsNotSuffix($definition);
            }

            throw InvalidRoute::unexpectedCharacter($definition);
        }

        return $parsed;
    }