674 lines
25 KiB
C++
674 lines
25 KiB
C++
#include "htmlprint.h"
|
|
#include <QDir>
|
|
#include <QDomElement>
|
|
|
|
using namespace example_novel;
|
|
using namespace printer;
|
|
using namespace lib_parse;
|
|
|
|
Access::Access(std::shared_ptr<const ast_gen::ElementAccess> handle)
|
|
:access_handle(handle) {}
|
|
|
|
std::shared_ptr<const ast_gen::ElementAccess> Access::accessPeers() const { return access_handle; }
|
|
|
|
void Access::setPageRefers(const QString& href) { this->summary_refer_store = href; }
|
|
|
|
QString Access::pageRefers() const { return this->summary_refer_store; }
|
|
|
|
Element::Element(std::shared_ptr<const ast_gen::ElementAccess> handle) :Access(handle) {}
|
|
|
|
void printer::Element::setSliceRefer(const QString& href) {
|
|
this->refer_store = href;
|
|
}
|
|
|
|
QString printer::Element::sliceRefers() const {
|
|
return refer_store;
|
|
}
|
|
|
|
Group::Group(std::shared_ptr<const ast_gen::ElementAccess> handle) : Access(handle) {}
|
|
|
|
void Group::append(std::shared_ptr<Element> elm)
|
|
{
|
|
element_store.append(elm);
|
|
}
|
|
|
|
QList<std::shared_ptr<Element>> Group::elements() const
|
|
{
|
|
return this->element_store;
|
|
}
|
|
|
|
std::shared_ptr<Element> printer::Group::getElement(const QString& signature) const
|
|
{
|
|
for (auto& it : elements()) {
|
|
if (it->accessPeers()->element()->signature() == signature)
|
|
return it;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
StoryLine::StoryLine(std::shared_ptr<const ast_gen::ElementAccess> handle) :Group(handle) {}
|
|
|
|
void StoryLine::buildPageHTML(QDomElement& parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto storyline_inst = std::dynamic_pointer_cast<const StoryDefine>(syntax_access->element());
|
|
|
|
auto doc = parent.ownerDocument();
|
|
auto dom_storyline = doc.createElement("div");
|
|
parent.appendChild(dom_storyline);
|
|
|
|
auto dom_title = doc.createElement("h1");
|
|
dom_title.appendChild(doc.createTextNode(storyline_inst->name()));
|
|
dom_storyline.appendChild(dom_title);
|
|
|
|
for (auto& inst_c : syntax_access->children()) {
|
|
switch ((NovelNode)inst_c->element()->typeMark()) {
|
|
case NovelNode::TextSection: {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
auto dom_p = doc.createElement("p");
|
|
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
dom_storyline.appendChild(dom_p);
|
|
}break;
|
|
case NovelNode::FragmentRefer:
|
|
case NovelNode::FragmentDefine: {
|
|
auto element_inst = this->getElement(inst_c->element()->signature());
|
|
element_inst->buildSliceHTML(dom_storyline);
|
|
}break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
StoryVolume::StoryVolume(std::shared_ptr<const ast_gen::ElementAccess> handle) : Group(handle) {}
|
|
|
|
void StoryVolume::buildPageHTML(QDomElement& parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto volume_inst = std::dynamic_pointer_cast<const VolumeDefine>(syntax_access->element());
|
|
|
|
auto doc_inst = parent.ownerDocument();
|
|
auto dom_volume = doc_inst.createElement("div");
|
|
parent.appendChild(dom_volume);
|
|
|
|
auto dom_title = doc_inst.createElement("h1");
|
|
dom_title.appendChild(doc_inst.createTextNode(volume_inst->name()));
|
|
dom_volume.appendChild(dom_title);
|
|
|
|
std::function<void(QDomElement&, const QList<std::shared_ptr<const ast_gen::ElementAccess>>&)> rich_refer_build =
|
|
[&](QDomElement& parent_element, const QList<std::shared_ptr<const ast_gen::ElementAccess>> children) {
|
|
for (auto& child : children) {
|
|
auto doc_ins = parent_element.ownerDocument();
|
|
switch ((NovelNode)child->element()->typeMark()) {
|
|
case NovelNode::TextSection: {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
auto dom_p = doc_ins.createElement("p");
|
|
dom_p.appendChild(doc_ins.createTextNode(text_inst->content()));
|
|
parent_element.appendChild(dom_p);
|
|
}break;
|
|
case NovelNode::ArticleDefine: {
|
|
auto article_inst = std::dynamic_pointer_cast<const ArticleDefine>(child->element());
|
|
auto article_group = doc_ins.createElement("div");
|
|
auto article_head = doc_ins.createElement("h2");
|
|
article_head.appendChild(doc_ins.createTextNode(article_inst->name() + u8"{"));
|
|
article_group.appendChild(article_head);
|
|
rich_refer_build(article_group, child->children());
|
|
article_group.appendChild(doc_ins.createTextNode(u8"}"));
|
|
parent_element.appendChild(article_group);
|
|
}break;
|
|
case NovelNode::FragmentRefer:{
|
|
auto fragment_inst = std::dynamic_pointer_cast<const FragmentRefers>(child->element());
|
|
auto refer_inst = this->getElement(fragment_inst->signature());
|
|
refer_inst->buildSliceHTML(parent_element);
|
|
}break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
rich_refer_build(dom_volume, syntax_access->children());
|
|
}
|
|
|
|
FragmentRef::FragmentRef(std::shared_ptr<const ast_gen::ElementAccess> handle) : Element(handle) {}
|
|
|
|
void printer::FragmentRef::setHost(std::shared_ptr<Fragment> frag_inst)
|
|
{
|
|
this->host_inst = frag_inst;
|
|
}
|
|
|
|
std::shared_ptr<Fragment> printer::FragmentRef::hostFragment() const
|
|
{
|
|
return this->host_inst.lock();
|
|
}
|
|
|
|
void FragmentRef::buildSliceHTML(QDomElement& dom_parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto refer_element = std::dynamic_pointer_cast<const FragmentRefers>(syntax_access->element());
|
|
|
|
auto jump_to_host = this->hostFragment()->pageRefers();
|
|
auto doc = dom_parent.ownerDocument();
|
|
|
|
auto dom_reference = doc.createElement(u8"div");
|
|
dom_reference.setAttribute("id", QString::number((qulonglong)refer_element.get()));
|
|
dom_parent.appendChild(dom_reference);
|
|
|
|
auto dom_title = doc.createElement(u8"h2");
|
|
dom_reference.appendChild(dom_title);
|
|
|
|
auto dom_href = doc.createElement(u8"a");
|
|
dom_href.appendChild(doc.createTextNode(refer_element->referSignature()));
|
|
dom_href.setAttribute("href", u8"file:///"+jump_to_host);
|
|
dom_title.appendChild(dom_href);
|
|
|
|
std::function<void(QDomElement&, const QList<std::shared_ptr<const ast_gen::ElementAccess>>&)> rich_refer_build =
|
|
[&](QDomElement& parent_element, const QList<std::shared_ptr<const ast_gen::ElementAccess>> children) {
|
|
for (auto& child : children) {
|
|
auto doc_ins = parent_element.ownerDocument();
|
|
switch ((NovelNode)child->element()->typeMark()) {
|
|
case NovelNode::TextSection: {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
auto dom_p = doc_ins.createElement("p");
|
|
dom_p.appendChild(doc_ins.createTextNode(text_inst->content()));
|
|
parent_element.appendChild(dom_p);
|
|
}break;
|
|
case NovelNode::ArticleDefine: {
|
|
auto article_inst = std::dynamic_pointer_cast<const ArticleDefine>(child->element());
|
|
auto article_group = doc_ins.createElement("div");
|
|
auto article_head = doc_ins.createElement("h2");
|
|
article_head.appendChild(doc_ins.createTextNode(article_inst->name() + u8"{"));
|
|
article_group.appendChild(article_head);
|
|
rich_refer_build(article_group, child->children());
|
|
article_group.appendChild(doc_ins.createTextNode(u8"}"));
|
|
parent_element.appendChild(article_group);
|
|
}break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
rich_refer_build(dom_reference, syntax_access->children());
|
|
}
|
|
|
|
void FragmentRef::buildPageHTML(QDomElement& parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto refer_element = std::dynamic_pointer_cast<const FragmentRefers>(syntax_access->element());
|
|
|
|
auto doc = parent.ownerDocument();
|
|
|
|
auto refers_dom = doc.createElement(u8"div");
|
|
parent.appendChild(refers_dom);
|
|
|
|
auto title_block = doc.createElement(u8"h2");
|
|
refers_dom.appendChild(title_block);
|
|
auto title_refer = doc.createElement(u8"a");
|
|
title_refer.appendChild(doc.createTextNode(refer_element->signature()));
|
|
title_refer.setAttribute("href", u8"file:///"+this->sliceRefers());
|
|
title_block.appendChild(title_refer);
|
|
|
|
std::function<void(QList<std::shared_ptr<const ast_gen::ElementAccess>>)> build_cascade =
|
|
[&](QList<std::shared_ptr<const ast_gen::ElementAccess>> children_items) {
|
|
for (auto child : children_items) {
|
|
if (child->element()->typeMark() == (int)NovelNode::TextSection) {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
auto p = doc.createElement("p");
|
|
p.appendChild(doc.createTextNode(text_inst->content()));
|
|
refers_dom.appendChild(p);
|
|
}
|
|
else {
|
|
build_cascade(child->children());
|
|
}
|
|
}
|
|
};
|
|
|
|
build_cascade(syntax_access->children());
|
|
}
|
|
|
|
Fragment::Fragment(std::shared_ptr<const ast_gen::ElementAccess> handle) : Element(handle) {}
|
|
|
|
void Fragment::appendRefers(std::shared_ptr<FragmentRef> inst) {
|
|
this->additionals_store.append(inst);
|
|
inst->setHost(std::static_pointer_cast<Fragment>(this->shared_from_this()));
|
|
}
|
|
|
|
QList<std::shared_ptr<FragmentRef>> Fragment::additionals() const {
|
|
return this->additionals_store;
|
|
}
|
|
|
|
void Fragment::buildSliceHTML(QDomElement& parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto fragment_inst = std::dynamic_pointer_cast<const FragmentDefine>(syntax_access->element());
|
|
|
|
auto doc = parent.ownerDocument();
|
|
auto dom_fragment = doc.createElement("div");
|
|
dom_fragment.setAttribute("id", QString::number((qulonglong)fragment_inst.get()));
|
|
parent.appendChild(dom_fragment);
|
|
|
|
auto dom_title = doc.createElement("h2");
|
|
dom_fragment.appendChild(dom_title);
|
|
|
|
auto dom_href = doc.createElement("a");
|
|
dom_href.appendChild(doc.createTextNode(fragment_inst->name()));
|
|
dom_href.setAttribute("href", u8"file:///"+this->pageRefers());
|
|
dom_title.appendChild(dom_href);
|
|
|
|
for (auto& inst_c : syntax_access->children()) {
|
|
if (NovelNode::TextSection == (NovelNode)inst_c->element()->typeMark()) {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
auto dom_p = doc.createElement("p");
|
|
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
dom_fragment.appendChild(dom_p);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void Fragment::buildPageHTML(QDomElement& parent) const {
|
|
auto syntax_access = this->accessPeers();
|
|
auto fragment_inst = std::dynamic_pointer_cast<const FragmentDefine>(syntax_access->element());
|
|
|
|
auto doc = parent.ownerDocument();
|
|
auto dom_fragment = doc.createElement("div");
|
|
parent.appendChild(dom_fragment);
|
|
|
|
auto dom_title = doc.createElement("h1");
|
|
dom_fragment.appendChild(dom_title);
|
|
|
|
auto dom_href = doc.createElement("a");
|
|
dom_href.appendChild(doc.createTextNode(fragment_inst->signature()));
|
|
dom_href.setAttribute("href", u8"file:///" + this->sliceRefers());
|
|
dom_title.appendChild(dom_href);
|
|
|
|
for (auto& inst_c : syntax_access->children()) {
|
|
if (NovelNode::TextSection == (NovelNode)inst_c->element()->typeMark()) {
|
|
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
auto dom_p = doc.createElement("p");
|
|
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
dom_fragment.appendChild(dom_p);
|
|
}
|
|
}
|
|
|
|
for (auto& it : this->additionals()) {
|
|
it->buildPageHTML(dom_fragment);
|
|
}
|
|
}
|
|
|
|
#include <ast_novel.h>
|
|
void tools_printer::build_fragments(std::shared_ptr<const ast_gen::ElementAccess> novel_root)
|
|
{
|
|
if (novel_root->element()->typeMark() == (int)NovelNode::FragmentDefine) {
|
|
auto inst = std::make_shared<Fragment>(novel_root);
|
|
auto name = novel_root->element()->signature();
|
|
this->fragment_defines[name] = inst;
|
|
}
|
|
|
|
for (auto& inst_c : novel_root->children()) {
|
|
build_fragments(inst_c);
|
|
}
|
|
}
|
|
|
|
void tools_printer::build_refers_network(std::shared_ptr<const ast_gen::ElementAccess> novel_node)
|
|
{
|
|
switch ((NovelNode)novel_node->element()->typeMark()) {
|
|
case NovelNode::StoryDefine: {
|
|
auto storyinst = std::make_shared<StoryLine>(novel_node);
|
|
this->storyline_defines[novel_node->element()->signature()] = storyinst;
|
|
build_storyline(storyinst);
|
|
}return;
|
|
case NovelNode::VolumeDefine: {
|
|
auto volumeinst = std::make_shared<StoryVolume>(novel_node);
|
|
this->volume_defines[novel_node->element()->signature()] = volumeinst;
|
|
build_volumeline(volumeinst);
|
|
}return;
|
|
}
|
|
|
|
for (auto& inst_c : novel_node->children())
|
|
build_refers_network(inst_c);
|
|
}
|
|
|
|
void tools_printer::build_storyline(std::shared_ptr<StoryLine> line, std::shared_ptr<const ast_gen::ElementAccess> novel_node)
|
|
{
|
|
if (!novel_node) {
|
|
for (auto& inst_c : line->accessPeers()->children()) {
|
|
build_storyline(line, inst_c);
|
|
}
|
|
}
|
|
else {
|
|
switch ((NovelNode)novel_node->element()->typeMark())
|
|
{
|
|
case NovelNode::FragmentDefine: {
|
|
auto inst = this->fragment_defines[novel_node->element()->signature()];
|
|
line->append(inst);
|
|
}return;
|
|
case NovelNode::FragmentRefer: {
|
|
auto refer_node = std::dynamic_pointer_cast<const FragmentRefers>(novel_node->element());
|
|
auto refer_fragment = this->fragment_defines[refer_node->referSignature()];
|
|
auto inst = std::make_shared<FragmentRef>(novel_node);
|
|
refer_fragment->appendRefers(inst);
|
|
line->append(inst);
|
|
}return;
|
|
}
|
|
|
|
for (auto& inst_c : novel_node->children())
|
|
build_storyline(line, inst_c);
|
|
}
|
|
}
|
|
|
|
void tools_printer::build_volumeline(std::shared_ptr<StoryVolume> volume, std::shared_ptr<const ast_gen::ElementAccess> novel_node)
|
|
{
|
|
if (!novel_node) {
|
|
for (auto& inst_c : volume->accessPeers()->children())
|
|
build_volumeline(volume, inst_c);
|
|
}
|
|
else {
|
|
if (NovelNode::FragmentRefer == (NovelNode)novel_node->element()->typeMark()) {
|
|
auto refer_node = std::dynamic_pointer_cast<const FragmentRefers>(novel_node->element());
|
|
auto refer_fragment = this->fragment_defines[refer_node->referSignature()];
|
|
auto inst = std::make_shared<FragmentRef>(novel_node);
|
|
refer_fragment->appendRefers(inst);
|
|
volume->append(inst);
|
|
return;
|
|
}
|
|
|
|
for (auto& inst_c : novel_node->children())
|
|
build_volumeline(volume, inst_c);
|
|
}
|
|
}
|
|
|
|
void tools_printer::fragments_anchors_define(const QList<std::shared_ptr<Fragment>>& list, const QDir& root_dir) {
|
|
auto path = root_dir.filePath("fragments");
|
|
if (!QDir(path).exists())
|
|
root_dir.mkdir("fragments");
|
|
QDir target_dir(path);
|
|
|
|
for (auto& it : list) {
|
|
auto address_x = QString::number((qulonglong)it->accessPeers()->element().get());
|
|
it->setPageRefers(target_dir.absoluteFilePath(QString("%1.html").arg(address_x)));
|
|
}
|
|
}
|
|
|
|
std::function<void(const QList<std::shared_ptr<Element>>&, const QString&)> refers_refresh =
|
|
[&](const QList<std::shared_ptr<Element>>& items, const QString& summary_href) {
|
|
for (auto& item : items) {
|
|
auto element_addr = QString::number((qulonglong)item->accessPeers()->element().get());
|
|
item->setSliceRefer(summary_href + u8"#" + element_addr);
|
|
}
|
|
};
|
|
|
|
void tools_printer::storylines_anchors_define(const QList<std::shared_ptr<StoryLine>>& list, const QDir& root_dir) {
|
|
auto path = root_dir.filePath("storylines");
|
|
if (!QDir(path).exists())
|
|
root_dir.mkdir("storylines");
|
|
QDir target_dir(path);
|
|
|
|
for (auto& it : list) {
|
|
auto address_x = QString::number((qulonglong)it->accessPeers()->element().get());
|
|
auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x));
|
|
it->setPageRefers(page_address);
|
|
refers_refresh(it->elements(), page_address);
|
|
}
|
|
}
|
|
|
|
void tools_printer::volumes_anchors_define(const QList<std::shared_ptr<StoryVolume>>& list, const QDir& root_dir) {
|
|
auto path = root_dir.filePath("volumes");
|
|
if (!QDir(path).exists())
|
|
root_dir.mkdir("volumes");
|
|
QDir target_dir(path);
|
|
|
|
for (auto& it : list) {
|
|
auto address_x = QString::number((qulonglong)it->accessPeers()->element().get());
|
|
auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x));
|
|
it->setPageRefers(page_address);
|
|
refers_refresh(it->elements(), page_address);
|
|
}
|
|
}
|
|
|
|
auto get_node_name = [](const std::shared_ptr<Access> item){
|
|
return u8"node_" + QString::number((qulonglong)item->accessPeers()->element().get());
|
|
};
|
|
|
|
QString printer::tools_printer::storylines_paint(const QList<std::shared_ptr<StoryLine>> &lines) {
|
|
QHash<QString, std::shared_ptr<Access>> node_records;
|
|
QString nodes_description;
|
|
for (auto& story : lines) {
|
|
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
node_records[story_elem->signature()] = story;
|
|
nodes_description += get_node_name(story) + QString(u8"[fillcolor=pink,label=\"%1{%2}\",shape=\"cds\"]\n").arg(story_elem->name()).arg(story_elem->sort());
|
|
|
|
for (auto &frag : story->elements()) {
|
|
auto fragment_peers = frag->accessPeers()->element();
|
|
if (fragment_peers->typeMark() == (int)example_novel::NovelNode::FragmentDefine) {
|
|
auto fragment_elem = std::dynamic_pointer_cast<const example_novel::FragmentDefine>(fragment_peers);
|
|
auto node_name = fragment_elem->signature();
|
|
node_records[node_name] = frag;
|
|
|
|
nodes_description += get_node_name(frag) + QString(u8"[label=\"{%2}::%1\",shape=\"rect\"]\n")
|
|
.arg(fragment_elem->name()).arg(story_elem->sort());
|
|
}
|
|
}
|
|
}
|
|
|
|
QString arrows_link;
|
|
for (auto &story : lines) {
|
|
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
|
|
QString previous_node = get_node_name(story);
|
|
for (auto &frag : story->elements()) {
|
|
if (example_novel::NovelNode::FragmentDefine == (example_novel::NovelNode) frag->accessPeers()->element()->typeMark()) {
|
|
arrows_link += previous_node + u8"->" + get_node_name(frag) + QString(u8"[label=\"%1{%2}\"]\n")
|
|
.arg(story_elem->name()).arg(story_elem->sort());
|
|
previous_node = get_node_name(frag);
|
|
}
|
|
else if (example_novel::NovelNode::FragmentRefer == (example_novel::NovelNode)frag->accessPeers()->element()->typeMark()) {
|
|
auto frag_refer = std::dynamic_pointer_cast<const example_novel::FragmentRefers>(frag->accessPeers()->element());
|
|
auto frag_src = node_records[frag_refer->referSignature()];
|
|
arrows_link += previous_node + u8"->" + get_node_name(frag_src) + QString(u8"[label=\"%1{%2}\"]\n")
|
|
.arg(story_elem->name()).arg(story_elem->sort());
|
|
previous_node = get_node_name(frag_src);
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString(u8"digraph{ rankdir = LR \n node[style=filled] \n %1\n %2 }").arg(nodes_description).arg(arrows_link);
|
|
}
|
|
|
|
QString printer::tools_printer::volumes_paint(const QList<std::shared_ptr<StoryVolume>>& vols, const QList<std::shared_ptr<StoryLine>>& lines) {
|
|
QHash<QString, std::shared_ptr<Element>> node_records;
|
|
|
|
QString clusters_description;
|
|
for (auto& story : lines) {
|
|
QString nodes_description;
|
|
for (auto &frag : story->elements()) {
|
|
auto fragment_peers = frag->accessPeers()->element();
|
|
if (fragment_peers->typeMark() == (int)example_novel::NovelNode::FragmentDefine) {
|
|
auto fragment_elem = std::dynamic_pointer_cast<const example_novel::FragmentDefine>(fragment_peers);
|
|
node_records[fragment_elem->signature()] = frag;
|
|
nodes_description += get_node_name(frag) + QString(u8"[label=\"%1\",shape=\"ellipse\"]\n").arg(fragment_elem->name());
|
|
}
|
|
}
|
|
|
|
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
clusters_description += QString(u8"subgraph cluster_%1 { label=%3 \n %2 }")
|
|
.arg((qulonglong)story_elem.get()).arg(nodes_description).arg(story_elem->name());
|
|
}
|
|
|
|
|
|
auto article_cluster = [&node_records](
|
|
const std::shared_ptr<const ast_gen::ElementAccess> article_access, QList<QString> &arrows_out)->QString {
|
|
QString nodes_description;
|
|
for (auto& fragment_access : article_access->children()) {
|
|
if (fragment_access->element()->typeMark() == (int)example_novel::NovelNode::FragmentRefer) {
|
|
auto refer_fragment = std::dynamic_pointer_cast<const example_novel::FragmentRefers>(fragment_access->element());
|
|
nodes_description += QString(u8"fragment_%1[label=\"%2\",shape=\"plaintext\"]\n")
|
|
.arg((qulonglong)refer_fragment.get()).arg(refer_fragment->fragmentRefer());
|
|
auto symbo_refer = node_records[refer_fragment->referSignature()];
|
|
arrows_out << QString(u8"fragment_%1 -- %2[color=\"red\"]\n").arg((qulonglong)refer_fragment.get()).arg(get_node_name(symbo_refer));
|
|
}
|
|
}
|
|
auto article_define = std::dynamic_pointer_cast<const example_novel::ArticleDefine>(article_access->element());
|
|
return QString(u8"subgraph cluster_%1{ label=%2 \n %3 }\n").arg((qulonglong)article_access->element().get())
|
|
.arg(article_define->name()).arg(nodes_description);
|
|
};
|
|
|
|
QString arrows_link;
|
|
for (auto &vol : vols) {
|
|
QString members_description;
|
|
for (auto& eref : vol->accessPeers()->children()) {
|
|
QList<QString> arrows_temp;
|
|
switch ((example_novel::NovelNode)eref->element()->typeMark()){
|
|
case example_novel::NovelNode::ArticleDefine:
|
|
members_description += article_cluster(eref, arrows_temp);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
for (auto& arrow : arrows_temp) {
|
|
arrows_link += arrow;
|
|
}
|
|
}
|
|
|
|
auto volume_elem = std::dynamic_pointer_cast<const example_novel::VolumeDefine>(vol->accessPeers()->element());
|
|
clusters_description += QString(u8"subgraph cluster_%1 { label=%3 \n %2 }")
|
|
.arg((qulonglong)volume_elem.get()).arg(members_description).arg(volume_elem->name());
|
|
}
|
|
|
|
return QString("graph scale{ %1 \n %2}").arg(clusters_description).arg(arrows_link);
|
|
}
|
|
|
|
void printer::AstGenerate::append_tokens(QDomElement _elm, std::shared_ptr<const ast_gen::SyntaxElement> inst) {
|
|
auto dom_tokens = doc.createElement(u8"tokens");
|
|
_elm.appendChild(dom_tokens);
|
|
|
|
for (auto& token : inst->selfTokens()) {
|
|
auto dom_token = doc.createElement(u8"token");
|
|
dom_tokens.appendChild(dom_token);
|
|
|
|
dom_token.setAttribute(u8"text", token->token()->content());
|
|
dom_token.setAttribute(u8"row", token->token()->row());
|
|
dom_token.setAttribute(u8"col", token->token()->column());
|
|
}
|
|
}
|
|
|
|
printer::AstGenerate::AstGenerate()
|
|
{
|
|
auto procs = doc.createProcessingInstruction("xml", "version='1.0' encoding='utf-8'");
|
|
doc.appendChild(procs);
|
|
|
|
}
|
|
|
|
QString printer::AstGenerate::content() const
|
|
{
|
|
return doc.toString(2);
|
|
}
|
|
|
|
VisitMode printer::AstGenerate::mode() const {
|
|
return VisitMode::FirstParent;
|
|
}
|
|
|
|
bool printer::AstGenerate::visit(std::shared_ptr<const ast_gen::ElementAccess> syntax_element) {
|
|
switch ((NovelNode)syntax_element->element()->typeMark()) {
|
|
case NovelNode::GlobalElement:{
|
|
auto body = doc.createElement(u8"ast");
|
|
doc.appendChild(body);
|
|
element_stack.append(body);
|
|
}break;
|
|
case NovelNode::Document: break;
|
|
case NovelNode::StoryDefine:{
|
|
while (element_stack.last().tagName() != u8"ast") {
|
|
element_stack.takeLast();
|
|
}
|
|
|
|
auto current_ast = element_stack.last();
|
|
auto story_node = std::dynamic_pointer_cast<const example_novel::StoryDefine>(syntax_element->element());
|
|
auto dom_story = doc.createElement(u8"story");
|
|
current_ast.appendChild(dom_story);
|
|
element_stack.append(dom_story);
|
|
|
|
dom_story.setAttribute(u8"name", story_node->name());
|
|
dom_story.setAttribute(u8"file-path", story_node->filePath());
|
|
dom_story.setAttribute(u8"sort", story_node->sort());
|
|
|
|
append_tokens(dom_story, story_node);
|
|
}break;
|
|
case NovelNode::FragmentDefine: {
|
|
while (element_stack.last().tagName() != u8"story") {
|
|
element_stack.takeLast();
|
|
}
|
|
|
|
auto current_story = element_stack.last();
|
|
auto fragment_node = std::dynamic_pointer_cast<const example_novel::FragmentDefine>(syntax_element->element());
|
|
auto dom_fragment = doc.createElement(u8"fragment");
|
|
current_story.appendChild(dom_fragment);
|
|
element_stack.append(dom_fragment);
|
|
|
|
dom_fragment.setAttribute(u8"name", fragment_node->name());
|
|
dom_fragment.setAttribute(u8"file-path", fragment_node->filePath());
|
|
|
|
append_tokens(dom_fragment, fragment_node);
|
|
}break;
|
|
case NovelNode::TextSection:{
|
|
auto current_text = element_stack.last();
|
|
auto text_node = std::dynamic_pointer_cast<const example_novel::TextSection>(syntax_element->element());
|
|
auto dom_text = doc.createElement(u8"text-section");
|
|
current_text.appendChild(dom_text);
|
|
|
|
dom_text.setAttribute(u8"text", text_node->content());
|
|
dom_text.setAttribute(u8"file-path", text_node->filePath());
|
|
|
|
append_tokens(dom_text, text_node);
|
|
}break;
|
|
case NovelNode::FragmentRefer:{
|
|
while (element_stack.last().tagName() != u8"article" && element_stack.last().tagName() != u8"story") {
|
|
element_stack.takeLast();
|
|
}
|
|
|
|
auto current_pnode = element_stack.last();
|
|
auto refer_node = std::dynamic_pointer_cast<const example_novel::FragmentRefers>(syntax_element->element());
|
|
auto dom_refer = doc.createElement(u8"refer");
|
|
element_stack.append(dom_refer);
|
|
current_pnode.appendChild(dom_refer);
|
|
|
|
dom_refer.setAttribute(u8"story", refer_node->storyRefer());
|
|
dom_refer.setAttribute(u8"fragment", refer_node->fragmentRefer());
|
|
dom_refer.setAttribute(u8"file-path", refer_node->filePath());
|
|
|
|
append_tokens(dom_refer, refer_node);
|
|
}break;
|
|
case NovelNode::VolumeDefine:{
|
|
while (element_stack.last().tagName() != u8"ast") {
|
|
element_stack.takeLast();
|
|
}
|
|
|
|
auto current_ast = element_stack.last();
|
|
auto volume_node = std::dynamic_pointer_cast<const example_novel::VolumeDefine>(syntax_element->element());
|
|
auto dom_volume = doc.createElement(u8"volume");
|
|
current_ast.appendChild(dom_volume);
|
|
element_stack.append(dom_volume);
|
|
|
|
dom_volume.setAttribute(u8"name", volume_node->name());
|
|
dom_volume.setAttribute(u8"file-path", volume_node->filePath());
|
|
|
|
append_tokens(dom_volume, volume_node);
|
|
}break;
|
|
case NovelNode::ArticleDefine:{
|
|
while (element_stack.last().tagName() != u8"volume") {
|
|
element_stack.takeLast();
|
|
}
|
|
|
|
auto current_volume = element_stack.last();
|
|
auto article_node = std::dynamic_pointer_cast<const example_novel::ArticleDefine>(syntax_element->element());
|
|
auto dom_article = doc.createElement(u8"article");
|
|
current_volume.appendChild(dom_article);
|
|
element_stack.append(dom_article);
|
|
|
|
dom_article.setAttribute(u8"name", article_node->name());
|
|
dom_article.setAttribute(u8"file-path", article_node->filePath());
|
|
|
|
append_tokens(dom_article, article_node);
|
|
}break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|