From 647f41aa80524fa6f96e8a06bb387ef9db79678b Mon Sep 17 00:00:00 2001
From: codeboss <2422523675@qq.com>
Date: Sat, 1 Mar 2025 21:15:15 +0800
Subject: [PATCH] fix-ast-struct
---
WsNovelParser/WsNovelParser.vcxproj.user | 2 +-
WsNovelParser/htmlprint.cpp | 80 +++++++++++++-----------
WsNovelParser/htmlprint.h | 2 +-
libSyntax/ast_novel.cpp | 4 ++
libSyntax/ast_novel.h | 10 +++
5 files changed, 60 insertions(+), 38 deletions(-)
diff --git a/WsNovelParser/WsNovelParser.vcxproj.user b/WsNovelParser/WsNovelParser.vcxproj.user
index aa22114..a8dea2e 100644
--- a/WsNovelParser/WsNovelParser.vcxproj.user
+++ b/WsNovelParser/WsNovelParser.vcxproj.user
@@ -3,7 +3,7 @@
$(SolutionDir)$(Platform)\$(Configuration)\
WindowsLocalDebugger
- --path "D:\Projects\Cpp\WsNovelParser\x64\test_file" --dest E:\
+ --path "D:\CustomNovels\科学+修仙+创造世界X" --dest E:\
--path "D:\Projects\Cpp\WsNovelParser\x64\test_file" --dest E:\
diff --git a/WsNovelParser/htmlprint.cpp b/WsNovelParser/htmlprint.cpp
index 5e264e4..0c6b19c 100644
--- a/WsNovelParser/htmlprint.cpp
+++ b/WsNovelParser/htmlprint.cpp
@@ -40,6 +40,7 @@ VisitMode printer::AstGenerate::mode() const {
#include
bool printer::AstGenerate::visit(std::shared_ptr syntax_element) {
+ auto depth = syntax_element->element()->depth();
switch ((NovelNode) syntax_element->element()->typeMark()) {
case NovelNode::GlobalElement:
{
@@ -47,20 +48,21 @@ bool printer::AstGenerate::visit(std::shared_ptr s
doc.appendChild(body);
body.setAttribute("time", QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"));
body.setAttribute("dir_src", src_root.absolutePath());
- element_stack.append(body);
+ element_stack.append(std::make_pair(depth, body));
}break;
case NovelNode::Document: break;
case NovelNode::StoryDefine:
{
- while (element_stack.last().tagName() != "ast") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep){ return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_ast = element_stack.last();
auto story_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_story = doc.createElement("story");
- current_ast.appendChild(dom_story);
- element_stack.append(dom_story);
+ current_ast.second.appendChild(dom_story);
+ element_stack.append(std::make_pair(depth, dom_story));
dom_story.setAttribute("name", story_node->name());
dom_story.setAttribute("address", (qulonglong) story_node.get());
@@ -71,30 +73,32 @@ bool printer::AstGenerate::visit(std::shared_ptr s
}break;
case NovelNode::FragmentSlice:
{
- while (element_stack.last().tagName() != "story") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_story = element_stack.last();
auto slice_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_slice = doc.createElement("slice");
- current_story.appendChild(dom_slice);
- element_stack.append(dom_slice);
+ current_story.second.appendChild(dom_slice);
+ element_stack.append(std::make_pair(depth, dom_slice));
dom_slice.setAttribute("name", slice_node->name());
dom_slice.setAttribute("address", (qulonglong) slice_node.get());
}break;
case NovelNode::PointDefines:
{
- while (element_stack.last().tagName() != "slice") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_slice = element_stack.last();
auto point_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_point = doc.createElement("point");
- current_slice.appendChild(dom_point);
- element_stack.append(dom_point);
+ current_slice.second.appendChild(dom_point);
+ element_stack.append(std::make_pair(depth, dom_point));
dom_point.setAttribute("name", point_node->name());
dom_point.setAttribute("address", (qulonglong) point_node.get());
@@ -104,14 +108,15 @@ bool printer::AstGenerate::visit(std::shared_ptr s
}break;
case NovelNode::TextSection:
{
- while (element_stack.last().tagName() == "text") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_pnode = element_stack.last();
auto text_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_text = doc.createElement("text-section");
- current_pnode.appendChild(dom_text);
+ current_pnode.second.appendChild(dom_text);
dom_text.setAttribute("text", text_node->content());
dom_text.setAttribute("file-path", src_root.relativeFilePath(text_node->filePath()));
@@ -120,15 +125,16 @@ bool printer::AstGenerate::visit(std::shared_ptr s
}break;
case NovelNode::PointRefers:
{
- while (element_stack.last().tagName() != "article" && element_stack.last().tagName() != "slice") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_pnode = element_stack.last();
auto refer_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_refer = doc.createElement("refer");
- element_stack.append(dom_refer);
- current_pnode.appendChild(dom_refer);
+ current_pnode.second.appendChild(dom_refer);
+ element_stack.append(std::make_pair(depth, dom_refer));
dom_refer.setAttribute("story", refer_node->storyRefer());
dom_refer.setAttribute("slice", refer_node->sliceRefer());
@@ -139,15 +145,16 @@ bool printer::AstGenerate::visit(std::shared_ptr s
}break;
case NovelNode::VolumeDefine:
{
- while (element_stack.last().tagName() != "ast") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_ast = element_stack.last();
auto volume_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_volume = doc.createElement("volume");
- current_ast.appendChild(dom_volume);
- element_stack.append(dom_volume);
+ current_ast.second.appendChild(dom_volume);
+ element_stack.append(std::make_pair(depth, dom_volume));
dom_volume.setAttribute("name", volume_node->name());
dom_volume.setAttribute("address", (qulonglong) volume_node.get());
@@ -157,15 +164,16 @@ bool printer::AstGenerate::visit(std::shared_ptr s
}break;
case NovelNode::ArticleDefine:
{
- while (element_stack.last().tagName() != "volume") {
- element_stack.takeLast();
- }
+ decltype(this->element_stack) temp_stack;
+ std::copy_if(element_stack.begin(), element_stack.end(),
+ std::back_inserter(temp_stack), [=](std::pair ep) { return ep.first < depth; });
+ this->element_stack = temp_stack;
auto current_volume = element_stack.last();
auto article_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_article = doc.createElement("article");
- current_volume.appendChild(dom_article);
- element_stack.append(dom_article);
+ current_volume.second.appendChild(dom_article);
+ element_stack.append(std::make_pair(depth, dom_article));
dom_article.setAttribute("name", article_node->name());
dom_article.setAttribute("address", (qulonglong) article_node.get());
@@ -178,7 +186,7 @@ bool printer::AstGenerate::visit(std::shared_ptr s
auto ast_element = element_stack.first();
auto rank_node = std::dynamic_pointer_cast(syntax_element->element());
auto dom_rank = doc.createElement("rank");
- ast_element.appendChild(dom_rank);
+ ast_element.second.appendChild(dom_rank);
dom_rank.setAttribute("rank", rank_node->rankNumber());
dom_rank.setAttribute("doc-path", src_root.relativeFilePath(rank_node->filePath()));
diff --git a/WsNovelParser/htmlprint.h b/WsNovelParser/htmlprint.h
index 6bcc4e9..30a1bf6 100644
--- a/WsNovelParser/htmlprint.h
+++ b/WsNovelParser/htmlprint.h
@@ -15,7 +15,7 @@ namespace printer {
private:
QDir src_root;
QDomDocument doc;
- QList element_stack;
+ QList> element_stack;
void append_tokens(QDomElement _elm, std::shared_ptr inst);
diff --git a/libSyntax/ast_novel.cpp b/libSyntax/ast_novel.cpp
index c21f901..d1c1662 100644
--- a/libSyntax/ast_novel.cpp
+++ b/libSyntax/ast_novel.cpp
@@ -188,6 +188,10 @@ QString NGlobalElement::signature() const {
return "::program";
}
+int example_novel::NGlobalElement::depth() const {
+ return 1;
+}
+
std::weak_ptr NGlobalElement::parent() const {
return std::weak_ptr();
}
diff --git a/libSyntax/ast_novel.h b/libSyntax/ast_novel.h
index b65c9c8..88111ab 100644
--- a/libSyntax/ast_novel.h
+++ b/libSyntax/ast_novel.h
@@ -46,6 +46,12 @@ namespace ast_gen {
*/
virtual QString signature() const = 0;
+ /**
+ * @brief 获取元素在Ast深度
+ * @return depth
+ */
+ virtual int depth() const = 0;
+
/**
* @brief 获取父元素
* @return 未设置parent,返回nullptr
@@ -149,6 +155,9 @@ namespace example_novel {
QString path() const override {
return ExprInstance::filePath();
}
+ int depth() const {
+ return parent().lock()->depth() + 1;
+ }
virtual std::weak_ptr parent() const override {
return std::dynamic_pointer_cast(ExprInstance::parentExpr().lock());
}
@@ -339,6 +348,7 @@ namespace example_novel {
bool isAnonymous() const override;
QString path() const override;
QString signature() const override;
+ int depth() const override;
std::weak_ptr parent() const override;
QList> selfTokens() const override;
};