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 {