From a1d19cf09c917d8e1e51b84b25c05198cb97dad3 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 9 Dec 2025 22:55:21 +0800 Subject: [PATCH] feat: finish clap parser and resolver --- src/yycc/carton/clap/parser.cpp | 18 ++++++++--- src/yycc/carton/clap/resolver.cpp | 52 ++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/yycc/carton/clap/parser.cpp b/src/yycc/carton/clap/parser.cpp index 5ecaf41..b7ae9ee 100644 --- a/src/yycc/carton/clap/parser.cpp +++ b/src/yycc/carton/clap/parser.cpp @@ -48,7 +48,8 @@ namespace yycc::carton::clap::parser { /// @brief The state machine context prepared for parser. struct ParserContext { 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. std::optional opt_waiting; ///< The token to the option waiting for associated value. @@ -61,14 +62,15 @@ namespace yycc::carton::clap::parser { #pragma region Core /// @brief Core capture function. - static TYPES::ClapResult>> capture(const APPLICATION::Application& app) { + template + static TYPES::ClapResult>> capture(const APPLICATION::Application& app, V args) { // Create context. ParserContext ctx(app); // Fetch commandline arguments // And skip the first argument because it is the path to executable. // 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 ClassifiedArgument classified_arg(arg); @@ -170,11 +172,17 @@ namespace yycc::carton::clap::parser { #pragma region Parser Class TYPES::ClapResult Parser::from_user(const APPLICATION::Application& app, const std::vector& args) { - return TYPES::ClapResult(); + auto rv = capture(app, args); + if (rv.has_value()) return Parser(std::move(rv.value())); + else return std::unexpected(rv.error()); } TYPES::ClapResult Parser::from_system(const APPLICATION::Application& app) { - return TYPES::ClapResult(); + 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)) {} diff --git a/src/yycc/carton/clap/resolver.cpp b/src/yycc/carton/clap/resolver.cpp index 32ec900..f40781e 100644 --- a/src/yycc/carton/clap/resolver.cpp +++ b/src/yycc/carton/clap/resolver.cpp @@ -1,16 +1,66 @@ #include "resolver.hpp" #include "types.hpp" +#include "../../env.hpp" +#include +#include #define TYPES ::yycc::carton::clap::types - +#define APPLICATION ::yycc::carton::clap::application +#define ENV ::yycc::env namespace yycc::carton::clap::resolver { #pragma region Core + /// @brief Core capture function + template + static TYPES::ClapResult>> capture(const APPLICATION::Application& app, V vars) { + std::map> 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 region Resolver Class + TYPES::ClapResult Resolver::from_user(const APPLICATION::Application& app, + const std::vector>& 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::from_system(const APPLICATION::Application& app) { + auto rv = capture(app, ENV::get_vars() | std::views::transform([](auto p) { + return std::make_pair(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() {}