WsParser_VS/libParse/parse_novel.cpp

226 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "parse_novel.h"
#include <ast_novel.h>
#include <iterator>
#include <QTime>
using namespace example_novel;
using namespace ast_basic;
using namespace ast_gen;
using namespace lib_syntax;
using namespace example_novel;
void FragmentExistsCheck::exists_check(std::shared_ptr<const ast_gen::GlobalElement> root,
std::shared_ptr<const ast_gen::ElementAccess> target) const {
if (target->element()->typeMark() == (int)NovelNode::FragmentRefer) {
auto refer = std::dynamic_pointer_cast<const FragmentRefers>(target->element());
auto signature = refer->storyRefer() + u8"&" + refer->fragmentRefer();
root->getNamedNodeBy((int)NovelNode::FragmentDefine, signature);
}
for (auto& xit : target->children()) {
exists_check(root, xit);
}
}
void FragmentExistsCheck::validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const {
this->exists_check(std::dynamic_pointer_cast<const ast_gen::GlobalElement>(root->element()), root);
}
QString FragmentExistsCheck::name() const {
return u8"FragmentExistsCheck";
}
QList<std::shared_ptr<FragmentGraphHelper>> example_novel::FragmentGraphCheck::refers_cycle_check(
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>>();
}
void FragmentGraphCheck::setElement(std::shared_ptr<FragmentGraphHelper> inst)
{
elements_store[inst->nodePeer()->signature()] = inst;
}
std::shared_ptr<FragmentGraphHelper> FragmentGraphCheck::getElement(const QString& signature) const
{
return elements_store[signature];
}
QList<std::shared_ptr<FragmentGraphHelper>> example_novel::FragmentGraphCheck::getHangoutNodes() {
QList<std::shared_ptr<FragmentGraphHelper>> values;
for (auto node_item : elements_store) {
if (!node_item->inDegree())
values.append(node_item);
}
for (auto inst : values) {
auto name = inst->nodePeer()->signature();
elements_store.remove(name);
}
return values;
}
bool example_novel::FragmentGraphCheck::nodeDismantle(std::shared_ptr<FragmentGraphHelper> inst) {
bool flag = false;
for (auto item : inst->nextList()) {
item->inDegree()--;
flag = true;
}
return flag;
}
void FragmentGraphCheck::validCheck(std::shared_ptr<const ast_gen::ElementAccess> root) const
{
std::function<QList<std::shared_ptr<const ast_gen::ElementAccess>>(std::shared_ptr<const ast_gen::ElementAccess>)> story_peak
= [&](std::shared_ptr<const ast_gen::ElementAccess> root)->QList<std::shared_ptr<const ast_gen::ElementAccess>> {
QList<std::shared_ptr<const ast_gen::ElementAccess>> return_temp;
auto type_mark = (NovelNode)root->element()->typeMark();
if (type_mark == NovelNode::StoryDefine) {
return_temp << root;
}
for (auto child : root->children()) {
return_temp.append(story_peak(child));
}
return return_temp;
};
auto self = std::const_pointer_cast<FragmentGraphCheck>(this->shared_from_this());
// <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();
// <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);
self->setElement(finst);
}break;
default: break;
}
}
}
// <20><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
for (auto story : all_story) {
auto fragment_items = story->children();
// <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;
default:
fragment_items.removeAt(idx);
idx--;
break;
}
}
auto get_name = [](std::shared_ptr<const ast_gen::ElementAccess> node)->QString {
switch (node->element()->typeMark()) {
case (int)NovelNode::FragmentDefine: {
auto def_node = std::dynamic_pointer_cast<const example_novel::FragmentDefine>(node->element());
return def_node->signature();
}break;
case (int)NovelNode::FragmentRefer: {
auto ref_node = std::dynamic_pointer_cast<const example_novel::FragmentRefers>(node->element());
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()++;
}
}
// <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];
self->nodeDismantle(target);
auto x_values = self->getHangoutNodes();
values.append(x_values);
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>в<EFBFBD><D0B2><EFBFBD>
if (elements_store.size()) {
for (auto node : elements_store.values()) {
auto cycle_link = refers_cycle_check(node);
QString error_msg = u8"Parse[0x0006]<5D><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڻ<EFBFBD><DABB>ν<CEBD><E1B9B9>\n";
for (auto n : cycle_link) {
error_msg += QString(u8"%1->").arg(n->nodePeer()->signature());
}
if (cycle_link.size())
throw new lib_parse::CheckException(error_msg);
}
}
}
QString example_novel::FragmentGraphCheck::name() const {
return u8"FragmentGraphCheck";
}
FragmentGraphHelper::FragmentGraphHelper(std::shared_ptr<const FragmentDefine> node) : node_peer(node) {}
std::shared_ptr<const FragmentDefine> FragmentGraphHelper::nodePeer() const
{
return this->node_peer;
}
void FragmentGraphHelper::appendNext(std::shared_ptr<FragmentGraphHelper> node) {
this->next_nodes.append(node);
}
QList<std::shared_ptr<FragmentGraphHelper>> FragmentGraphHelper::nextList() const
{
return next_nodes;
}
uint& FragmentGraphHelper::inDegree()
{
return this->indegree;
}