feat: finish clap parser basic layout
This commit is contained in:
@ -36,6 +36,8 @@ PRIVATE
|
||||
yycc/carton/clap/summary.cpp
|
||||
yycc/carton/clap/application.cpp
|
||||
yycc/carton/clap/manual.cpp
|
||||
yycc/carton/clap/parser.cpp
|
||||
yycc/carton/clap/resolver.cpp
|
||||
)
|
||||
target_sources(YYCCommonplace
|
||||
PUBLIC
|
||||
@ -97,6 +99,8 @@ FILES
|
||||
yycc/carton/clap/application.hpp
|
||||
yycc/carton/clap/manual.hpp
|
||||
yycc/carton/clap/validator.hpp
|
||||
yycc/carton/clap/parser.hpp
|
||||
yycc/carton/clap/resolver.hpp
|
||||
yycc/carton/fft.hpp
|
||||
)
|
||||
# Setup header infomations
|
||||
|
||||
3
src/yycc/carton/clap/parser.cpp
Normal file
3
src/yycc/carton/clap/parser.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "parser.hpp"
|
||||
|
||||
namespace yycc::carton::clap::parser {}
|
||||
5
src/yycc/carton/clap/parser.hpp
Normal file
5
src/yycc/carton/clap/parser.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace yycc::carton::clap::parser {
|
||||
|
||||
}
|
||||
81
src/yycc/carton/clap/resolver.cpp
Normal file
81
src/yycc/carton/clap/resolver.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "resolver.hpp"
|
||||
#include "types.hpp"
|
||||
#include <string_view>
|
||||
|
||||
#define TYPES ::yycc::carton::clap::types
|
||||
|
||||
namespace yycc::carton::clap::resolver {
|
||||
|
||||
#pragma region Misc
|
||||
|
||||
/// @brief The states of parser internal state machine.
|
||||
enum class ParserState {
|
||||
Normal, ///< Normal state. Expect an option.
|
||||
WaitingValue, ///< Waiting an associated value.
|
||||
};
|
||||
/// @brief The state machine context prepared for parser.
|
||||
struct ParserContext {
|
||||
ParserContext() : state(ParserState::Normal), opt_waiting(std::nullopt) {}
|
||||
YYCC_DEFAULT_COPY_MOVE(ParserContext)
|
||||
|
||||
ParserState state; ///< Current state.
|
||||
std::optional<TYPES::Token> opt_waiting; ///< The token to the option waiting for associated value.
|
||||
};
|
||||
|
||||
/// @brief The kind of argument.
|
||||
enum class ArgumentKind { LongName, ShortName, Value };
|
||||
/// @brief Representing a classified argument.
|
||||
struct ClassifiedArgument {
|
||||
ClassifiedArgument(const std::u8string_view& arg) {
|
||||
if (arg.starts_with(TYPES::DOUBLE_DASH)) {
|
||||
kind = ArgumentKind::LongName;
|
||||
content = arg.substr(TYPES::DOUBLE_DASH.length());
|
||||
} else if (arg.starts_with(TYPES::DASH)) {
|
||||
kind = ArgumentKind::ShortName;
|
||||
content = arg.substr(TYPES::DASH.length());
|
||||
} else {
|
||||
kind = ArgumentKind::Value;
|
||||
content = arg;
|
||||
}
|
||||
}
|
||||
YYCC_DEFAULT_COPY_MOVE(ClassifiedArgument)
|
||||
|
||||
/// @brief The kind of argument.
|
||||
ArgumentKind kind;
|
||||
/**
|
||||
* @brief The data of argument.
|
||||
* @details For long and short name, it is the body of option, the words removing any leading dash.
|
||||
* For value, it just the value self.
|
||||
*/
|
||||
std::u8string_view content;
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Core
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Parser Class
|
||||
|
||||
Parser::Parser(const NS_YYCC_CLAP_APPLICATION::Application& app) {}
|
||||
|
||||
Parser::~Parser() {}
|
||||
|
||||
bool Parser::has_option(TYPES::Token token) const {
|
||||
// TODO:
|
||||
return false;
|
||||
}
|
||||
|
||||
TYPES::ClapResult<bool> Parser::get_flag_option(TYPES::Token token) const {
|
||||
// TODO:
|
||||
return TYPES::ClapResult<bool>();
|
||||
}
|
||||
|
||||
TYPES::ClapResult<std::u8string_view> Parser::get_raw_value_option(TYPES::Token token) const {
|
||||
// TODO:
|
||||
return TYPES::ClapResult<std::u8string_view>();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
} // namespace yycc::carton::clap::resolver
|
||||
53
src/yycc/carton/clap/resolver.hpp
Normal file
53
src/yycc/carton/clap/resolver.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "../../macro/class_copy_move.hpp"
|
||||
#include "application.hpp"
|
||||
#include "validator.hpp"
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#define NS_YYCC_CLAP_TYPES ::yycc::carton::clap::types
|
||||
#define NS_YYCC_CLAP_APPLICATION ::yycc::carton::clap::application
|
||||
#define NS_YYCC_CLAP_VALIDATOR ::yycc::carton::clap::validator
|
||||
|
||||
namespace yycc::carton::clap::resolver {
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
Parser(const NS_YYCC_CLAP_APPLICATION::Application& app);
|
||||
~Parser();
|
||||
YYCC_DEFAULT_COPY_MOVE(Parser)
|
||||
|
||||
private:
|
||||
NS_YYCC_CLAP_TYPES::ClapResult<std::u8string_view> get_raw_value_option(NS_YYCC_CLAP_TYPES::Token token) const;
|
||||
|
||||
public:
|
||||
bool has_option(NS_YYCC_CLAP_TYPES::Token token) const;
|
||||
NS_YYCC_CLAP_TYPES::ClapResult<bool> get_flag_option(NS_YYCC_CLAP_TYPES::Token token) const;
|
||||
template<NS_YYCC_CLAP_VALIDATOR::Validator T>
|
||||
NS_YYCC_CLAP_TYPES::ClapResult<NS_YYCC_CLAP_VALIDATOR::ValidatorReturnType<T>> get_value_option(
|
||||
NS_YYCC_CLAP_TYPES::Token token) const {
|
||||
auto raw_value = this->get_raw_value_option(token);
|
||||
if (raw_value.has_value()) {
|
||||
T validator{};
|
||||
auto value = validator.validate(raw_value.value());
|
||||
if (value.has_value()) return value.value();
|
||||
else return std::unexpected(NS_YYCC_CLAP_TYPES::ClapError::BadCast);
|
||||
} else {
|
||||
return std::unexpected(raw_value.error())
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief All captured commandline argument.
|
||||
* @details Key is the token to already registered option.
|
||||
* Value is the associated value for key token.
|
||||
* If it is no-value option, the value will be \c std::nullopt.
|
||||
*/
|
||||
std::map<NS_YYCC_CLAP_TYPES::Token, std::optional<std::u8string>> values;
|
||||
};
|
||||
|
||||
} // namespace yycc::carton::clap::resolver
|
||||
|
||||
#undef NS_YYCC_CLAP_TYPES
|
||||
@ -6,7 +6,12 @@ namespace yycc::carton::clap::types {
|
||||
|
||||
/// @brief All possible error kind occurs in this module.
|
||||
enum class ClapError {
|
||||
|
||||
InvalidName, ///< When parsing commandline argument, given option name is invalid.
|
||||
DuplicatedAssign, ///< When parsing commandline argument, multiple assign for a single option.
|
||||
UnexpectedValue, ///< When parsing commandline argument, reach associated value unexpected.
|
||||
LostValue, ///< When parsing commandline argument, fail to find associated value.
|
||||
NotCaptured, ///< When fetching option or variable, given option or variable is not captured.
|
||||
BadCast ///< When fetching option or variable, the content of given option or variable can not be cast into expected type.
|
||||
};
|
||||
|
||||
/// @brief The result type used in this module.
|
||||
|
||||
@ -19,17 +19,23 @@ namespace yycc::carton::clap::validator {
|
||||
* And, it also should have an member function called "validate"
|
||||
* which receive <TT>const std::string_view&</TT> as its only argument,
|
||||
* and return <TT>std::optional<ReturnType></TT> as result.
|
||||
* If this \t std::optional is empty, it means that there is some error occurs when validating,
|
||||
* If this \c std::optional is empty, it means that there is some error occurs when validating,
|
||||
* otherwise, it is the validated value.
|
||||
*
|
||||
* Finally, it must can be default initialized.
|
||||
*/
|
||||
template<typename T>
|
||||
concept Validator = requires(const T& t, const std::u8string_view& sv) {
|
||||
concept Validator = std::default_initializable<T> && requires(const T& t, const std::u8string_view& sv) {
|
||||
// Check whether there is T::ReturnType type
|
||||
typename T::ReturnType;
|
||||
// Check whether there is "validate" member function and it has correct signature.
|
||||
{ t.validate(sv) } -> std::same_as<std::optional<typename T::ReturnType>>;
|
||||
};
|
||||
|
||||
/// @brief A convenient alias to the return type of validator.
|
||||
template<Validator T>
|
||||
using ValidatorReturnType = T::ReturnType;
|
||||
|
||||
template<std::integral T, auto TMin = std::numeric_limits<T>::min(), auto TMax = std::numeric_limits<T>::max()>
|
||||
struct IntegralValidator {
|
||||
static_assert(TMin <= TMax);
|
||||
|
||||
Reference in New Issue
Block a user