#include "astprint.h" #include #include using namespace example_novel; using namespace printer; using namespace lib_parse; #include #include #include void printer::AstGenerate::append_tokens(QDomElement _elm, std::shared_ptr inst) { auto dom_tokens = doc.createElement("tokens"); _elm.appendChild(dom_tokens); for (auto& token : inst->selfTokens()) { auto dom_token = doc.createElement("token"); dom_tokens.appendChild(dom_token); dom_token.setAttribute("text", token->token()->content()); dom_token.setAttribute("row", token->token()->row()); dom_token.setAttribute("col", token->token()->column()); } } printer::AstGenerate::AstGenerate(const QDir& src_rt) : src_root(src_rt) { auto procs = doc.createProcessingInstruction("xml", "version='1.0' encoding='utf-8'"); doc.appendChild(procs); } QString printer::AstGenerate::content() const { return doc.toString(2); } VisitMode printer::AstGenerate::mode() const { return VisitMode::FirstParent; } #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: { auto body = doc.createElement("ast"); doc.appendChild(body); body.setAttribute("time", QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")); body.setAttribute("dir_src", src_root.absolutePath()); element_stack.append(std::make_pair(depth, body)); }break; case NovelNode::Document: break; case NovelNode::StoryDefine: { 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.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()); dom_story.setAttribute("file-path", src_root.relativeFilePath(story_node->filePath())); dom_story.setAttribute("sort", story_node->sort()); append_tokens(dom_story, story_node); }break; case NovelNode::FragmentSlice: { 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.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()); dom_slice.setAttribute("file-path", src_root.relativeFilePath(slice_node->filePath())); append_tokens(dom_slice, slice_node); }break; case NovelNode::TextSection: { 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.second.appendChild(dom_text); dom_text.setAttribute("text", text_node->content()); dom_text.setAttribute("file-path", src_root.relativeFilePath(text_node->filePath())); append_tokens(dom_text, text_node); }break; case NovelNode::FragmentRefers: { 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"); 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()); dom_refer.setAttribute("file-path", src_root.relativeFilePath(refer_node->filePath())); append_tokens(dom_refer, refer_node); }break; case NovelNode::VolumeDefine: { 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.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()); dom_volume.setAttribute("file-path", src_root.relativeFilePath(volume_node->filePath())); append_tokens(dom_volume, volume_node); }break; case NovelNode::ArticleDefine: { 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.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()); dom_article.setAttribute("file-path", src_root.relativeFilePath(article_node->filePath())); append_tokens(dom_article, article_node); }break; case NovelNode::RankDeclaration: { auto ast_element = element_stack.first(); auto rank_node = std::dynamic_pointer_cast(syntax_element->element()); auto dom_rank = doc.createElement("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())); append_tokens(dom_rank, rank_node); }break; default: break; } return true; }