working on subparsers

v2
Brett 2025-02-13 13:59:59 -05:00
parent 44a57e5ec2
commit 89d95dfec4
2 changed files with 89 additions and 6 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
include(cmake/color.cmake)
set(BLT_VERSION 4.0.4)
set(BLT_VERSION 4.0.5)
set(BLT_TARGET BLT)

View File

@ -56,6 +56,49 @@ namespace blt::argparse
}
};
class subparse_error final : public std::exception
{
public:
explicit subparse_error(const std::string_view found_string, std::vector<std::string_view> allowed_strings): m_found_string(found_string),
m_allowed_strings(std::move(allowed_strings))
{
}
[[nodiscard]] const std::vector<std::string_view>& get_allowed_strings() const
{
return m_allowed_strings;
}
[[nodiscard]] std::string_view get_found_string() const
{
return m_found_string;
}
[[nodiscard]] std::string error_string() const
{
std::string message = "Subparser Error: ";
message += m_found_string;
message += " is not a valid command. Allowed commands are: {";
for (const auto [i, allowed_string] : enumerate(m_allowed_strings))
{
message += allowed_string;
if (i != m_allowed_strings.size() - 1)
message += ' ';
}
message += "}";
return message;
}
[[nodiscard]] const char* what() const override
{
return "Please use error_string() method instead of what(). This exception should *always* be caught!";
}
private:
std::string_view m_found_string;
std::vector<std::string_view> m_allowed_strings;
};
template <typename... Args>
struct arg_data_helper_t
{
@ -207,6 +250,8 @@ namespace blt::argparse
class argument_parser_t
{
friend argument_subparser_t;
public:
explicit argument_parser_t(const std::optional<std::string_view> name = {}, const std::optional<std::string_view> usage = {}):
m_name(name), m_usage(usage)
@ -219,6 +264,10 @@ namespace blt::argparse
return *this;
}
void parse(argument_consumer_t& consumer) // NOLINT
{
}
private:
std::optional<std::string> m_name;
std::optional<std::string> m_usage;
@ -229,17 +278,51 @@ namespace blt::argparse
class argument_subparser_t
{
public:
argument_parser_t add_subparser(const std::string_view dest)
explicit argument_subparser_t(const argument_parser_t& parent): m_parent(&parent)
{
}
argument_parser_t add_subparser(std::string& dest)
argument_parser_t& add_parser(const std::string_view name)
{
m_parsers.emplace(name);
return m_parsers[name];
}
/**
* Parses the next argument using the provided argument consumer.
*
* This function uses an argument consumer to extract and process the next argument.
* If the argument is a flag or if it cannot be matched against the available parsers,
* an exception is thrown.
*
* @param consumer Reference to an argument_consumer_t object, which handles argument parsing.
* The consumer provides the next argument to be parsed.
*
* @throws detail::subparse_error If the argument is a flag or does not match any known parser.
*/
void parse(argument_consumer_t& consumer) // NOLINT
{
const auto key = consumer.consume();
if (key.is_flag())
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
const auto it = m_parsers.find(key.get_name());
if (it == m_parsers.end())
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
it->second.parse(consumer);
}
private:
[[nodiscard]] std::vector<std::string_view> get_allowed_strings() const
{
std::vector<std::string_view> vec;
for (const auto& [key, value] : m_parsers)
vec.push_back(key);
return vec;
}
const argument_parser_t* m_parent;
hashmap_t<std::string_view, argument_parser_t> m_parsers;
};
}