This commit is contained in:
codeboss 2025-02-15 20:25:51 +08:00
parent 40c9eef31f
commit 8c902fca46
8 changed files with 420 additions and 247 deletions

165
.editorconfig Normal file
View File

@ -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

View File

@ -73,7 +73,8 @@
<AdditionalDependencies>libWords.lib;libSyntax.lib;%(AdditionalDependencies);$(Qt_LIBS_)</AdditionalDependencies>
</Link>
<ClCompile>
<LanguageStandard>Default</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@ -16,12 +16,12 @@ std::shared_ptr<const ElementAccess> Analyzer::validCheckWith(std::shared_ptr<co
QTime time_stamp = QTime::currentTime();
v->validCheck(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<const ElementAccess> syntax_elm, std::shared_ptr<TreeVisitor> visitor) {
bool VisitEntry::visitWith(std::shared_ptr<const ElementAccess> syntax_elm, std::shared_ptr<TreeVisitor> visitor) {
switch (visitor->mode()) {
case VisitMode::FirstParent: {
if (visitor->visit(syntax_elm)) {

View File

@ -3,10 +3,11 @@
#include "libparse_global.h"
#include <ast_basic.h>
#include <ast_gen.h>
#include <ast_novel.h>
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<std::shared_ptr<const CheckProvider>> check_providers;
public:
/**
* @brief AST分析器.
*
* \param providers
*/
Analyzer(const QList<std::shared_ptr<const CheckProvider>>& providers);
/**
* @brief 使Ast.
*
* \param root
* \return
*/
std::shared_ptr<const ast_gen::ElementAccess> validCheckWith(std::shared_ptr<const ast_gen::ElementAccess> 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<const ast_gen::ElementAccess> syntax_element) = 0;
};
class LIBPARSE_EXPORT VisitorControl {
/**
* @brief Ast遍历控制接口.
*/
class LIBPARSE_EXPORT VisitEntry {
public:
bool visitWith(std::shared_ptr<const ast_gen::ElementAccess> syntax_elm, std::shared_ptr<TreeVisitor> visitor);
};

View File

@ -11,13 +11,40 @@ using namespace ast_gen;
using namespace lib_syntax;
using namespace example_novel;
void FragmentExistsCheck::exists_check(std::shared_ptr<const GlobalElement> root,
std::shared_ptr<const ElementAccess> target) const {
void ElementsCache::clearCache() {
node_cache.clear();
}
std::shared_ptr<const SyntaxElement> ElementsCache::appendToCache(std::shared_ptr<const SyntaxElement> 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<const SyntaxElement> 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<ElementsCache> cache, std::shared_ptr<const ast_gen::ElementAccess> 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<ElementsCache> root, std::shared_ptr<const ElementAccess> target) const {
if (target->element()->typeMark() == (int) NovelNode::PointRefers) {
auto refer = std::dynamic_pointer_cast<const PointRefers>(target->element());
auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer();
auto signature = refer->storyRefer() + "&" + refer->sliceRefer() + "&" + refer->pointRefer();
if (!root->getNamedNodeBy((int) NovelNode::PointDefines, signature))
throw new SyntaxException(QString(u8"CheckError[0x0005]系统中不包含指定签名的节点:%1<type%2>{%3:(%4)}")
throw new SyntaxException(QString("CheckError[0x0005]系统中不包含指定签名的节点:%1<type%2>{%3:(%4)}")
.arg(signature).arg((int) NovelNode::PointDefines).arg(refer->signature()).arg(refer->filePath()));
}
@ -27,15 +54,16 @@ void FragmentExistsCheck::exists_check(std::shared_ptr<const GlobalElement> root
}
void FragmentExistsCheck::validCheck(std::shared_ptr<const ElementAccess> root) const {
this->exists_check(std::dynamic_pointer_cast<const GlobalElement>(root->element()), root);
const_cast<FragmentExistsCheck*>(this)->nodes_regist(this->_nodes_cache, root);
this->exists_check(this->_nodes_cache, root);
}
QString FragmentExistsCheck::name() const {
return u8"情节引用有效性检查器";
return "情节引用有效性检查器";
}
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::refers_cycle_check(
std::shared_ptr<FragmentGraphHelper> item, QList<std::shared_ptr<FragmentGraphHelper>> prevs) const {
QList<std::shared_ptr<PointGraphHelper>> FragmentGraphCheck::refers_cycle_check(
std::shared_ptr<PointGraphHelper> item, QList<std::shared_ptr<PointGraphHelper>> prevs) const {
if (prevs.contains(item)) {
return prevs << item;
}
@ -50,25 +78,23 @@ QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::refers_cycle_che
}
}
return QList<std::shared_ptr<FragmentGraphHelper>>();
return QList<std::shared_ptr<PointGraphHelper>>();
}
void FragmentGraphCheck::setElement(std::shared_ptr<FragmentGraphHelper> inst)
{
void FragmentGraphCheck::setElement(std::shared_ptr<PointGraphHelper> inst) {
elements_store[inst->nodePeer()->signature()] = inst;
}
QList<std::shared_ptr<const FragmentGraphHelper>> FragmentGraphCheck::fragmentsSequence() const {
QList<std::shared_ptr<const PointGraphHelper>> FragmentGraphCheck::fragmentsSequence() const {
return fragments_sort_list;
}
std::shared_ptr<FragmentGraphHelper> FragmentGraphCheck::getElement(const QString& signature) const
{
std::shared_ptr<PointGraphHelper> FragmentGraphCheck::getElement(const QString& signature) const {
return elements_store[signature];
}
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::getHangoutNodes() {
QList<std::shared_ptr<FragmentGraphHelper>> values;
QList<std::shared_ptr<PointGraphHelper>> FragmentGraphCheck::getHangoutNodes() {
QList<std::shared_ptr<PointGraphHelper>> values;
for (auto node_item : elements_store) {
if (!node_item->inDegree())
@ -83,7 +109,7 @@ QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::getHangoutNodes(
return values;
}
bool FragmentGraphCheck::nodeDismantle(std::shared_ptr<FragmentGraphHelper> inst) {
bool FragmentGraphCheck::nodeDismantle(std::shared_ptr<PointGraphHelper> inst) {
bool flag = false;
for (auto item : inst->nextList()) {
@ -94,9 +120,9 @@ bool FragmentGraphCheck::nodeDismantle(std::shared_ptr<FragmentGraphHelper> inst
return flag;
}
void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) const
{
void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) const {
const_cast<FragmentGraphCheck*>(this)->fragments_sort_list.clear();
auto self = std::const_pointer_cast<FragmentGraphCheck>(this->shared_from_this());
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)> story_peak
= [&](std::shared_ptr<const ElementAccess> root)->QList<std::shared_ptr<const ElementAccess>> {
@ -114,21 +140,44 @@ void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) c
return return_temp;
};
auto self = std::const_pointer_cast<FragmentGraphCheck>(this->shared_from_this());
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)>
points_extract = [](std::shared_ptr<const ElementAccess> story) {
QList<std::shared_ptr<const ElementAccess>> return_temp;
// 获取所有故事线
auto story_children = story->children();
QList<std::shared_ptr<const ElementAccess>> slice_list;
std::copy_if(story_children.begin(), story_children.end(),
std::back_inserter(slice_list), [](std::shared_ptr<const ElementAccess> 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<const ElementAccess> 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();
// 构建情节节点列表
for (auto frag_primitive : fragment_items) {
switch (frag_primitive->element()->typeMark()) {
case (int)NovelNode::PointDefines: {
auto target_node = std::dynamic_pointer_cast<const PointDefines>(frag_primitive->element());
auto finst = std::make_shared<FragmentGraphHelper>(target_node);
auto point_items = points_extract(story);
// 构建情节节点列表
for (auto point_primitive : point_items) {
switch (point_primitive->element()->typeMark()) {
case (int) NovelNode::PointDefines:
{
auto target_node = std::dynamic_pointer_cast<const PointDefines>(point_primitive->element());
auto finst = std::make_shared<PointGraphHelper>(target_node);
self->setElement(finst);
}break;
default: break;
@ -136,32 +185,32 @@ void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) c
}
}
// 构建图连接
// 构建图连接
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())
{
// 过滤获取情节节点
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:
fragment_items.removeAt(idx);
idx--;
point_items.removeAt(idx--);
break;
}
}
auto get_name = [](std::shared_ptr<const ElementAccess> node)->QString {
switch (node->element()->typeMark()) {
case (int)NovelNode::PointDefines: {
case (int) NovelNode::PointDefines:
{
auto def_node = std::dynamic_pointer_cast<const PointDefines>(node->element());
return def_node->signature();
}break;
case (int)NovelNode::PointRefers: {
case (int) NovelNode::PointRefers:
{
auto ref_node = std::dynamic_pointer_cast<const PointRefers>(node->element());
return ref_node->referSignature();
}break;
@ -169,10 +218,10 @@ void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) c
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<const ElementAccess> 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<const ElementAccess> 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<const ElementAccess> root) c
}
QString FragmentGraphCheck::name() const {
return u8"情节网络有效性检查器";
return "情节网络有效性检查器";
}
FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const PointDefines> node) : node_peer(node) {}
PointGraphHelper::PointGraphHelper(std::shared_ptr<const PointDefines> node) : node_peer(node) {
}
std::shared_ptr<const PointDefines> FragmentGraphHelper::nodePeer() const
{
std::shared_ptr<const PointDefines> PointGraphHelper::nodePeer() const {
return this->node_peer;
}
void FragmentGraphHelper::appendNext(std::shared_ptr<FragmentGraphHelper> node) {
void PointGraphHelper::appendNext(std::shared_ptr<PointGraphHelper> node) {
this->next_nodes.append(node);
}
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphHelper::nextList() const
{
QList<std::shared_ptr<PointGraphHelper>> PointGraphHelper::nextList() const {
return next_nodes;
}
uint& FragmentGraphHelper::inDegree()
{
uint& PointGraphHelper::inDegree() {
return this->indegree;
}
@ -241,30 +288,30 @@ QList<std::shared_ptr<const ElementAccess>> StoryOrderCheck::valid_docs_peak(std
auto type_code = pnode->element()->typeMark();
switch ((NovelNode) type_code) {
case NovelNode::GlobalElement: {
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<const ElementAccess> e) {
return e->element()->typeMark() == (int) NovelNode::StoryDefine;
});
if (story_exists) {
auto first_elm = storys_collection.at(0);
if (story_set.size()) {
values.append(pnode);
auto first_elm = elms_set.at(0);
if (first_elm->element()->typeMark() != (int) NovelNode::RankDeclaration)
throw new CheckException(QString(u8"CheckError[0x0007]具有故事节点的文档必须在第一行指定排序(%1").arg(pnode->element()->path()));
throw new CheckException(QString("CheckError[0x0007]具有故事节点的文档必须在第一行指定排序(%1").arg(pnode->element()->path()));
}
}break;
@ -275,17 +322,16 @@ QList<std::shared_ptr<const ElementAccess>> StoryOrderCheck::valid_docs_peak(std
return values;
}
QString StoryOrderCheck::name() const
{
return u8"故事序列有效性检查器";
QString StoryOrderCheck::name() const {
return "故事序列有效性检查器";
}
void StoryOrderCheck::validCheck(std::shared_ptr<const ElementAccess> root) const
{
void StoryOrderCheck::validCheck(std::shared_ptr<const ElementAccess> root) const {
const_cast<StoryOrderCheck*>(this)->sort_index = 1;
auto story_docs = valid_docs_peak(root);
std::sort(story_docs.begin(), story_docs.end(), [](std::shared_ptr<const ElementAccess> adoc, std::shared_ptr<const ElementAccess> bdoc) {
std::sort(story_docs.begin(), story_docs.end(),
[](std::shared_ptr<const ElementAccess> adoc, std::shared_ptr<const ElementAccess> bdoc) {
auto elm_xa = std::dynamic_pointer_cast<const RankDeclare>(adoc->children().first()->element());
auto elm_xb = std::dynamic_pointer_cast<const RankDeclare>(bdoc->children().first()->element());
return elm_xa->rankNumber() < elm_xb->rankNumber();
@ -295,12 +341,13 @@ void StoryOrderCheck::validCheck(std::shared_ptr<const ElementAccess> root) cons
int page_rank = 0;
for (auto& item : story_docs) {
auto elm_xa = std::dynamic_pointer_cast<const RankDeclare>(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<const ElementAccess> doc_node, int start_index) -> int {
auto childs = doc_node->children();
for (auto& inst : childs) {

View File

@ -2,36 +2,67 @@
#include "libparse.h"
#include <ast_novel.h>
#include <QtCore/QString>
#include <QtCore/QHash>
#include <memory>
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<const ast_gen::GlobalElement> root, std::shared_ptr<const ast_gen::ElementAccess> target) const;
QHash<QString, std::shared_ptr<const ast_gen::SyntaxElement>> node_cache;
public:
// 通过 CheckProvider 继承
virtual void validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const override;
virtual QString name() const override;
virtual void clearCache();
virtual std::shared_ptr<const ast_gen::SyntaxElement> appendToCache(std::shared_ptr<const ast_gen::SyntaxElement> named_node);
/**
* @brief
* @param signature
* @return
* @throws
*/
virtual std::shared_ptr<const ast_gen::SyntaxElement> getNamedNodeBy(int paramType, const QString& signature) const;
};
class FragmentGraphHelper;
class LIBPARSE_EXPORT FragmentGraphCheck : public std::enable_shared_from_this<FragmentGraphCheck>, public lib_parse::CheckProvider {
/**
* @brief .
*/
class LIBPARSE_EXPORT FragmentExistsCheck : public lib_parse::CheckProvider {
private:
QHash<QString, std::shared_ptr<FragmentGraphHelper>> elements_store;
QList<std::shared_ptr<const FragmentGraphHelper>> fragments_sort_list;
std::shared_ptr<ElementsCache> _nodes_cache;
void nodes_regist(std::shared_ptr<ElementsCache> cache, std::shared_ptr<const ast_gen::ElementAccess> target);
QList<std::shared_ptr<FragmentGraphHelper>> refers_cycle_check(
std::shared_ptr<FragmentGraphHelper> item, QList<std::shared_ptr<FragmentGraphHelper>> prevs = QList<std::shared_ptr<FragmentGraphHelper>>()) const;
void exists_check(std::shared_ptr<ElementsCache> cache, std::shared_ptr<const ast_gen::ElementAccess> target) const;
public:
void setElement(std::shared_ptr<FragmentGraphHelper> inst);
std::shared_ptr<FragmentGraphHelper> getElement(const QString &signature) const;
// 通过 CheckProvider 继承
virtual QString name() const override;
virtual void validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const override;
};
QList<std::shared_ptr<FragmentGraphHelper>> getHangoutNodes();
bool nodeDismantle(std::shared_ptr<FragmentGraphHelper> inst);
/**
* @brief .
*/
class LIBPARSE_EXPORT FragmentGraphCheck : public lib_parse::CheckProvider, public std::enable_shared_from_this<FragmentGraphCheck> {
private:
QHash<QString, std::shared_ptr<PointGraphHelper>> elements_store;
QList<std::shared_ptr<const PointGraphHelper>> fragments_sort_list;
QList<std::shared_ptr<const FragmentGraphHelper>> fragmentsSequence() const;
QList<std::shared_ptr<PointGraphHelper>> refers_cycle_check(
std::shared_ptr<PointGraphHelper> item, QList<std::shared_ptr<PointGraphHelper>> prevs = QList<std::shared_ptr<PointGraphHelper>>()) const;
public:
void setElement(std::shared_ptr<PointGraphHelper> inst);
std::shared_ptr<PointGraphHelper> getElement(const QString &signature) const;
QList<std::shared_ptr<PointGraphHelper>> getHangoutNodes();
bool nodeDismantle(std::shared_ptr<PointGraphHelper> inst);
QList<std::shared_ptr<const PointGraphHelper>> 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<FragmentGraphHelper> {
class PointGraphHelper : public std::enable_shared_from_this<PointGraphHelper> {
private:
std::shared_ptr<const example_novel::PointDefines> node_peer;
QList<std::shared_ptr<FragmentGraphHelper>> next_nodes;
QList<std::shared_ptr<PointGraphHelper>> next_nodes;
uint indegree = 0;
public:
FragmentGraphHelper(std::shared_ptr<const example_novel::PointDefines> node);
PointGraphHelper(std::shared_ptr<const example_novel::PointDefines> node);
std::shared_ptr<const example_novel::PointDefines> nodePeer() const;
void appendNext(std::shared_ptr<FragmentGraphHelper> node);
QList<std::shared_ptr<FragmentGraphHelper>> nextList() const;
void appendNext(std::shared_ptr<PointGraphHelper> node);
QList<std::shared_ptr<PointGraphHelper>> 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<std::shared_ptr<const ast_gen::ElementAccess>> valid_docs_peak(std::shared_ptr<const ast_gen::ElementAccess> pnode) const;
public:
// 通过 CheckProvider 继承
// 通过 CheckProvider 继承
QString name() const override;
void validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const override;
};

View File

@ -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<const SyntaxElement> GlobalElement::appendToCache(std::shared_ptr<const SyntaxElement> 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<const SyntaxElement> 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<const SyntaxElement> GlobalElement::parent() const {
return std::weak_ptr<const SyntaxElement>();
}
void GlobalElement::setParent(std::shared_ptr<const SyntaxElement> inst) { }
QList<std::shared_ptr<const TokenAccess>> GlobalElement::selfTokens() const {
return QList<std::shared_ptr<const TokenAccess>>();
}
std::shared_ptr<const IExprInstance> GlobalElement::bindExpression() const {
return nullptr;
}
void GlobalElement::addChild(std::shared_ptr<SyntaxElement> citem) { }
ElementAccess::ElementAccess(std::shared_ptr<const SyntaxElement> point) {
peers = point;
}

View File

@ -99,42 +99,6 @@ namespace ast_gen {
virtual std::shared_ptr<const lib_token::IToken> token() const;
};
/**
* @brief
*/
class LIBSYNTAX_EXPORT GlobalElement : public SyntaxElement {
private:
QString names_store;
QHash<QString, std::shared_ptr<const SyntaxElement>> node_cache;
public:
static GlobalElement* UniquePtr;
GlobalElement(const QString& name);
virtual void clearCache();
virtual std::shared_ptr<const ast_gen::SyntaxElement> appendToCache(std::shared_ptr<const ast_gen::SyntaxElement> named_node);
/**
* @brief
* @param signature
* @return
* @throws
*/
virtual std::shared_ptr<const ast_gen::SyntaxElement> getNamedNodeBy(int paramType, const QString& signature) const;
virtual void addChild(std::shared_ptr<ast_gen::SyntaxElement> 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<const SyntaxElement> parent() const override;
virtual void setParent(std::shared_ptr<const SyntaxElement> inst) override;
virtual QList<std::shared_ptr<const TokenAccess>> selfTokens() const override;
// 通过 SyntaxElement 继承
virtual std::shared_ptr<const ast_basic::IExprInstance> bindExpression() const override;
};
}
namespace example_novel {