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