diff --git a/ArgsParser/argsparser.cpp b/ArgsParser/argsparser.cpp index 0a1b8e6..1fd52cb 100644 --- a/ArgsParser/argsparser.cpp +++ b/ArgsParser/argsparser.cpp @@ -23,13 +23,13 @@ QString __ArgvPackImpls::value() const { } FloatKeyValue::FloatKeyValue(const QString& key, const QString& means, bool optional) : - __FloatArgvImpl(key, means, optional) { } + __FloatArgvImpls(key, means, optional) { } -QString __FloatArgvImpl::bindKey() const { +QString __FloatArgvImpls::bindKey() const { return key_name; } -bool __FloatArgvImpl::optional() const { +bool __FloatArgvImpls::optional() const { return optional_value; } @@ -46,9 +46,11 @@ int FloatKeyValue::matchLenth() const { bool FloatKeyValue::parse(const QList args, int start) { auto args_t = args[start]; auto args_v = args[start + 1]; - if (args_t == bindKey()) + if (args_t == u8"--" + bindKey()){ setValue(args_v); - return args_t == bindKey(); + return true; + } + return false; } IndexParam::IndexParam(const QString& place_v, const QString& means) @@ -67,11 +69,11 @@ bool IndexParam::parse(const QList args, int start) { return true; } -__FloatArgvImpl::__FloatArgvImpl(const QString& key, const QString& means, bool optional) +__FloatArgvImpls::__FloatArgvImpls(const QString& key, const QString& means, bool optional) : __ArgvPackImpls(means, ParamType::FloatParam), key_name(key), optional_value(optional) { } FloatOption::FloatOption(const QString& key, const QString& means, bool opt) - : __FloatArgvImpl(key, means, opt) { + : __FloatArgvImpls(key, means, opt) { setValue(u8"0"); } @@ -88,28 +90,45 @@ int FloatOption::matchLenth() const { bool FloatOption::parse(const QList args, int start) { auto args_t = args[start]; setValue(QString::number(args_t == bindKey())); - return args_t == bindKey(); + return args_t == u8"--" + bindKey(); } -MatchMode::MatchMode(const QList> mode, int mode_code) - :args_mode(mode), code_store(mode_code) { } +MatchMode::MatchMode(int mode_code, const QString& mode) + :_means_explain(mode), code_store(mode_code) { } /** * @brief 获取模式代码 * @return 模式代码 */ +MatchMode& args_parse::MatchMode::operator<<(std::shared_ptr unit) { + args_mode << unit; + return *this; +} + int MatchMode::modeCode() const { return code_store; } -/** -* @brief 获取模式匹配结果 -* @return 模式匹配结果 -*/ +QString args_parse::MatchMode::usageString() const { + QString usage_string; + for (auto& item : args_mode) + usage_string += item->placeHolder() + u8" "; -QList> MatchMode::result() const { - return args_mode; + return usage_string; +} + +QString args_parse::MatchMode::explanString() const { + QStringList sections; + sections << u8" " + _means_explain; + sections << QString(" Switch:"); + + for (auto& item : args_mode) { + sections << " " + item->placeHolder(); + sections << " " + item->means(); + } + + return sections.join("\n"); } /** @@ -131,11 +150,11 @@ bool MatchMode::parse(const QList& args, int argv_index, int parse_inde }break; case ParamType::FloatParam:// 浮动参数匹配 { - QList> float_parsers; + QList> float_parsers; for (auto& unit : args_mode) { if (unit->paramType() == ParamType::FloatParam) - float_parsers << dynamic_pointer_cast<__FloatArgvImpl>(unit); + float_parsers << dynamic_pointer_cast<__FloatArgvImpls>(unit); } for (auto& unit : float_parsers) { @@ -156,11 +175,37 @@ bool MatchMode::parse(const QList& args, int argv_index, int parse_inde return false; } -void ArgsParser::loadMode(int mode_code, const QList>& args_model) { - this->match_modes.append(make_shared(args_model, mode_code)); +std::shared_ptr args_parse::MatchMode::getUnitViaKey(const QString& key) { + for (auto& u : args_mode) { + if (u->paramType() == ParamType::FloatParam) { + auto conv = std::dynamic_pointer_cast<__FloatArgvImpls>(u); + if (conv->bindKey() == key) + return u; + } + } + + return std::shared_ptr(); } -tuple>> ArgsParser::parse(int argc, char* argv[]) { +std::shared_ptr args_parse::MatchMode::getUnitViaPos(int pos) { + return args_mode[pos]; +} + +QString args_parse::ArgsParser::helpDoc() const { + QString help_string; + for (auto& mode : this->match_modes) { + help_string += "Usage:" + mode->usageString() + "\n"; + help_string += mode->explanString() + "\n\n"; + } + return help_string; +} + +ArgsParser& args_parse::ArgsParser::operator<<(std::shared_ptr mode) { + this->match_modes.append(mode); + return *this; +} + +std::shared_ptr ArgsParser::parse(int argc, char* argv[]) { // 聚合参数数组 QList args_list; for (int idx = 0; idx < argc; idx++) { @@ -171,8 +216,8 @@ tuple>> ArgsParser::parse(int argc, char* argv[ // 枚举模式匹配 for (auto& minst : this->match_modes) { if (minst->parse(args_list, 0, 0)) - return tuple>>(minst->modeCode(), minst->result()); + return minst; } - return tuple>>(0, QList>()); + return std::shared_ptr(); } diff --git a/ArgsParser/argsparser.h b/ArgsParser/argsparser.h index 3b72ec6..ab37883 100644 --- a/ArgsParser/argsparser.h +++ b/ArgsParser/argsparser.h @@ -69,13 +69,13 @@ namespace args_parse { QString value() const override; }; - class ARGSPARSER_EXPORT __FloatArgvImpl : public __ArgvPackImpls { + class ARGSPARSER_EXPORT __FloatArgvImpls : public __ArgvPackImpls { private: QString key_name; bool optional_value; public: - explicit __FloatArgvImpl(const QString& key, const QString& means, bool optional); + explicit __FloatArgvImpls(const QString& key, const QString& means, bool optional); QString bindKey() const; virtual bool optional() const; @@ -85,7 +85,7 @@ namespace args_parse { * @brief 命令行key-value解析匹配模式. * --key value */ - class ARGSPARSER_EXPORT FloatKeyValue : public __FloatArgvImpl { + class ARGSPARSER_EXPORT FloatKeyValue : public __FloatArgvImpls { public: /** * 浮动key-value解析单元. @@ -106,7 +106,7 @@ namespace args_parse { * @brief 命令行key解析匹配模式. * --key */ - class ARGSPARSER_EXPORT FloatOption : public __FloatArgvImpl { + class ARGSPARSER_EXPORT FloatOption : public __FloatArgvImpls { public: /** * 浮动option解析单元. @@ -142,26 +142,55 @@ namespace args_parse { class ARGSPARSER_EXPORT MatchMode { private: - QList> args_mode; int code_store; + QString _means_explain; + + QList> args_mode; public: - explicit MatchMode(const QList> mode, int mode_code); + explicit MatchMode(int mode_code, const QString &explain); /** * @brief 获取模式代码 * @return 模式代码 */ int modeCode()const; + /** - * @brief 获取模式匹配结果 - * @return 模式匹配结果 - */ - QList> result() const; + * 获取用例字符串. + * + * \return + */ + QString usageString() const; + + /** + * 返回模式解析字符串. + * + * \return + */ + QString explanString() const; + + /** + * 添加参数解析单元. + * + * \param unit + * \return + */ + MatchMode& operator<<(std::shared_ptr unit); + /** * @brief 解析匹配参数 */ bool parse(const QList& args, int argv_index, int parse_index); + + /** + * 获取解析单元. + * + * \param key + * \return + */ + std::shared_ptr getUnitViaKey(const QString& key); + std::shared_ptr getUnitViaPos(int pos); }; class ARGSPARSER_EXPORT ArgsParser { @@ -169,9 +198,11 @@ namespace args_parse { QList> match_modes; public: - void loadMode(int mode_code, const QList> &args_model); + QString helpDoc() const; - std::tuple>> parse(int argc, char* argv[]); + ArgsParser& operator<<(std::shared_ptr mode); + + std::shared_ptr parse(int argc, char* argv[]); }; } \ No newline at end of file diff --git a/WsNovelParser/main.cpp b/WsNovelParser/main.cpp index ef18cbb..e6b02e1 100644 --- a/WsNovelParser/main.cpp +++ b/WsNovelParser/main.cpp @@ -17,6 +17,8 @@ #include "htmlprint.h" using namespace example_novel; +using namespace std; +using namespace args_parse; /* * nsc --help @@ -28,99 +30,101 @@ using namespace example_novel; int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); - args_parse::ArgsParser args_parser; - QList> args_mode; - args_mode << std::make_shared(u8"nsc", u8"程序名称"); - args_mode << std::make_shared(u8"--help", u8"帮助"); - args_parser.loadMode(0x000Au, args_mode); + ArgsParser args_parser; + auto help_mode = make_shared(0x000Au, u8"打印帮助信息"); + args_parser << help_mode; + *help_mode << make_shared(u8"nsc", u8"程序名称") + << make_shared(u8"help", u8"帮助"); - args_mode.clear(); - args_mode << std::make_shared(u8"nsc", u8"程序名称"); - args_mode << std::make_shared(u8"--path", u8"源代码目录"); - args_mode << std::make_shared(u8"--dest", u8"生成目录"); - args_mode << std::make_shared(u8"--html", u8"生成html文件格式取代AST", true); - args_parser.loadMode(0x000Bu, args_mode); + auto build_mode = make_shared(0x000Bu, u8"执行故事线编译任务"); + args_parser << build_mode; + *build_mode << make_shared(u8"nsc", u8"程序名称") + << make_shared(u8"path", u8"指定源代码目录") + << make_shared(u8"dest", u8"指定生成目录") + << make_shared(u8"html", u8"生成html文件格式取代AST", true); - auto parse_result = args_parser.parse(argc, argv); - switch (std::get<0>(parse_result)) { - case 0xBu: { - auto args = std::get<1>(parse_result); - auto src_dir = std::dynamic_pointer_cast(args_mode[1]); - auto dst_dir = std::dynamic_pointer_cast(args_mode[2]); - auto html_opt = std::dynamic_pointer_cast(args_mode[3]); + auto p_result = args_parser.parse(argc, argv); + if (!p_result) { + qDebug().noquote() << args_parser.helpDoc(); + } + else { + switch (p_result->modeCode()) { + case 0xAu: + default: + qDebug().noquote() << args_parser.helpDoc(); + break; + case 0xBu: + { + auto src_dir = dynamic_pointer_cast(p_result->getUnitViaKey(u8"path")); + auto dst_dir = dynamic_pointer_cast(p_result->getUnitViaKey(u8"dest")); + auto html_opt = dynamic_pointer_cast(p_result->getUnitViaKey(u8"html")); - auto source_dir = QDir(src_dir->value()); - if (!source_dir.exists()) { - std::cout << "%编译指定的源代码目录不存在!" << std::endl; - exit(0); - } - auto destination_dir = QDir::current(); - auto target_output = dst_dir->value(); - if (!target_output.isEmpty() && QDir(target_output).exists()) { - destination_dir = QDir(target_output); - } - else { - std::cout << "%编译指定的生成目录不存在,重置为:" << destination_dir.absolutePath().toLocal8Bit().data() << std::endl; - } - - auto files = source_dir.entryInfoList(QStringList() << "*.story"); - std::shared_ptr access_ptr = nullptr; - if (files.size()) { - try { - auto parser = std::make_shared(); - auto docs = parser->parse(files); - - auto errors_list = parser->parserContext()->errors(); - if (errors_list.size()) { - for (auto& err : errors_list) { - qDebug().noquote() << err; + auto source_dir = QDir(src_dir->value()); + if (!source_dir.exists()) { + cout << "%编译指定的源代码目录不存在!" << endl; + exit(0); + } + auto destination_dir = QDir::current(); + auto target_output = dst_dir->value(); + if (!target_output.isEmpty() && QDir(target_output).exists()) { + destination_dir = QDir(target_output); + } + else { + cout << "%编译指定的生成目录不存在,重置为:" << destination_dir.absolutePath().toLocal8Bit().data() << endl; } - exit(0); - } - access_ptr = parser->validsApply(docs); - } - catch (lib_syntax::SyntaxException* e) { - qDebug().noquote() << e->message(); - delete e; - exit(0); - } - catch (lib_parse::CheckException* e) { - qDebug().noquote() << e->message(); - delete e; - exit(0); - } - } - if (html_opt->value().toInt() == 1 && access_ptr) { - printer::tools_printer tool; - tool.plain_html_output(access_ptr, destination_dir); + auto files = source_dir.entryInfoList(QStringList() << "*.story"); + shared_ptr access_ptr = nullptr; + if (files.size()) { + try { + auto parser = make_shared(); + auto docs = parser->parse(files); + + auto errors_list = parser->parserContext()->errors(); + if (errors_list.size()) { + for (auto& err : errors_list) { + qDebug().noquote() << err; + } + exit(0); + } + access_ptr = parser->validsApply(docs); + } + catch (lib_syntax::SyntaxException* e) { + qDebug().noquote() << e->message(); + delete e; + exit(0); + } + catch (lib_parse::CheckException* e) { + qDebug().noquote() << e->message(); + delete e; + exit(0); + } + } + + if (html_opt->value().toInt() == 1 && access_ptr) { + printer::tools_printer tool; + tool.plain_html_output(access_ptr, destination_dir); + } + else if (access_ptr) { + QTime time_stamp = QTime::currentTime(); + lib_parse::VisitorControl control; + auto visitor = make_shared(source_dir); + control.visitWith(access_ptr, visitor);; + auto dom_result = visitor->content(); + QFile file(destination_dir.absoluteFilePath(u8"storyline.xast")); + if (file.open(QIODevice::Text | QIODevice::WriteOnly)) { + QTextStream tout(&file); + tout.setCodec("UTF-8"); + tout << dom_result; + tout.flush(); + } + auto current_stamp = QTime::currentTime(); + qDebug().noquote() << QString(u8"%AST构建消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)); + qDebug().noquote() << QString(u8"%编译成功:%1。").arg(QFileInfo(file).absoluteFilePath()); + } + }break; } - else if (access_ptr) { - QTime time_stamp = QTime::currentTime(); - lib_parse::VisitorControl control; - auto visitor = std::make_shared(source_dir); - control.visitWith(access_ptr, visitor);; - auto dom_result = visitor->content(); - QFile file(destination_dir.absoluteFilePath(u8"storyline.xast")); - if (file.open(QIODevice::Text | QIODevice::WriteOnly)) { - QTextStream tout(&file); - tout.setCodec("UTF-8"); - tout << dom_result; - tout.flush(); - } - auto current_stamp = QTime::currentTime(); - qDebug().noquote() << QString(u8"%AST构建消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)); - qDebug().noquote() << QString(u8"%编译成功:%1。").arg(QFileInfo(file).absoluteFilePath()); - } - }break; - case 0xAu: - default: { - std::cout << "nsc(WsNovelStoryCompiler:故事线编译器)" << std::endl; - std::cout << "版本:V1.0.0" << std::endl; - std::cout << "nsc --path path-to-dir --dest path-to-output [--html]" << std::endl; - std::cout << "nsc --help" << std::endl; - }break; } //return a.exec(); return 0;