WsParser_VS/libParse/parse_novel.cpp

226 lines
6.0 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 GlobalElement> root,
std::shared_ptr<const 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 ElementAccess> root) const {
this->exists_check(std::dynamic_pointer_cast<const GlobalElement>(root->element()), root);
}
QString FragmentExistsCheck::name() const {
return u8"FragmentExistsCheck";
}
QList<std::shared_ptr<FragmentGraphHelper>> 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>> 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 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 ElementAccess> root) const
{
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;
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 ElementAccess> node)->QString {
switch (node->element()->typeMark()) {
case (int)NovelNode::FragmentDefine: {
auto def_node = std::dynamic_pointer_cast<const FragmentDefine>(node->element());
return def_node->signature();
}break;
case (int)NovelNode::FragmentRefer: {
auto ref_node = std::dynamic_pointer_cast<const 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 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;
}