feat: finish clap parser and resolver
This commit is contained in:
@ -48,7 +48,8 @@ namespace yycc::carton::clap::parser {
|
|||||||
/// @brief The state machine context prepared for parser.
|
/// @brief The state machine context prepared for parser.
|
||||||
struct ParserContext {
|
struct ParserContext {
|
||||||
ParserContext(const APPLICATION::Application& app) : state(ParserState::Normal), opt_waiting(std::nullopt), app(app), values() {}
|
ParserContext(const APPLICATION::Application& app) : state(ParserState::Normal), opt_waiting(std::nullopt), app(app), values() {}
|
||||||
YYCC_DEFAULT_COPY_MOVE(ParserContext)
|
// We have a "const" reference member so we delete these.
|
||||||
|
YYCC_DELETE_COPY_MOVE(ParserContext)
|
||||||
|
|
||||||
ParserState state; ///< Current state.
|
ParserState state; ///< Current state.
|
||||||
std::optional<TYPES::Token> opt_waiting; ///< The token to the option waiting for associated value.
|
std::optional<TYPES::Token> opt_waiting; ///< The token to the option waiting for associated value.
|
||||||
@ -61,14 +62,15 @@ namespace yycc::carton::clap::parser {
|
|||||||
#pragma region Core
|
#pragma region Core
|
||||||
|
|
||||||
/// @brief Core capture function.
|
/// @brief Core capture function.
|
||||||
static TYPES::ClapResult<std::map<TYPES::Token, std::optional<std::u8string>>> capture(const APPLICATION::Application& app) {
|
template<std::ranges::viewable_range V>
|
||||||
|
static TYPES::ClapResult<std::map<TYPES::Token, std::optional<std::u8string>>> capture(const APPLICATION::Application& app, V args) {
|
||||||
// Create context.
|
// Create context.
|
||||||
ParserContext ctx(app);
|
ParserContext ctx(app);
|
||||||
|
|
||||||
// Fetch commandline arguments
|
// Fetch commandline arguments
|
||||||
// And skip the first argument because it is the path to executable.
|
// And skip the first argument because it is the path to executable.
|
||||||
// Then start to execute until all arguments are consumed.
|
// Then start to execute until all arguments are consumed.
|
||||||
for (const auto& arg : ENV::get_args() | std::views::drop(1)) {
|
for (const auto& arg : args | std::views::drop(1)) {
|
||||||
// Fetch argument kind
|
// Fetch argument kind
|
||||||
ClassifiedArgument classified_arg(arg);
|
ClassifiedArgument classified_arg(arg);
|
||||||
|
|
||||||
@ -170,11 +172,17 @@ namespace yycc::carton::clap::parser {
|
|||||||
#pragma region Parser Class
|
#pragma region Parser Class
|
||||||
|
|
||||||
TYPES::ClapResult<Parser> Parser::from_user(const APPLICATION::Application& app, const std::vector<std::u8string_view>& args) {
|
TYPES::ClapResult<Parser> Parser::from_user(const APPLICATION::Application& app, const std::vector<std::u8string_view>& args) {
|
||||||
return TYPES::ClapResult<Parser>();
|
auto rv = capture(app, args);
|
||||||
|
if (rv.has_value()) return Parser(std::move(rv.value()));
|
||||||
|
else return std::unexpected(rv.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPES::ClapResult<Parser> Parser::from_system(const APPLICATION::Application& app) {
|
TYPES::ClapResult<Parser> Parser::from_system(const APPLICATION::Application& app) {
|
||||||
return TYPES::ClapResult<Parser>();
|
auto rv = capture(app, ENV::get_args() | std::views::transform([](auto s) {
|
||||||
|
return std::u8string_view(s);
|
||||||
|
}));
|
||||||
|
if (rv.has_value()) return Parser(std::move(rv.value()));
|
||||||
|
else return std::unexpected(rv.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser(decltype(Parser::values)&& value) : values(std::move(values)) {}
|
Parser::Parser(decltype(Parser::values)&& value) : values(std::move(values)) {}
|
||||||
|
|||||||
@ -1,16 +1,66 @@
|
|||||||
#include "resolver.hpp"
|
#include "resolver.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
#include "../../env.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
#define TYPES ::yycc::carton::clap::types
|
#define TYPES ::yycc::carton::clap::types
|
||||||
|
#define APPLICATION ::yycc::carton::clap::application
|
||||||
|
#define ENV ::yycc::env
|
||||||
namespace yycc::carton::clap::resolver {
|
namespace yycc::carton::clap::resolver {
|
||||||
|
|
||||||
#pragma region Core
|
#pragma region Core
|
||||||
|
|
||||||
|
/// @brief Core capture function
|
||||||
|
template<std::ranges::viewable_range V>
|
||||||
|
static TYPES::ClapResult<std::map<TYPES::Token, std::optional<std::u8string>>> capture(const APPLICATION::Application& app, V vars) {
|
||||||
|
std::map<TYPES::Token, std::optional<std::u8string>> values;
|
||||||
|
const auto& variables = app.get_variables();
|
||||||
|
|
||||||
|
// Iterate variable list and process them one by one.
|
||||||
|
for (const auto& [name, value] : vars) {
|
||||||
|
// Check whether capture this variable.
|
||||||
|
auto opt_token = variables.find_name(name);
|
||||||
|
if (!opt_token.has_value()) continue;
|
||||||
|
auto token = opt_token.value();
|
||||||
|
|
||||||
|
// Check whether it is captured.
|
||||||
|
// If it is already captured, report error,
|
||||||
|
// because environment variable can not be duplicated.
|
||||||
|
if (values.contains(token)) {
|
||||||
|
throw std::runtime_error("impossible duplicated environment variable name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally check whether it care value, and insert data.
|
||||||
|
if (variables.get_variable(token).is_care_value()) {
|
||||||
|
values.emplace(token, value);
|
||||||
|
} else {
|
||||||
|
values.emplace(token, std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Resolver Class
|
#pragma region Resolver Class
|
||||||
|
|
||||||
|
TYPES::ClapResult<Resolver> Resolver::from_user(const APPLICATION::Application& app,
|
||||||
|
const std::vector<std::pair<std::u8string_view, std::u8string_view>>& vars) {
|
||||||
|
auto rv = capture(app, vars);
|
||||||
|
if (rv.has_value()) return Resolver(std::move(rv.value()));
|
||||||
|
else return std::unexpected(rv.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPES::ClapResult<Resolver> Resolver::from_system(const APPLICATION::Application& app) {
|
||||||
|
auto rv = capture(app, ENV::get_vars() | std::views::transform([](auto p) {
|
||||||
|
return std::make_pair<std::u8string_view, std::u8string_view>(p.first, p.second);
|
||||||
|
}));
|
||||||
|
if (rv.has_value()) return Resolver(std::move(rv.value()));
|
||||||
|
else return std::unexpected(rv.error());
|
||||||
|
}
|
||||||
|
|
||||||
Resolver::Resolver(decltype(Resolver::values)&& values) : values(std::move(values)) {}
|
Resolver::Resolver(decltype(Resolver::values)&& values) : values(std::move(values)) {}
|
||||||
|
|
||||||
Resolver::~Resolver() {}
|
Resolver::~Resolver() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user