diff --git a/WsNovelParser/WsNovelParser.vcxproj.user b/WsNovelParser/WsNovelParser.vcxproj.user index 7526613..24aef19 100644 --- a/WsNovelParser/WsNovelParser.vcxproj.user +++ b/WsNovelParser/WsNovelParser.vcxproj.user @@ -3,7 +3,7 @@ $(SolutionDir)$(Platform)\$(Configuration)\ WindowsLocalDebugger - --path "D:\手作小说\科学+修仙+创造世界" --html --dest E:\ + --path "D:\手作小说\科学+修仙+创造世界" --dest E:\ --path "D:\手作小说\科学+修仙+创造世界" diff --git a/WsNovelParser/htmlprint.cpp b/WsNovelParser/htmlprint.cpp index 6e6b86b..2210cc4 100644 --- a/WsNovelParser/htmlprint.cpp +++ b/WsNovelParser/htmlprint.cpp @@ -4,6 +4,7 @@ using namespace example_novel; using namespace printer; +using namespace lib_parse; Access::Access(std::shared_ptr handle) :access_handle(handle) {} @@ -532,3 +533,141 @@ QString printer::tools_printer::volumes_paint(const QList 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'"); + 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 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(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(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(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(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(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(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; +} diff --git a/WsNovelParser/htmlprint.h b/WsNovelParser/htmlprint.h index 921f453..9a00c9d 100644 --- a/WsNovelParser/htmlprint.h +++ b/WsNovelParser/htmlprint.h @@ -157,4 +157,21 @@ namespace printer { QString storylines_paint(const QList> &lines); QString volumes_paint(const QList> &vols, const QList> &lines); }; + + class AstGenerate : public lib_parse::TreeVisitor { + private: + QDomDocument doc; + QList element_stack; + + void append_tokens(QDomElement _elm, std::shared_ptr inst); + + public: + AstGenerate(); + + QString content() const; + + // ͨ TreeVisitor ̳ + lib_parse::VisitMode mode() const override; + bool visit(std::shared_ptr syntax_element) override; + }; } \ No newline at end of file diff --git a/WsNovelParser/main.cpp b/WsNovelParser/main.cpp index 30c54e2..16ccb58 100644 --- a/WsNovelParser/main.cpp +++ b/WsNovelParser/main.cpp @@ -54,7 +54,7 @@ int main(int argc, char* argv[]) { auto args = std::get<1>(parse_result); auto src_dir = std::dynamic_pointer_cast(args_mode[1]); auto dst_dir = std::dynamic_pointer_cast(args_mode[2]); - auto fmt_opt = std::dynamic_pointer_cast(args_mode[3]); + auto html_opt = std::dynamic_pointer_cast(args_mode[3]); auto source_dir = QDir(src_dir->value()); if (!source_dir.exists()) { @@ -66,7 +66,7 @@ int main(int argc, char* argv[]) { if (!target_output.isEmpty() && QDir(target_output).exists()) { destination_dir = QDir(target_output); } - else{ + else { std::cout << "ָĿ¼ڣΪ" << destination_dir.absolutePath().toLocal8Bit().data() << std::endl; } @@ -76,6 +76,7 @@ int main(int argc, char* argv[]) { try { auto parser = std::make_shared(); access_ptr = parser->parse(files); + qDebug() << u8"%ɹ" << destination_dir.absoluteFilePath(u8"index.html"); } catch (lib_syntax::SyntaxException* e) { qDebug().noquote() << e->message(); @@ -89,7 +90,7 @@ int main(int argc, char* argv[]) { } } - if (fmt_opt->value().toInt() == 1 && access_ptr) { + if (html_opt->value().toInt() == 1 && access_ptr) { QTime time_stamp = QTime::currentTime(); printer::tools_printer tool; tool.build_fragments(access_ptr); @@ -246,8 +247,13 @@ int main(int argc, char* argv[]) { auto current_stamp = QTime::currentTime(); qDebug() << QString(u8"htmlʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)); } - - qDebug() << u8"ɹ" << destination_dir.absoluteFilePath(u8"index.html"); + else if (access_ptr) { + lib_parse::VisitorControl control; + auto visitor = std::make_shared(); + control.visitWith(access_ptr, visitor);; + auto dom_result = visitor->content(); + qDebug().noquote() << dom_result; + } }break; default: break; diff --git a/WsNovelParser/novelparser.cpp b/WsNovelParser/novelparser.cpp index a1f2fdf..466dd53 100644 --- a/WsNovelParser/novelparser.cpp +++ b/WsNovelParser/novelparser.cpp @@ -42,7 +42,7 @@ std::shared_ptr NovelParser::parse(const QFileInfo forst_root.append(std::get<0>(exprs_result)); } auto current_stamp = QTime::currentTime(); - qDebug() << QString(u8"ʷ+﷨ʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)); + qDebug().noquote() << QString(u8"%ʷ+﷨ʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)); time_stamp = QTime::currentTime(); QList> docs_node; @@ -55,7 +55,7 @@ std::shared_ptr NovelParser::parse(const QFileInfo auto x_root = NovalSyntax::tidy(context, docs_node); auto novel_accesstree = std::make_shared(x_root); current_stamp = QTime::currentTime(); - qDebug() << QString(u8"ṹؽʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)); + qDebug().noquote() << QString(u8"%ṹؽʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)); return analyzer_ref->validCheckWith(novel_accesstree); } diff --git a/libParse/libparse.cpp b/libParse/libparse.cpp index a60d731..16a26ce 100644 --- a/libParse/libparse.cpp +++ b/libParse/libparse.cpp @@ -1,6 +1,7 @@ #include "libparse.h" using namespace lib_parse; +using namespace ast_gen; CheckException::CheckException(const QString& msg) : msg_store(msg) {} @@ -10,12 +11,41 @@ Analyzer::Analyzer(const QList >& providers #include #include -std::shared_ptr Analyzer::validCheckWith(std::shared_ptr root) const { +std::shared_ptr Analyzer::validCheckWith(std::shared_ptr root) const { for (auto& v : check_providers){ QTime time_stamp = QTime::currentTime(); v->validCheck(root); auto current_stamp = QTime::currentTime(); - qDebug() << QString(u8"У%2 ʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)).arg(v->name()); + qDebug().noquote() << QString(u8"%У%2 ʱ䣺%1 ms").arg(time_stamp.msecsTo(current_stamp)).arg(v->name()); } return root; } + +bool VisitorControl::visitWith(std::shared_ptr syntax_elm, std::shared_ptr visitor) { + switch (visitor->mode()) { + case VisitMode::FirstParent: { + if (visitor->visit(syntax_elm)) { + for (auto& e : syntax_elm->children()) { + visitWith(e, visitor); + } + } + return true; + }break; + case VisitMode::LastParent:{ + bool exc_continue = true; + for (auto& e : syntax_elm->children()) { + if(!visitWith(e, visitor)){ + exc_continue = false; + break; + } + } + + if(exc_continue) + visitor->visit(syntax_elm); + + return exc_continue; + }break; + default: + break; + } +} diff --git a/libParse/libparse.h b/libParse/libparse.h index 73beeca..3b68fdb 100644 --- a/libParse/libparse.h +++ b/libParse/libparse.h @@ -42,4 +42,32 @@ namespace lib_parse { std::shared_ptr validCheckWith(std::shared_ptr root) const; }; + + enum class VisitMode { + FirstParent, // + LastParent, // + }; + + class TreeVisitor { + public: + /** + * ȡıģʽ. + * + * \return + */ + virtual VisitMode mode() const = 0; + + /** + * ﷨ִнڵ. + * + * \param syntax_element ǰʽڵ + * \return Ƿִб + */ + virtual bool visit(std::shared_ptr syntax_element) = 0; + }; + + class LIBPARSE_EXPORT VisitorControl { + public: + bool visitWith(std::shared_ptr syntax_elm, std::shared_ptr visitor); + }; }