update
This commit is contained in:
parent
40c9eef31f
commit
8c902fca46
|
@ -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
|
|
@ -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'">
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue