2024-03-17 07:58:28 +00:00
|
|
|
|
#include "parse_novel.h"
|
|
|
|
|
|
|
|
|
|
#include <ast_novel.h>
|
|
|
|
|
#include <iterator>
|
2024-06-15 01:18:33 +00:00
|
|
|
|
#include <QTime>
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-20 13:36:46 +00:00
|
|
|
|
using namespace lib_parse;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
using namespace example_novel;
|
|
|
|
|
using namespace ast_basic;
|
|
|
|
|
using namespace ast_gen;
|
|
|
|
|
using namespace lib_syntax;
|
|
|
|
|
using namespace example_novel;
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
void FragmentExistsCheck::exists_check(std::shared_ptr<const GlobalElement> root,
|
|
|
|
|
std::shared_ptr<const ElementAccess> target) const {
|
2024-06-15 08:09:19 +00:00
|
|
|
|
if (target->element()->typeMark() == (int)NovelNode::FragmentRefer) {
|
|
|
|
|
auto refer = std::dynamic_pointer_cast<const FragmentRefers>(target->element());
|
2024-03-17 07:58:28 +00:00
|
|
|
|
auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer();
|
2024-06-20 13:36:46 +00:00
|
|
|
|
if(!root->getNamedNodeBy((int)NovelNode::FragmentDefine, signature))
|
|
|
|
|
throw new SyntaxException(QString(u8"CheckError[0x0005]ϵͳ<CFB5>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ǩ<EFBFBD><C7A9><EFBFBD>Ľڵ㣺%1<type<70><65>%2>{%3:(%4)}")
|
|
|
|
|
.arg(signature).arg((int)NovelNode::FragmentDefine).arg(refer->signature()).arg(refer->filePath()));
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& xit : target->children()) {
|
|
|
|
|
exists_check(root, xit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
void FragmentExistsCheck::validCheck(std::shared_ptr<const ElementAccess> root) const {
|
|
|
|
|
this->exists_check(std::dynamic_pointer_cast<const GlobalElement>(root->element()), root);
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
QString FragmentExistsCheck::name() const {
|
2024-06-20 13:36:46 +00:00
|
|
|
|
return u8"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::refers_cycle_check(
|
2024-06-15 08:52:16 +00:00
|
|
|
|
std::shared_ptr<FragmentGraphHelper> item, QList<std::shared_ptr<FragmentGraphHelper>> prevs) const {
|
|
|
|
|
if (prevs.contains(item)) {
|
|
|
|
|
return prevs << item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto next_list = item->nextList();
|
|
|
|
|
if (next_list.size()) {
|
|
|
|
|
prevs << item;
|
|
|
|
|
for (auto next : next_list) {
|
|
|
|
|
auto ref_link = refers_cycle_check(next, prevs);
|
|
|
|
|
if (ref_link.size())
|
|
|
|
|
return ref_link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return QList<std::shared_ptr<FragmentGraphHelper>>();
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
void FragmentGraphCheck::setElement(std::shared_ptr<FragmentGraphHelper> inst)
|
2024-03-17 07:58:28 +00:00
|
|
|
|
{
|
2024-06-15 08:09:19 +00:00
|
|
|
|
elements_store[inst->nodePeer()->signature()] = inst;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
std::shared_ptr<FragmentGraphHelper> FragmentGraphCheck::getElement(const QString& signature) const
|
|
|
|
|
{
|
|
|
|
|
return elements_store[signature];
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphCheck::getHangoutNodes() {
|
2024-06-15 08:09:19 +00:00
|
|
|
|
QList<std::shared_ptr<FragmentGraphHelper>> values;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
for (auto node_item : elements_store) {
|
|
|
|
|
if (!node_item->inDegree())
|
|
|
|
|
values.append(node_item);
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
for (auto inst : values) {
|
|
|
|
|
auto name = inst->nodePeer()->signature();
|
|
|
|
|
elements_store.remove(name);
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return values;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
bool FragmentGraphCheck::nodeDismantle(std::shared_ptr<FragmentGraphHelper> inst) {
|
2024-06-15 08:09:19 +00:00
|
|
|
|
bool flag = false;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
for (auto item : inst->nextList()) {
|
|
|
|
|
item->inDegree()--;
|
|
|
|
|
flag = true;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return flag;
|
2024-05-04 15:34:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
void FragmentGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) const
|
2024-03-17 07:58:28 +00:00
|
|
|
|
{
|
2024-06-19 14:45:55 +00:00
|
|
|
|
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>> {
|
|
|
|
|
QList<std::shared_ptr<const ElementAccess>> return_temp;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
auto type_mark = (NovelNode)root->element()->typeMark();
|
|
|
|
|
if (type_mark == NovelNode::StoryDefine) {
|
|
|
|
|
return_temp << root;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
for (auto child : root->children()) {
|
|
|
|
|
return_temp.append(story_peak(child));
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return return_temp;
|
|
|
|
|
};
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
auto self = std::const_pointer_cast<FragmentGraphCheck>(this->shared_from_this());
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
auto all_story = story_peak(root);
|
|
|
|
|
// ע<><D7A2>ͼ<EFBFBD>ڵ<EFBFBD>
|
|
|
|
|
for (auto story : all_story) {
|
|
|
|
|
auto fragment_items = story->children();
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽڵ<DABD><DAB5>б<EFBFBD>
|
|
|
|
|
for (auto frag_primitive : fragment_items) {
|
|
|
|
|
switch (frag_primitive->element()->typeMark()) {
|
|
|
|
|
case (int)NovelNode::FragmentDefine: {
|
|
|
|
|
auto target_node = std::dynamic_pointer_cast<const FragmentDefine>(frag_primitive->element());
|
|
|
|
|
auto finst = std::make_shared<FragmentGraphHelper>(target_node);
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
self->setElement(finst);
|
|
|
|
|
}break;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
|
|
|
|
|
for (auto story : all_story) {
|
|
|
|
|
auto fragment_items = story->children();
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><><EFBFBD>˻<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ڽڵ<DABD>
|
|
|
|
|
for (auto idx = 0; idx < fragment_items.size(); idx++) {
|
|
|
|
|
auto fragment_inst = fragment_items[idx];
|
|
|
|
|
switch (fragment_inst->element()->typeMark())
|
|
|
|
|
{
|
|
|
|
|
case (int)NovelNode::FragmentDefine:
|
|
|
|
|
case (int)NovelNode::FragmentRefer:
|
|
|
|
|
break;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
default:
|
2024-06-15 08:09:19 +00:00
|
|
|
|
fragment_items.removeAt(idx);
|
|
|
|
|
idx--;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
auto get_name = [](std::shared_ptr<const ElementAccess> node)->QString {
|
2024-06-15 08:09:19 +00:00
|
|
|
|
switch (node->element()->typeMark()) {
|
|
|
|
|
case (int)NovelNode::FragmentDefine: {
|
2024-06-19 14:45:55 +00:00
|
|
|
|
auto def_node = std::dynamic_pointer_cast<const FragmentDefine>(node->element());
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return def_node->signature();
|
|
|
|
|
}break;
|
|
|
|
|
case (int)NovelNode::FragmentRefer: {
|
2024-06-19 14:45:55 +00:00
|
|
|
|
auto ref_node = std::dynamic_pointer_cast<const FragmentRefers>(node->element());
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return ref_node->referSignature();
|
|
|
|
|
}break;
|
|
|
|
|
}
|
|
|
|
|
return QString();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>ṹ
|
|
|
|
|
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]);
|
|
|
|
|
|
|
|
|
|
auto tail_helper = getElement(tail_name);
|
|
|
|
|
auto head_helper = getElement(head_name);
|
|
|
|
|
|
|
|
|
|
tail_helper->appendNext(head_helper);
|
|
|
|
|
head_helper->inDegree()++;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
auto values = self->getHangoutNodes();
|
|
|
|
|
for (auto idx = 0; idx < values.size(); ++idx) {
|
|
|
|
|
auto target = values[idx];
|
2024-05-04 15:34:21 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
self->nodeDismantle(target);
|
|
|
|
|
auto x_values = self->getHangoutNodes();
|
|
|
|
|
values.append(x_values);
|
2024-05-04 15:34:21 +00:00
|
|
|
|
}
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>в<EFBFBD><D0B2><EFBFBD>
|
2024-06-15 08:52:16 +00:00
|
|
|
|
if (elements_store.size()) {
|
|
|
|
|
for (auto node : elements_store.values()) {
|
|
|
|
|
auto cycle_link = refers_cycle_check(node);
|
|
|
|
|
|
2024-06-20 13:36:46 +00:00
|
|
|
|
QString error_msg = u8"CheckError[0x0006]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>ڻ<EFBFBD><DABB>νṹ<CEBD><E1B9B9>\n";
|
2024-06-15 08:52:16 +00:00
|
|
|
|
for (auto n : cycle_link) {
|
|
|
|
|
error_msg += QString(u8"%1->").arg(n->nodePeer()->signature());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cycle_link.size())
|
2024-06-20 13:36:46 +00:00
|
|
|
|
throw new CheckException(error_msg);
|
2024-06-15 08:52:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 14:45:55 +00:00
|
|
|
|
QString FragmentGraphCheck::name() const {
|
2024-06-20 13:36:46 +00:00
|
|
|
|
return u8"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const FragmentDefine> node) : node_peer(node) {}
|
2024-03-17 07:58:28 +00:00
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
std::shared_ptr<const FragmentDefine> FragmentGraphHelper::nodePeer() const
|
2024-03-17 07:58:28 +00:00
|
|
|
|
{
|
2024-06-15 08:09:19 +00:00
|
|
|
|
return this->node_peer;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
void FragmentGraphHelper::appendNext(std::shared_ptr<FragmentGraphHelper> node) {
|
|
|
|
|
this->next_nodes.append(node);
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphHelper::nextList() const
|
|
|
|
|
{
|
|
|
|
|
return next_nodes;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 08:09:19 +00:00
|
|
|
|
uint& FragmentGraphHelper::inDegree()
|
|
|
|
|
{
|
|
|
|
|
return this->indegree;
|
2024-03-17 07:58:28 +00:00
|
|
|
|
}
|
2024-06-20 13:36:46 +00:00
|
|
|
|
|
|
|
|
|
QList<std::shared_ptr<const ElementAccess>> StoryOrderCheck::valid_docs_peak(std::shared_ptr<const ElementAccess> pnode) const {
|
|
|
|
|
QList<std::shared_ptr<const ElementAccess>> 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;
|
|
|
|
|
|
|
|
|
|
case NovelNode::Document: {
|
|
|
|
|
auto storys_collection = pnode->children();
|
|
|
|
|
|
|
|
|
|
bool story_exists = false;
|
|
|
|
|
for (auto& syntax_elm : storys_collection) {
|
|
|
|
|
if (syntax_elm->element()->typeMark() == (int)NovelNode::StoryDefine) {
|
|
|
|
|
story_exists = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (story_exists) {
|
|
|
|
|
auto first_elm = storys_collection.at(0);
|
|
|
|
|
values.append(pnode);
|
|
|
|
|
|
|
|
|
|
if(first_elm->element()->typeMark() != (int)NovelNode::RankDeclaration)
|
|
|
|
|
throw new CheckException(QString(u8"CheckError[0x0007]<5D><><EFBFBD>й<EFBFBD><D0B9>½ڵ<C2BD><DAB5><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>һ<EFBFBD><D2BB>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>%1<><31>").arg(pnode->element()->path()));
|
|
|
|
|
}
|
|
|
|
|
}break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString StoryOrderCheck::name() const
|
|
|
|
|
{
|
|
|
|
|
return u8"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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){
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// page_rank valid
|
|
|
|
|
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]<5D>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>ͬ<EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>{%1}").arg(elm_xa->path()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>½ڵ<C2BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
auto story_node_sort = [](std::shared_ptr<const ElementAccess> doc_node, int start_index) -> int{
|
|
|
|
|
auto childs = doc_node->children();
|
|
|
|
|
for (auto &inst : childs) {
|
|
|
|
|
if (inst->element()->typeMark() == (int)NovelNode::StoryDefine) {
|
|
|
|
|
auto cast_inst = std::dynamic_pointer_cast<const StoryDefine>(inst->element());
|
|
|
|
|
std::const_pointer_cast<StoryDefine>(cast_inst)->setSort(start_index++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return start_index;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int ranks_number = 1;
|
|
|
|
|
for(auto &story : story_docs)
|
|
|
|
|
ranks_number = story_node_sort(story, ranks_number);
|
|
|
|
|
}
|