WsParser_VS/WsNovelParser/main.cpp

281 lines
10 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 <QtCore/QCoreApplication>
#include <QCoreApplication>
#include <QDebug>
#include <QFileInfoList>
#include <ast_gen.h>
#include <ast_novel.h>
#include <libtoken.h>
#include <syntax_novel.h>
#include <tokens_novel.h>
#include <QDir>
#include <QTextStream>
#include <iostream>
#include <QTime>
#include <argsparser.h>
#include "novelparser.h"
#include "htmlprint.h"
using namespace example_novel;
/*
* nsc --help
* nsc -[pw] --path path-to-dir [--out path-to-dir]
* opts:
* p print-struct 输出整体结构
* w print-web 基础的web页面输出格式
*/
int main(int argc, char* argv[]) {
QCoreApplication a(argc, argv);
args_parse::ArgsParser args_parser;
QList<std::shared_ptr<args_parse::ArgvPack>> args_mode;
args_mode << std::make_shared<args_parse::IndexParam>(u8"程序名称");
args_mode << std::make_shared<args_parse::FloatOption>(u8"--help", u8"帮助");
args_parser.loadMode(0x000Au, args_mode);
args_mode.clear();
args_mode << std::make_shared<args_parse::IndexParam>(u8"程序名称");
args_mode << std::make_shared<args_parse::FloatArgvPack>(u8"--path", u8"源代码目录");
args_mode << std::make_shared<args_parse::FloatArgvPack>(u8"--dest", u8"生成目录");
args_mode << std::make_shared<args_parse::FloatOption>(u8"--html", u8"生成html文件格式取代AST", true);
args_parser.loadMode(0x000Bu, args_mode);
auto parse_result = args_parser.parse(argc, argv);
switch (std::get<0>(parse_result)) {
case 0xBu: {
auto args = std::get<1>(parse_result);
auto src_dir = std::dynamic_pointer_cast<args_parse::FloatArgvPack>(args_mode[1]);
auto dst_dir = std::dynamic_pointer_cast<args_parse::FloatArgvPack>(args_mode[2]);
auto html_opt = std::dynamic_pointer_cast<args_parse::FloatOption>(args_mode[3]);
auto source_dir = QDir(src_dir->value());
if (!source_dir.exists()) {
std::cout << "%编译指定的源代码目录不存在!" << std::endl;
exit(0);
}
auto destination_dir = QDir::current();
auto target_output = dst_dir->value();
if (!target_output.isEmpty() && QDir(target_output).exists()) {
destination_dir = QDir(target_output);
}
else {
std::cout << "%编译指定的生成目录不存在,重置为:" << destination_dir.absolutePath().toLocal8Bit().data() << std::endl;
}
auto files = source_dir.entryInfoList(QStringList() << "*.story");
std::shared_ptr<const ast_gen::ElementAccess> access_ptr = nullptr;
if (files.size()) {
try {
auto parser = std::make_shared<NovelParser>();
auto docs = parser->parse(files);
auto errors_list = parser->parserContext()->errors();
if (errors_list.size()) {
for (auto& err : errors_list) {
qDebug().noquote() << err;
}
exit(0);
}
access_ptr = parser->validsApply(docs);
}
catch (lib_syntax::SyntaxException* e) {
qDebug().noquote() << e->message();
delete e;
exit(0);
}
catch (lib_parse::CheckException* e) {
qDebug().noquote() << e->message();
delete e;
exit(0);
}
}
if (html_opt->value().toInt() == 1 && access_ptr) {
QTime time_stamp = QTime::currentTime();
printer::tools_printer tool;
tool.build_fragments(access_ptr);
tool.build_refers_network(access_ptr);
tool.fragments_anchors_define(tool.fragment_defines.values(), destination_dir);
tool.storylines_anchors_define(tool.storyline_defines.values(), destination_dir);
tool.volumes_anchors_define(tool.volume_defines.values(), destination_dir);
std::function<void(std::shared_ptr<const printer::Access>)> html_output =
[](std::shared_ptr<const printer::Access> inst) {
auto target_path = inst->pageRefers();
QFile tfile(target_path);
if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QDomDocument doc_inst(QDomImplementation().createDocumentType(u8"html", QString(), QString()));
auto html = doc_inst.createElement(u8"html");
doc_inst.appendChild(html);
auto body = doc_inst.createElement(u8"body");
html.appendChild(body);
inst->buildPageHTML(body);
QTextStream tout(&tfile);
doc_inst.save(tout, 2);
tout.flush();
}
};
for (auto& node : tool.fragment_defines)
html_output(node);
for (auto& node : tool.storyline_defines)
html_output(node);
for (auto& node : tool.volume_defines)
html_output(node);
QDir::setCurrent(destination_dir.canonicalPath());
auto dot_src = tool.storylines_paint(tool.storyline_defines.values());
QFile dot_file(QDir::current().filePath(u8"relates.dot"));
if (dot_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream txt(&dot_file);
txt.setCodec(u8"UTF-8");
txt << dot_src;
txt.flush();
}
system("dot -Tsvg relates.dot -o relates.svg");
auto vols_src = tool.volumes_paint(tool.volume_defines.values(), tool.storyline_defines.values());
QFile vols_file(QDir::current().filePath(u8"volumes_group.dot"));
if (vols_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream txt(&vols_file);
txt.setCodec(u8"UTF-8");
txt << vols_src;
txt.flush();
}
system("fdp -Tsvg volumes_group.dot -o volumes_group.svg");
{
QFile tfile("./index.html");
if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QDomDocument doc_inst(QDomImplementation().createDocumentType(u8"html", QString(), QString()));
auto html = doc_inst.createElement(u8"html");
doc_inst.appendChild(html);
auto body = doc_inst.createElement(u8"body");
html.appendChild(body);
auto dom_storyline = doc_inst.createElement("div");
auto dom_storyline_title = doc_inst.createElement("h2");
dom_storyline_title.appendChild(doc_inst.createTextNode(u8"故事脉络"));
dom_storyline.appendChild(dom_storyline_title);
body.appendChild(dom_storyline);
auto lines = tool.storyline_defines.values();
std::sort(lines.begin(), lines.end(), [](std::shared_ptr<printer::StoryLine> a, std::shared_ptr<printer::StoryLine> b)->bool {
auto a_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(a->accessPeers()->element());
auto b_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(b->accessPeers()->element());
return a_elm->sort() < b_elm->sort();
});
for (auto& inst_line : lines) {
auto dom_line = doc_inst.createElement("p");
dom_storyline.appendChild(dom_line);
auto line_href = doc_inst.createElement("a");
line_href.setAttribute(u8"href", u8"file:///" + inst_line->pageRefers());
auto a_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(inst_line->accessPeers()->element());
line_href.appendChild(doc_inst.createTextNode(QString(u8"%1.%2").arg(a_elm->sort()).arg(a_elm->signature())));
dom_line.appendChild(line_href);
}
auto dom_volume = doc_inst.createElement("div");
auto dom_volume_title = doc_inst.createElement("h2");
dom_volume_title.appendChild(doc_inst.createTextNode(u8"分卷内容"));
dom_volume.appendChild(dom_volume_title);
body.appendChild(dom_volume);
for (auto& inst_volume : tool.volume_defines) {
auto dom_volume_ref = doc_inst.createElement("p");
dom_volume.appendChild(dom_volume_ref);
auto volume_href = doc_inst.createElement("a");
volume_href.setAttribute(u8"href", u8"file:///" + inst_volume->pageRefers());
volume_href.appendChild(doc_inst.createTextNode(inst_volume->accessPeers()->element()->signature()));
dom_volume_ref.appendChild(volume_href);
}
auto dom_fragment = doc_inst.createElement("div");
auto dom_fragment_title = doc_inst.createElement("h2");
dom_fragment_title.appendChild(doc_inst.createTextNode(u8"情节集合"));
dom_fragment.appendChild(dom_fragment_title);
body.appendChild(dom_fragment);
auto table_cube = doc_inst.createElement(u8"table");
dom_fragment.appendChild(table_cube);
int row_ctrl = 0;
QDomElement elm_row;
for (auto& inst_frag : tool.fragment_defines) {
if (row_ctrl++ % 4 == 0) {
elm_row = doc_inst.createElement(u8"tr");
table_cube.appendChild(elm_row);
}
auto dom_fragment_ref = doc_inst.createElement("td");
elm_row.appendChild(dom_fragment_ref);
auto frag_href = doc_inst.createElement("a");
frag_href.setAttribute(u8"href", u8"file:///" + inst_frag->pageRefers());
frag_href.appendChild(doc_inst.createTextNode(inst_frag->accessPeers()->element()->signature()));
dom_fragment_ref.appendChild(frag_href);
}
auto dom_relate = doc_inst.createElement(u8"div");
auto dom_relate_title = doc_inst.createElement(u8"h2");
dom_relate_title.appendChild(doc_inst.createTextNode(u8"联系图"));
dom_relate.appendChild(dom_relate_title);
body.appendChild(dom_relate);
auto img = doc_inst.createElement(u8"img");
img.setAttribute(u8"src", u8"file:///" + QDir::current().filePath(u8"relates.svg"));
dom_relate.appendChild(img);
dom_relate.appendChild(doc_inst.createElement("br"));
img = doc_inst.createElement(u8"img");
img.setAttribute(u8"src", u8"file:///" + QDir::current().filePath(u8"volumes_group.svg"));
dom_relate.appendChild(img);
QTextStream tout(&tfile);
doc_inst.save(tout, 2);
tout.flush();
}
}
auto current_stamp = QTime::currentTime();
qDebug().noquote() << QString(u8"%html构建消耗时间%1 ms。").arg(time_stamp.msecsTo(current_stamp));
qDebug().noquote() << u8"%编译成功:" << destination_dir.absoluteFilePath(u8"index.html");
}
else if (access_ptr) {
QTime time_stamp = QTime::currentTime();
lib_parse::VisitorControl control;
auto visitor = std::make_shared<printer::AstGenerate>();
control.visitWith(access_ptr, visitor);;
auto dom_result = visitor->content();
QFile file(destination_dir.absoluteFilePath(u8"storyline.xast"));
if (file.open(QIODevice::Text | QIODevice::WriteOnly)) {
QTextStream tout(&file);
tout.setCodec("UTF-8");
tout << dom_result;
tout.flush();
}
auto current_stamp = QTime::currentTime();
qDebug().noquote() << QString(u8"%AST构建消耗时间%1 ms。").arg(time_stamp.msecsTo(current_stamp));
qDebug().noquote() << QString(u8"%编译成功:%1。").arg(QFileInfo(file).absoluteFilePath());
}
}break;
case 0xAu:
default: {
std::cout << "nsc(WsNovelStoryCompiler故事线编译器)" << std::endl;
std::cout << "版本V1.0.0" << std::endl;
std::cout << "nsc --path path-to-dir --dest path-to-output [--html]" << std::endl;
}break;
}
//return a.exec();
return 0;
}