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);
+ };
}