diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..266ee42 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,165 @@ +# Visual Studio 生成了具有 C++ 设置的 .editorconfig 文件。 +root = true + +[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] + +# Visual C++ 代码样式设置 + +cpp_generate_documentation_comments = xml + +# Visual C++ 格式设置 + +cpp_indent_braces = false +cpp_indent_multi_line_relative_to = statement_begin +cpp_indent_within_parentheses = indent +cpp_indent_preserve_within_parentheses = true +cpp_indent_case_contents = true +cpp_indent_case_labels = true +cpp_indent_case_contents_when_block = true +cpp_indent_lambda_braces_when_parameter = true +cpp_indent_goto_labels = leftmost_column +cpp_indent_preprocessor = leftmost_column +cpp_indent_access_specifiers = false +cpp_indent_namespace_contents = true +cpp_indent_preserve_comments = false +cpp_new_line_before_open_brace_namespace = same_line +cpp_new_line_before_open_brace_type = same_line +cpp_new_line_before_open_brace_function = same_line +cpp_new_line_before_open_brace_block = same_line +cpp_new_line_before_open_brace_lambda = same_line +cpp_new_line_scope_braces_on_separate_lines = true +cpp_new_line_close_brace_same_line_empty_type = true +cpp_new_line_close_brace_same_line_empty_function = true +cpp_new_line_before_catch = true +cpp_new_line_before_else = true +cpp_new_line_before_while_in_do_while = false +cpp_space_before_function_open_parenthesis = remove +cpp_space_within_parameter_list_parentheses = false +cpp_space_between_empty_parameter_list_parentheses = false +cpp_space_after_keywords_in_control_flow_statements = true +cpp_space_within_control_flow_statement_parentheses = false +cpp_space_before_lambda_open_parenthesis = false +cpp_space_within_cast_parentheses = false +cpp_space_after_cast_close_parenthesis = true +cpp_space_within_expression_parentheses = false +cpp_space_before_block_open_brace = true +cpp_space_between_empty_braces = true +cpp_space_before_initializer_list_open_brace = false +cpp_space_within_initializer_list_braces = true +cpp_space_preserve_in_initializer_list = true +cpp_space_before_open_square_bracket = false +cpp_space_within_square_brackets = false +cpp_space_before_empty_square_brackets = false +cpp_space_between_empty_square_brackets = false +cpp_space_group_square_brackets = true +cpp_space_within_lambda_brackets = false +cpp_space_between_empty_lambda_brackets = false +cpp_space_before_comma = false +cpp_space_after_comma = true +cpp_space_remove_around_member_operators = true +cpp_space_before_inheritance_colon = true +cpp_space_before_constructor_colon = true +cpp_space_remove_before_semicolon = true +cpp_space_after_semicolon = true +cpp_space_remove_around_unary_operator = true +cpp_space_around_binary_operator = insert +cpp_space_around_assignment_operator = insert +cpp_space_pointer_reference_alignment = left +cpp_space_around_ternary_operator = insert +cpp_use_unreal_engine_macro_formatting = true +cpp_wrap_preserve_blocks = never + +# Visual C++ 包含清理设置 + +cpp_include_cleanup_add_missing_error_tag_type = suggestion +cpp_include_cleanup_remove_unused_error_tag_type = dimmed +cpp_include_cleanup_optimize_unused_error_tag_type = suggestion +cpp_include_cleanup_sort_after_edits = false +cpp_sort_includes_error_tag_type = none +cpp_sort_includes_priority_case_sensitive = false +cpp_sort_includes_priority_style = quoted +cpp_includes_style = default +cpp_includes_use_forward_slash = true + +[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] + +# Visual C++ 代码样式设置 + +cpp_generate_documentation_comments = xml + +# Visual C++ 格式设置 + +cpp_indent_braces = false +cpp_indent_multi_line_relative_to = statement_begin +cpp_indent_within_parentheses = indent +cpp_indent_preserve_within_parentheses = true +cpp_indent_case_contents = true +cpp_indent_case_labels = true +cpp_indent_case_contents_when_block = true +cpp_indent_lambda_braces_when_parameter = true +cpp_indent_goto_labels = leftmost_column +cpp_indent_preprocessor = leftmost_column +cpp_indent_access_specifiers = false +cpp_indent_namespace_contents = true +cpp_indent_preserve_comments = false +cpp_new_line_before_open_brace_namespace = same_line +cpp_new_line_before_open_brace_type = same_line +cpp_new_line_before_open_brace_function = same_line +cpp_new_line_before_open_brace_block = same_line +cpp_new_line_before_open_brace_lambda = same_line +cpp_new_line_scope_braces_on_separate_lines = true +cpp_new_line_close_brace_same_line_empty_type = true +cpp_new_line_close_brace_same_line_empty_function = true +cpp_new_line_before_catch = true +cpp_new_line_before_else = true +cpp_new_line_before_while_in_do_while = false +cpp_space_before_function_open_parenthesis = remove +cpp_space_within_parameter_list_parentheses = false +cpp_space_between_empty_parameter_list_parentheses = false +cpp_space_after_keywords_in_control_flow_statements = true +cpp_space_within_control_flow_statement_parentheses = false +cpp_space_before_lambda_open_parenthesis = false +cpp_space_within_cast_parentheses = false +cpp_space_after_cast_close_parenthesis = true +cpp_space_within_expression_parentheses = false +cpp_space_before_block_open_brace = true +cpp_space_between_empty_braces = true +cpp_space_before_initializer_list_open_brace = false +cpp_space_within_initializer_list_braces = true +cpp_space_preserve_in_initializer_list = true +cpp_space_before_open_square_bracket = false +cpp_space_within_square_brackets = false +cpp_space_before_empty_square_brackets = false +cpp_space_between_empty_square_brackets = false +cpp_space_group_square_brackets = true +cpp_space_within_lambda_brackets = false +cpp_space_between_empty_lambda_brackets = false +cpp_space_before_comma = false +cpp_space_after_comma = true +cpp_space_remove_around_member_operators = true +cpp_space_before_inheritance_colon = true +cpp_space_before_constructor_colon = true +cpp_space_remove_before_semicolon = true +cpp_space_after_semicolon = true +cpp_space_remove_around_unary_operator = true +cpp_space_around_binary_operator = insert +cpp_space_around_assignment_operator = insert +cpp_space_pointer_reference_alignment = left +cpp_space_around_ternary_operator = insert +cpp_use_unreal_engine_macro_formatting = true +cpp_wrap_preserve_blocks = never + +# Visual C++ 包含清理设置 + +cpp_include_cleanup_add_missing_error_tag_type = suggestion +cpp_include_cleanup_remove_unused_error_tag_type = dimmed +cpp_include_cleanup_optimize_unused_error_tag_type = suggestion +cpp_include_cleanup_sort_after_edits = false +cpp_sort_includes_error_tag_type = none +cpp_sort_includes_priority_case_sensitive = false +cpp_sort_includes_priority_style = quoted +cpp_includes_style = default +cpp_includes_use_forward_slash = true + + +charset = utf-8 \ No newline at end of file diff --git a/libParse/libParse.vcxproj b/libParse/libParse.vcxproj index f2932de..b57f0db 100644 --- a/libParse/libParse.vcxproj +++ b/libParse/libParse.vcxproj @@ -73,7 +73,8 @@ libWords.lib;libSyntax.lib;%(AdditionalDependencies);$(Qt_LIBS_) - Default + stdcpp20 + /utf-8 %(AdditionalOptions) diff --git a/libParse/libparse.cpp b/libParse/libparse.cpp index 89a83a0..b2cf0f8 100644 --- a/libParse/libparse.cpp +++ b/libParse/libparse.cpp @@ -16,12 +16,12 @@ std::shared_ptr Analyzer::validCheckWith(std::shared_ptrvalidCheck(root); auto current_stamp = QTime::currentTime(); - qDebug().noquote() << QString(u8"%У%2 ʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)).arg(v->name()); + qDebug().noquote() << QString("%校验器:%2 消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp)).arg(v->name()); } return root; } -bool VisitorControl::visitWith(std::shared_ptr syntax_elm, std::shared_ptr visitor) { +bool VisitEntry::visitWith(std::shared_ptr syntax_elm, std::shared_ptr visitor) { switch (visitor->mode()) { case VisitMode::FirstParent: { if (visitor->visit(syntax_elm)) { diff --git a/libParse/libparse.h b/libParse/libparse.h index 3b68fdb..0b5a4f2 100644 --- a/libParse/libparse.h +++ b/libParse/libparse.h @@ -3,10 +3,11 @@ #include "libparse_global.h" #include #include +#include namespace lib_parse { /** - * @brief 쳣 + * @brief 检查机制异常 */ class LIBPARSE_EXPORT CheckException { private: @@ -21,7 +22,7 @@ namespace lib_parse { /** - * @brief Уṩ + * @brief 校验机制提供类型 */ class CheckProvider { public: @@ -31,42 +32,62 @@ namespace lib_parse { /** - * @brief ӿ + * @brief 分析器对外接口 */ class LIBPARSE_EXPORT Analyzer { private: QList> check_providers; public: + /** + * @brief 构建AST分析器. + * + * \param providers + */ Analyzer(const QList>& providers); + /** + * @brief 使用本分析器分析指定Ast. + * + * \param root + * \return + */ std::shared_ptr validCheckWith(std::shared_ptr root) const; }; + /** + * @brief 遍历模式. + */ enum class VisitMode { - FirstParent, // - LastParent, // + FirstParent, // 先序遍历 + LastParent, // 后序遍历 }; + /** + * @brief Ast树遍历模式. + */ class TreeVisitor { public: /** - * ȡıģʽ. + * 获取访问器的遍历模式. * * \return */ virtual VisitMode mode() const = 0; /** - * ﷨ִнڵ. + * 对语法树执行节点遍历. * - * \param syntax_element ǰʽڵ - * \return Ƿִб + * \param syntax_element 当前访问节点 + * \return 是否继续执行遍历 */ virtual bool visit(std::shared_ptr syntax_element) = 0; }; - class LIBPARSE_EXPORT VisitorControl { + /** + * @brief Ast遍历控制接口. + */ + class LIBPARSE_EXPORT VisitEntry { public: bool visitWith(std::shared_ptr syntax_elm, std::shared_ptr visitor); }; diff --git a/libParse/parse_novel.cpp b/libParse/parse_novel.cpp index 4f2d716..bd2e007 100644 --- a/libParse/parse_novel.cpp +++ b/libParse/parse_novel.cpp @@ -11,14 +11,41 @@ using namespace ast_gen; using namespace lib_syntax; using namespace example_novel; -void FragmentExistsCheck::exists_check(std::shared_ptr root, - std::shared_ptr target) const { - if (target->element()->typeMark() == (int)NovelNode::PointRefers) { + +void ElementsCache::clearCache() { + node_cache.clear(); +} + +std::shared_ptr ElementsCache::appendToCache(std::shared_ptr named_node) { + auto mixed_key = QString("%1<%2>").arg(named_node->signature()).arg(named_node->typeMark()); + if (node_cache.contains(mixed_key)) + return node_cache[mixed_key]; + node_cache[mixed_key] = named_node; + return nullptr; +} + +std::shared_ptr ElementsCache::getNamedNodeBy(int paramType, const QString& signature) const { + auto mixed_key = QString("%1<%2>").arg(signature).arg(paramType); + if (!node_cache.contains(mixed_key)) + return nullptr; + return node_cache[mixed_key]; +} + +void example_novel::FragmentExistsCheck::nodes_regist(std::shared_ptr cache, std::shared_ptr target) { + if (!target->element()->isAnonymous()) + cache->appendToCache(target->element()); + + for (auto item : target->children()) + nodes_regist(cache, item); +} + +void FragmentExistsCheck::exists_check(std::shared_ptr root, std::shared_ptr target) const { + if (target->element()->typeMark() == (int) NovelNode::PointRefers) { auto refer = std::dynamic_pointer_cast(target->element()); - auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer(); - if (!root->getNamedNodeBy((int)NovelNode::PointDefines, signature)) - throw new SyntaxException(QString(u8"CheckError[0x0005]ϵͳвָǩĽڵ㣺%1{%3:(%4)}") - .arg(signature).arg((int)NovelNode::PointDefines).arg(refer->signature()).arg(refer->filePath())); + auto signature = refer->storyRefer() + "&" + refer->sliceRefer() + "&" + refer->pointRefer(); + if (!root->getNamedNodeBy((int) NovelNode::PointDefines, signature)) + throw new SyntaxException(QString("CheckError[0x0005]系统中不包含指定签名的节点:%1{%3:(%4)}") + .arg(signature).arg((int) NovelNode::PointDefines).arg(refer->signature()).arg(refer->filePath())); } for (auto& xit : target->children()) { @@ -27,15 +54,16 @@ void FragmentExistsCheck::exists_check(std::shared_ptr root } void FragmentExistsCheck::validCheck(std::shared_ptr root) const { - this->exists_check(std::dynamic_pointer_cast(root->element()), root); + const_cast(this)->nodes_regist(this->_nodes_cache, root); + this->exists_check(this->_nodes_cache, root); } QString FragmentExistsCheck::name() const { - return u8"ЧԼ"; + return "情节引用有效性检查器"; } -QList> FragmentGraphCheck::refers_cycle_check( - std::shared_ptr item, QList> prevs) const { +QList> FragmentGraphCheck::refers_cycle_check( + std::shared_ptr item, QList> prevs) const { if (prevs.contains(item)) { return prevs << item; } @@ -50,25 +78,23 @@ QList> FragmentGraphCheck::refers_cycle_che } } - return QList>(); + return QList>(); } -void FragmentGraphCheck::setElement(std::shared_ptr inst) -{ +void FragmentGraphCheck::setElement(std::shared_ptr inst) { elements_store[inst->nodePeer()->signature()] = inst; } -QList> FragmentGraphCheck::fragmentsSequence() const { +QList> FragmentGraphCheck::fragmentsSequence() const { return fragments_sort_list; } -std::shared_ptr FragmentGraphCheck::getElement(const QString& signature) const -{ +std::shared_ptr FragmentGraphCheck::getElement(const QString& signature) const { return elements_store[signature]; } -QList> FragmentGraphCheck::getHangoutNodes() { - QList> values; +QList> FragmentGraphCheck::getHangoutNodes() { + QList> values; for (auto node_item : elements_store) { if (!node_item->inDegree()) @@ -83,7 +109,7 @@ QList> FragmentGraphCheck::getHangoutNodes( return values; } -bool FragmentGraphCheck::nodeDismantle(std::shared_ptr inst) { +bool FragmentGraphCheck::nodeDismantle(std::shared_ptr inst) { bool flag = false; for (auto item : inst->nextList()) { @@ -94,15 +120,15 @@ bool FragmentGraphCheck::nodeDismantle(std::shared_ptr inst return flag; } -void FragmentGraphCheck::validCheck(std::shared_ptr root) const -{ +void FragmentGraphCheck::validCheck(std::shared_ptr root) const { const_cast(this)->fragments_sort_list.clear(); + auto self = std::const_pointer_cast(this->shared_from_this()); std::function>(std::shared_ptr)> story_peak = [&](std::shared_ptr root)->QList> { QList> return_temp; - auto type_mark = (NovelNode)root->element()->typeMark(); + auto type_mark = (NovelNode) root->element()->typeMark(); if (type_mark == NovelNode::StoryDefine) { return_temp << root; } @@ -112,67 +138,90 @@ void FragmentGraphCheck::validCheck(std::shared_ptr root) c } return return_temp; - }; + }; - auto self = std::const_pointer_cast(this->shared_from_this()); + std::function>(std::shared_ptr)> + points_extract = [](std::shared_ptr story) { + QList> return_temp; - // ȡй + auto story_children = story->children(); + QList> slice_list; + std::copy_if(story_children.begin(), story_children.end(), + std::back_inserter(slice_list), [](std::shared_ptr ins) { + return ins->element()->typeMark() == (int) NovelNode::FragmentSlice; + }); + + decltype(slice_list) slice_children; + for (auto slice : slice_list) + slice_children.append(slice->children()); + + std::copy_if(slice_children.begin(), slice_children.end(), + std::back_inserter(return_temp), [](std::shared_ptr ins) { + return ins->element()->typeMark() == (int) NovelNode::PointDefines && + ins->element()->typeMark() == (int) NovelNode::PointRefers; + }); + + return return_temp; + }; + + + // 获取所有故事线 auto all_story = story_peak(root); - // עͼڵ + // 注册图节点 for (auto story : all_story) { - auto fragment_items = story->children(); + auto point_items = points_extract(story); - // ڽڵб - for (auto frag_primitive : fragment_items) { - switch (frag_primitive->element()->typeMark()) { - case (int)NovelNode::PointDefines: { - auto target_node = std::dynamic_pointer_cast(frag_primitive->element()); - auto finst = std::make_shared(target_node); - - self->setElement(finst); - }break; - default: break; + // 构建情节节点列表 + for (auto point_primitive : point_items) { + switch (point_primitive->element()->typeMark()) { + case (int) NovelNode::PointDefines: + { + auto target_node = std::dynamic_pointer_cast(point_primitive->element()); + auto finst = std::make_shared(target_node); + self->setElement(finst); + }break; + default: break; } } } - // ͼ + // 构建图连接 for (auto story : all_story) { - auto fragment_items = story->children(); + auto point_items = points_extract(story); - // ˻ȡڽڵ - for (auto idx = 0; idx < fragment_items.size(); idx++) { - auto fragment_inst = fragment_items[idx]; - switch (fragment_inst->element()->typeMark()) - { - case (int)NovelNode::PointDefines: - case (int)NovelNode::PointRefers: - break; - default: - fragment_items.removeAt(idx); - idx--; - break; + // 过滤获取情节节点 + for (auto idx = 0; idx < point_items.size(); idx++) { + auto point_inst = point_items[idx]; + switch (point_inst->element()->typeMark()) { + case (int) NovelNode::PointDefines: + case (int) NovelNode::PointRefers: + break; + default: + point_items.removeAt(idx--); + break; } } auto get_name = [](std::shared_ptr node)->QString { switch (node->element()->typeMark()) { - case (int)NovelNode::PointDefines: { - auto def_node = std::dynamic_pointer_cast(node->element()); - return def_node->signature(); - }break; - case (int)NovelNode::PointRefers: { - auto ref_node = std::dynamic_pointer_cast(node->element()); - return ref_node->referSignature(); - }break; + case (int) NovelNode::PointDefines: + { + auto def_node = std::dynamic_pointer_cast(node->element()); + return def_node->signature(); + }break; + case (int) NovelNode::PointRefers: + { + auto ref_node = std::dynamic_pointer_cast(node->element()); + return ref_node->referSignature(); + }break; } return QString(); - }; + }; - // ͼṹ - for (auto fidx = 1; fidx < fragment_items.size(); fidx++) { - auto tail_name = get_name(fragment_items[fidx - 1]); - auto head_name = get_name(fragment_items[fidx]); + // 构建完整图结构 + for (auto fidx = 1; fidx < point_items.size(); fidx++) { + auto tail_name = get_name(point_items[fidx - 1]); + auto head_name = get_name(point_items[fidx]); auto tail_helper = getElement(tail_name); auto head_helper = getElement(head_name); @@ -182,7 +231,7 @@ void FragmentGraphCheck::validCheck(std::shared_ptr root) c } } - // ȡ + // 获取拓扑排序序列 auto values = self->getHangoutNodes(); for (auto idx = 0; idx < values.size(); ++idx) { auto target = values[idx]; @@ -192,14 +241,14 @@ void FragmentGraphCheck::validCheck(std::shared_ptr root) c values.append(x_values); } - // ϲӦв + // 理论上不应该有残余 if (elements_store.size()) { for (auto node : elements_store.values()) { auto cycle_link = refers_cycle_check(node); - QString error_msg = u8"CheckError[0x0006]ôڻνṹ\n"; + QString error_msg = "CheckError[0x0006]情节引用存在环形结构:\n"; for (auto n : cycle_link) { - error_msg += QString(u8"%1->").arg(n->nodePeer()->signature()); + error_msg += QString("%1->").arg(n->nodePeer()->signature()); } if (cycle_link.size()) @@ -212,27 +261,25 @@ void FragmentGraphCheck::validCheck(std::shared_ptr root) c } QString FragmentGraphCheck::name() const { - return u8"ЧԼ"; + return "情节网络有效性检查器"; } -FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr node) : node_peer(node) {} +PointGraphHelper::PointGraphHelper(std::shared_ptr node) : node_peer(node) { +} -std::shared_ptr FragmentGraphHelper::nodePeer() const -{ +std::shared_ptr PointGraphHelper::nodePeer() const { return this->node_peer; } -void FragmentGraphHelper::appendNext(std::shared_ptr node) { +void PointGraphHelper::appendNext(std::shared_ptr node) { this->next_nodes.append(node); } -QList> FragmentGraphHelper::nextList() const -{ +QList> PointGraphHelper::nextList() const { return next_nodes; } -uint& FragmentGraphHelper::inDegree() -{ +uint& PointGraphHelper::inDegree() { return this->indegree; } @@ -240,52 +287,51 @@ QList> StoryOrderCheck::valid_docs_peak(std QList> values; auto type_code = pnode->element()->typeMark(); - switch ((NovelNode)type_code) { - case NovelNode::GlobalElement: { - auto children = pnode->children(); - for (auto& cinst : children) { - values.append(valid_docs_peak(cinst)); - } - }break; + switch ((NovelNode) type_code) { + case NovelNode::GlobalElement: + { + auto children = pnode->children(); + for (auto& cinst : children) { + values.append(valid_docs_peak(cinst)); + } + }break; - case NovelNode::Document: { - auto storys_collection = pnode->children(); + case NovelNode::Document: + { + auto elms_set = pnode->children(); - bool story_exists = false; - for (auto& syntax_elm : storys_collection) { - if (syntax_elm->element()->typeMark() == (int)NovelNode::StoryDefine) { - story_exists = true; - break; - } - } + decltype(elms_set) story_set; + std::copy_if(elms_set.begin(), elms_set.end(), + std::back_inserter(story_set), [](std::shared_ptr e) { + return e->element()->typeMark() == (int) NovelNode::StoryDefine; + }); - if (story_exists) { - auto first_elm = storys_collection.at(0); - values.append(pnode); + if (story_set.size()) { + values.append(pnode); - if (first_elm->element()->typeMark() != (int)NovelNode::RankDeclaration) - throw new CheckException(QString(u8"CheckError[0x0007]й½ڵĵڵһָ%1").arg(pnode->element()->path())); - } - }break; + auto first_elm = elms_set.at(0); + if (first_elm->element()->typeMark() != (int) NovelNode::RankDeclaration) + throw new CheckException(QString("CheckError[0x0007]具有故事节点的文档必须在第一行指定排序(%1)").arg(pnode->element()->path())); + } + }break; - default: - break; + default: + break; } return values; } -QString StoryOrderCheck::name() const -{ - return u8"ЧԼ"; +QString StoryOrderCheck::name() const { + return "故事序列有效性检查器"; } -void StoryOrderCheck::validCheck(std::shared_ptr root) const -{ +void StoryOrderCheck::validCheck(std::shared_ptr root) const { const_cast(this)->sort_index = 1; auto story_docs = valid_docs_peak(root); - std::sort(story_docs.begin(), story_docs.end(), [](std::shared_ptr adoc, std::shared_ptr bdoc) { + std::sort(story_docs.begin(), story_docs.end(), + [](std::shared_ptr adoc, std::shared_ptr bdoc) { auto elm_xa = std::dynamic_pointer_cast(adoc->children().first()->element()); auto elm_xb = std::dynamic_pointer_cast(bdoc->children().first()->element()); return elm_xa->rankNumber() < elm_xb->rankNumber(); @@ -295,22 +341,23 @@ void StoryOrderCheck::validCheck(std::shared_ptr root) cons int page_rank = 0; for (auto& item : story_docs) { auto elm_xa = std::dynamic_pointer_cast(item->children().first()->element()); - if (page_rank >= elm_xa->rankNumber()) { - throw new CheckException(QString(u8"CheckError[0x0009]ĵֱ0ͬĵظ{%1}").arg(elm_xa->path())); - } + if (page_rank >= elm_xa->rankNumber()) + throw new CheckException(QString("CheckError[0x0009]文档排序声明数字必须大于0,不同文档的排序不能重复{%1}").arg(elm_xa->path())); + + page_rank = elm_xa->rankNumber(); } - // ½ڵ + // 故事节点排序 auto story_node_sort = [](std::shared_ptr doc_node, int start_index) -> int { auto childs = doc_node->children(); for (auto& inst : childs) { - if (inst->element()->typeMark() == (int)NovelNode::StoryDefine) { + if (inst->element()->typeMark() == (int) NovelNode::StoryDefine) { auto cast_inst = std::dynamic_pointer_cast(inst->element()); std::const_pointer_cast(cast_inst)->setSort(start_index++); } } return start_index; - }; + }; int ranks_number = 1; for (auto& story : story_docs) diff --git a/libParse/parse_novel.h b/libParse/parse_novel.h index 39fa653..b831063 100644 --- a/libParse/parse_novel.h +++ b/libParse/parse_novel.h @@ -2,36 +2,67 @@ #include "libparse.h" #include +#include +#include +#include namespace example_novel { - class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider { + class PointGraphHelper; + + /** + * @brief 根元素定义 + */ + class LIBPARSE_EXPORT ElementsCache { private: - void exists_check(std::shared_ptr root, std::shared_ptr target) const; + QHash> node_cache; public: - // ͨ CheckProvider ̳ - virtual void validCheck(std::shared_ptr root) const override; - virtual QString name() const override; + virtual void clearCache(); + virtual std::shared_ptr appendToCache(std::shared_ptr named_node); + /** + * @brief 通过节点签名获取定义节点 + * @param signature 完全签名 + * @return + * @throws 没有指定节点抛出异常 + */ + virtual std::shared_ptr getNamedNodeBy(int paramType, const QString& signature) const; }; - - class FragmentGraphHelper; - class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this, public lib_parse::CheckProvider { + /** + * @brief 剧情存在性校验器. + */ + class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider { private: - QHash> elements_store; - QList> fragments_sort_list; + std::shared_ptr _nodes_cache; + void nodes_regist(std::shared_ptr cache, std::shared_ptr target); - QList> refers_cycle_check( - std::shared_ptr item, QList> prevs = QList>()) const; + void exists_check(std::shared_ptr cache, std::shared_ptr target) const; public: - void setElement(std::shared_ptr inst); - std::shared_ptr getElement(const QString &signature) const; + // 通过 CheckProvider 继承 + virtual QString name() const override; + virtual void validCheck(std::shared_ptr root) const override; + }; - QList> getHangoutNodes(); - bool nodeDismantle(std::shared_ptr inst); + /** + * @brief 情节节点校验. + */ + class LIBPARSE_EXPORT FragmentGraphCheck : public lib_parse::CheckProvider, public std::enable_shared_from_this { + private: + QHash> elements_store; + QList> fragments_sort_list; - QList> fragmentsSequence() const; + QList> refers_cycle_check( + std::shared_ptr item, QList> prevs = QList>()) const; + + public: + void setElement(std::shared_ptr inst); + std::shared_ptr getElement(const QString &signature) const; + + QList> getHangoutNodes(); + bool nodeDismantle(std::shared_ptr inst); + + QList> fragmentsSequence() const; // CheckProvider interface public: @@ -39,29 +70,31 @@ namespace example_novel { virtual QString name() const override; }; - class FragmentGraphHelper : public std::enable_shared_from_this { + class PointGraphHelper : public std::enable_shared_from_this { private: std::shared_ptr node_peer; - QList> next_nodes; + QList> next_nodes; uint indegree = 0; public: - FragmentGraphHelper(std::shared_ptr node); + PointGraphHelper(std::shared_ptr node); std::shared_ptr nodePeer() const; - void appendNext(std::shared_ptr node); - QList> nextList() const; + void appendNext(std::shared_ptr node); + QList> nextList() const; uint& inDegree(); }; - + /** + * @brief 故事线排序校验. + */ class LIBPARSE_EXPORT StoryOrderCheck : public lib_parse::CheckProvider { private: uint sort_index = 1; /** - * ȡʵĵڵ. + * 获取合适的文档节点. * * \param pnode * \return @@ -69,7 +102,7 @@ namespace example_novel { QList> valid_docs_peak(std::shared_ptr pnode) const; public: - // ͨ CheckProvider ̳ + // 通过 CheckProvider 继承 QString name() const override; void validCheck(std::shared_ptr root) const override; }; diff --git a/libSyntax/ast_novel.cpp b/libSyntax/ast_novel.cpp index 72f9428..46b8c9e 100644 --- a/libSyntax/ast_novel.cpp +++ b/libSyntax/ast_novel.cpp @@ -205,64 +205,6 @@ NGlobalElement::NGlobalElement(const QString& root): ExprProgram(root) { } using namespace ast_gen; using namespace ast_basic; - -GlobalElement* GlobalElement::UniquePtr = nullptr; - -GlobalElement::GlobalElement(const QString& name) :names_store(name) { - UniquePtr = this; -} - -void GlobalElement::clearCache() { - node_cache.clear(); -} - -std::shared_ptr GlobalElement::appendToCache(std::shared_ptr named_node) { - auto mixed_key = QString("%1<%2>").arg(named_node->signature()).arg(named_node->typeMark()); - if (node_cache.contains(mixed_key)) - return node_cache[mixed_key]; - node_cache[mixed_key] = named_node; - return nullptr; -} - -std::shared_ptr GlobalElement::getNamedNodeBy(int paramType, const QString& signature) const { - auto mixed_key = QString("%1<%2>").arg(signature).arg(paramType); - if (!node_cache.contains(mixed_key)) - return nullptr; - return node_cache[mixed_key]; -} - -int GlobalElement::typeMark() const { - return 0; -} - -bool GlobalElement::isAnonymous() const { - return true; -} - -QString GlobalElement::signature() const { - return "::global"; -} - -QString GlobalElement::path() const { - return ""; -} - -std::weak_ptr GlobalElement::parent() const { - return std::weak_ptr(); -} - -void GlobalElement::setParent(std::shared_ptr inst) { } - -QList> GlobalElement::selfTokens() const { - return QList>(); -} - -std::shared_ptr GlobalElement::bindExpression() const { - return nullptr; -} - -void GlobalElement::addChild(std::shared_ptr citem) { } - ElementAccess::ElementAccess(std::shared_ptr point) { peers = point; } diff --git a/libSyntax/ast_novel.h b/libSyntax/ast_novel.h index b5b5d0c..267c046 100644 --- a/libSyntax/ast_novel.h +++ b/libSyntax/ast_novel.h @@ -99,42 +99,6 @@ namespace ast_gen { virtual std::shared_ptr token() const; }; - /** - * @brief 根元素定义 - */ - class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement { - private: - QString names_store; - QHash> node_cache; - - public: - static GlobalElement* UniquePtr; - GlobalElement(const QString& name); - - virtual void clearCache(); - virtual std::shared_ptr appendToCache(std::shared_ptr named_node); - /** - * @brief 通过节点签名获取定义节点 - * @param signature 完全签名 - * @return - * @throws 没有指定节点抛出异常 - */ - virtual std::shared_ptr getNamedNodeBy(int paramType, const QString& signature) const; - virtual void addChild(std::shared_ptr citem); - - // ParseElement interface - public: - virtual int typeMark() const override; - virtual bool isAnonymous() const override; - virtual QString signature() const override; - virtual QString path() const override; - virtual std::weak_ptr parent() const override; - virtual void setParent(std::shared_ptr inst) override; - virtual QList> selfTokens() const override; - - // 通过 SyntaxElement 继承 - virtual std::shared_ptr bindExpression() const override; - }; } namespace example_novel {