diff --git a/AstConv/AstImport.fs b/AstConv/AstImport.fs index fc80e6c..88328fc 100644 --- a/AstConv/AstImport.fs +++ b/AstConv/AstImport.fs @@ -13,6 +13,7 @@ open System.Linq default this.members(): AstObject list = [] end + /// 父子节点map转换 let rec branch_map_conv (pnode: AstObject, childs: AstObject list) = match childs with | [] -> [] @@ -20,6 +21,7 @@ open System.Linq let head = childs.Head (head.address(), (head, pnode))::branch_map_conv(pnode, childs.Tail)@branch_map_conv(head, head.members()) + /// 节点深度计算 let rec depth_seek(branchs: (string*(AstObject*AstObject))list, node: AstObject): int = let prev_nodes = branchs |> List.filter(fun (key, _) -> key.Equals(node.address())) match prev_nodes.Length with @@ -85,39 +87,50 @@ open System.Linq end /// 定义节点 - type PointDef(bind: XmlElement, texts: TextItem list) = + type PointChildType = |Text of TextItem |Refer of PointRef + type PointDef(bind: XmlElement, objs: AstObject list) = class inherit AstObject() new(bind: XmlElement) = PointDef(bind, []) - member this.name() = - bind.GetAttribute "name" - member this.appendChild(t: TextItem) = - PointDef(bind, texts@[t]) - member this.children() = - texts + member this.name() = bind.GetAttribute "name" + + member this.appendChild(o: PointChildType) = + match o with + |Text t -> PointDef(bind, objs@[t]) + |Refer r -> PointDef(bind, objs@[r]) + + member this.children() = objs - override this.members(): AstObject list = - texts |> List.map (fun it->it :> AstObject) + override this.members(): AstObject list = objs - static member GenerateFromChildSibling(child: XmlNode): TextItem list = + static member GenerateFromChildSibling(child: XmlNode): PointChildType list = match child with | null -> [] | _ -> - match TextItem.GenerateText(child) with - | Some text -> text::PointDef.GenerateFromChildSibling(child.NextSibling) - | None -> PointDef.GenerateFromChildSibling(child.NextSibling) + let h = match child.Name with + | "text-section" -> Some(Text(TextItem.GenerateText(child).Value)) + | "refer" -> Some(Refer(PointRef.GeneratePointRef(child).Value)) + | _ -> None + match h with + | Some childx -> childx::PointDef.GenerateFromChildSibling(child.NextSibling) + | None -> PointDef.GenerateFromChildSibling(child.NextSibling) static member GeneratePointDef(def_opt: XmlNode) : Option = match def_opt with | :? XmlElement as defo when defo.Name.Equals "point" -> - let text_objs = PointDef.GenerateFromChildSibling(defo.FirstChild) - Some(PointDef(defo, text_objs)) + let child_objs = PointDef.GenerateFromChildSibling(defo.FirstChild) + let objs = child_objs |> List.map ( + fun o-> match o with + |Refer refs -> refs :> AstObject + |Text text -> text :> AstObject + ) + Some(PointDef(defo, objs)) | _ -> None end - type SliceChildType = |Text of TextItem |Define of PointDef |Refer of PointRef + type SliceChildType = |Text of TextItem |Define of PointDef /// 情节节点 type SliceDef(bind: XmlElement, objs: AstObject list) = class @@ -130,7 +143,6 @@ open System.Linq match o with | Text t -> SliceDef(bind, objs@[t]) | Define d -> SliceDef(bind, objs@[d]) - | Refer r -> SliceDef(bind, objs@[r]) member this.children() = objs override this.members(): AstObject list = objs @@ -141,7 +153,6 @@ open System.Linq | _ -> let h = match child.Name with | "text-section" -> Some(Text(TextItem.GenerateText(child).Value)) - | "refer" -> Some(Refer(PointRef.GeneratePointRef(child).Value)) | "point" -> Some(Define(PointDef.GeneratePointDef(child).Value)) | _ -> None @@ -156,7 +167,6 @@ open System.Linq let objs = mbrs |> List.map ( fun o-> match o with |Define defs -> defs :> AstObject - |Refer refs -> refs :> AstObject |Text text -> text :> AstObject ) Some(SliceDef(slice, objs)) diff --git a/AstConv/HtmlStruct.fs b/AstConv/HtmlStruct.fs index fec994e..ae8e8d3 100644 --- a/AstConv/HtmlStruct.fs +++ b/AstConv/HtmlStruct.fs @@ -138,7 +138,6 @@ open System.IO inherit Present.Forwards(refs) let ref_signature = $"@{refs.storyRef()}&{refs.sliceRef()}&{refs.pointRef()}" - let lines = refs.children() |> List.map (fun x->x.content()) interface Present.IDomUnit with member this.name(): string = ref_signature @@ -158,8 +157,6 @@ open System.IO class inherit Present.Forwards(defs) - let lines = defs.children() |> List.map (fun x->x.content()) - interface Present.IDomUnit with member this.name(): string = defs.name() member this.object() = defs @@ -170,8 +167,13 @@ open System.IO failwith "append" end let point_assemble (defs: AstImport.PointDef) : PointDefine = - let texts = defs.children() |> List.map (fun dom -> TextContent(dom) :> Present.IDomUnit) - PointDefine(defs, texts) + let objs = defs.children() |> List.map (fun dom -> + match dom with + | :? AstImport.TextItem as t -> TextContent(t) :> Present.IDomUnit + | :? AstImport.PointRef as r -> refer_assemble(r) + | _ -> failwith "match error" + ) + PointDefine(defs, objs) /// 具有回退功能的元素 @@ -208,7 +210,6 @@ open System.IO let childs = defs.children() |> List.map(fun data -> match data with - | :? AstImport.PointRef as refs -> refer_assemble(refs) | :? AstImport.PointDef as defs -> point_assemble(defs) | :? AstImport.TextItem as text -> TextContent(text) | _ -> failwith "match error" @@ -265,8 +266,7 @@ open System.IO type VolumeDefine(defs: AstImport.VolumeDef, childs: Present.IDomUnit list) = class interface Present.IDomUnit with - member this.name(): string = - defs.name() + member this.name(): string = defs.name() member this.object() = defs interface Present.IContainer with diff --git a/CoreTest/main.cpp b/CoreTest/main.cpp index febc364..28747d2 100644 --- a/CoreTest/main.cpp +++ b/CoreTest/main.cpp @@ -11,12 +11,12 @@ int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); - QFile in("D:\\Projects\\Cpp\\WsNovelParser\\x64\\test_file\\description - 副本.story"); + QFile in("D:\\Projects\\Cpp\\WsNovelParser\\CoreTest\\syntax_example.txt"); in.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream tt(&in); - //tt.setCodec("UTF-8"); + tt.setCodec("UTF-8"); lib_words::WordReader reader; - auto vwords = reader.wordsFrom(tt, "D:\\Projects\\Cpp\\WsNovelParser\\x64\\test_file\\description - 副本.story"); + auto vwords = reader.wordsFrom(tt, "D:\\Projects\\Cpp\\WsNovelParser\\CoreTest\\syntax_example.txt"); ast_gen::SyntaxParser parser(example_novel::NovalSyntax::getSyntaxTree()); auto rst = parser.parse(vwords); diff --git a/CoreTest/syntax_example.txt b/CoreTest/syntax_example.txt index 4317d10..1595d4a 100644 --- a/CoreTest/syntax_example.txt +++ b/CoreTest/syntax_example.txt @@ -1,129 +1,129 @@ -# 1 +#排序 1 -{ 1 +{故事 故事名称1 } -{ 2 - ½ܶ} +{故事 故事名称2 + 故事介绍段落} -{ 3 - ½ܶ aldkfjl flwief} +{故事 故事名称3 + 故事介绍段落 aldkfjl flwief} -{ 4 - ½ܶ aldkfjl flwief +{故事 故事名称4 + 故事介绍段落 aldkfjl flwief } -{ 5 - ½ܶ aldkfjl flwief - { } +{故事 故事名称5 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称} } -{ 6 - ½ܶ aldkfjl flwief - { } +{故事 故事名称6 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 剧情介绍} } -{ 7 - ½ܶ aldkfjl flwief - { - +{故事 故事名称7 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 } } -{ 8 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ} +{故事 故事名称8 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称} } } -{ 9 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ - ; O} +{故事 故事名称9 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称 + 奥龙订饭;爱领克 非两爱看扥} } } -{ 10 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ - ; O +{故事 故事名称10 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称 + 奥龙订饭;爱领克 非两爱看扥 } } } -{ 11 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ - ; O - } - {@ڵ 10&&ڵ} - } -} - -{ 4 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ - ; O - } - {@ڵ 10&&ڵ - asldkfj } - } -} - -{ 4 - ½ܶ aldkfjl flwief - { - - {ڵ ڵ - ; O - } - {@ڵ 10&&ڵ - asldkfj +{故事 故事名称11 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称 + 奥龙订饭;爱领克 非两爱看扥 + {@节点 故事名称10&剧情名称&节点名称} } } } -{־ } +{故事 故事名称4 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称 + 奥龙订饭;爱领克 非两爱看扥 + {@节点 故事名称10&剧情名称&节点名称 + asldkfj 来看房莱肯} + } + } +} -{־ - } +{故事 故事名称4 + 故事介绍段落 aldkfjl flwief + {剧情 剧情名称 + 剧情介绍 + {节点 节点名称 + 奥龙订饭;爱领克 非两爱看扥 + {@节点 故事名称10&剧情名称&节点名称 + asldkfj 来看房莱肯 + } + } + } +} + +{分卷 卷宗名称} + +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯} -{־ - lakdjf;alfj +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯 lakdjf;alfj } -{־ - lakdjf;alfj - {½ ½} +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯 lakdjf;alfj + {章节 章节名称} } -{־ - lakdjf;alfj - {½ ½ 췢} +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯 lakdjf;alfj + {章节 章节名称 昂来看申领发} } -{־ - lakdjf;alfj - {½ ½ 췢 - {@ڵ 10&&ڵ} +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯 lakdjf;alfj + {章节 章节名称 昂来看申领发 + {@节点 故事名称10&剧情名称&节点名称} } } -{־ - lakdjf;alfj - {½ ½ 췢 - {@ڵ 10&&ڵ - ɭ嵫Ѿ} +{分卷 卷宗名称 + 拉开茯苓领赛季发啦肯 lakdjf;alfj + {章节 章节名称 昂来看申领发 + {@节点 故事名称10&剧情名称&节点名称 + 森铃但凡拉动垦局} } } \ No newline at end of file diff --git a/WsNovelParser/WsNovelParser.vcxproj.user b/WsNovelParser/WsNovelParser.vcxproj.user index a8dea2e..6e591db 100644 --- a/WsNovelParser/WsNovelParser.vcxproj.user +++ b/WsNovelParser/WsNovelParser.vcxproj.user @@ -3,7 +3,7 @@ $(SolutionDir)$(Platform)\$(Configuration)\ WindowsLocalDebugger - --path "D:\CustomNovels\科学+修仙+创造世界X" --dest E:\ + --path "D:/Projects/Cpp/WsNovelParser/x64/test_file/" --dest E:\ --path "D:\Projects\Cpp\WsNovelParser\x64\test_file" --dest E:\ diff --git a/libParse/parse_novel.cpp b/libParse/parse_novel.cpp index c6823b7..1ace7fb 100644 --- a/libParse/parse_novel.cpp +++ b/libParse/parse_novel.cpp @@ -54,8 +54,7 @@ void FragmentExistsCheck::exists_check(std::shared_ptr root, std: } example_novel::FragmentExistsCheck::FragmentExistsCheck() - :_nodes_cache(std::make_shared()) { -} + :_nodes_cache(std::make_shared()) { } void FragmentExistsCheck::validCheck(std::shared_ptr root) const { const_cast(this)->nodes_regist(this->_nodes_cache, root); @@ -128,6 +127,7 @@ void PointGraphCheck::validCheck(std::shared_ptr root) cons const_cast(this)->fragments_sort_list.clear(); auto self = std::const_pointer_cast(this->shared_from_this()); + // 提取所有故事线 std::function>(std::shared_ptr)> story_peak = [&](std::shared_ptr root)->QList> { QList> return_temp; @@ -144,27 +144,41 @@ void PointGraphCheck::validCheck(std::shared_ptr root) cons return return_temp; }; - std::function>(std::shared_ptr)> - points_extract = [](std::shared_ptr story) { + // 提取所有节点定义 + std::function>(std::shared_ptr)> points_extract + = [&](std::shared_ptr story) { QList> return_temp; auto story_children = story->children(); - QList> slice_list; - std::copy_if(story_children.begin(), story_children.end(), - std::back_inserter(slice_list), [](std::shared_ptr ins) { - return ins->element()->typeMark() == (int) NovelNode::FragmentSlice; - }); + for (auto ins : story_children) { + switch (ins->element()->typeMark()) { + case (int) NovelNode::PointDefines: + return_temp << ins; + break; + default: + return_temp << points_extract(ins); + break; + } + } + return return_temp; + }; - decltype(slice_list) slice_children; - for (auto slice : slice_list) - slice_children.append(slice->children()); - - std::copy_if(slice_children.begin(), slice_children.end(), - std::back_inserter(return_temp), [](std::shared_ptr ins) { - return ins->element()->typeMark() == (int) NovelNode::PointDefines && - ins->element()->typeMark() == (int) NovelNode::PointRefers; - }); + // 提取节点内包含的引用节点 + std::function>(std::shared_ptr)> refers_within + = [&](std::shared_ptr defs) { + QList> return_temp; + auto x_children = defs->children(); + for (auto ins : x_children) { + switch (ins->element()->typeMark()) { + case (int) NovelNode::PointRefers: + return_temp << ins; + break; + default: + return_temp << refers_within(ins); + break; + } + } return return_temp; }; @@ -177,62 +191,55 @@ void PointGraphCheck::validCheck(std::shared_ptr root) cons // 构建情节节点列表 for (auto point_primitive : point_items) { - switch (point_primitive->element()->typeMark()) { - case (int) NovelNode::PointDefines: - { - auto target_node = std::dynamic_pointer_cast(point_primitive->element()); - auto finst = std::make_shared(target_node); - self->setElement(finst); - }break; - default: break; - } + auto target_node = std::dynamic_pointer_cast(point_primitive->element()); + auto finst = std::make_shared(target_node); + self->setElement(finst); } } + // 获取绑定节点名称 + auto get_name = [](std::shared_ptr node)->QString { + switch (node->element()->typeMark()) { + case (int) NovelNode::PointDefines: { + auto def_node = std::dynamic_pointer_cast(node->element()); + return def_node->signature(); + }break; + case (int) NovelNode::PointRefers: { + auto ref_node = std::dynamic_pointer_cast(node->element()); + return ref_node->referSignature(); + }break; + } + return QString(); + }; // 构建图连接 for (auto story : all_story) { + // 过滤获取情节节点 auto point_items = points_extract(story); - // 过滤获取情节节点 - for (auto idx = 0; idx < point_items.size(); idx++) { - auto point_inst = point_items[idx]; - switch (point_inst->element()->typeMark()) { - case (int) NovelNode::PointDefines: - case (int) NovelNode::PointRefers: - break; - default: - point_items.removeAt(idx--); - break; - } - } - - auto get_name = [](std::shared_ptr node)->QString { - switch (node->element()->typeMark()) { - case (int) NovelNode::PointDefines: - { - auto def_node = std::dynamic_pointer_cast(node->element()); - return def_node->signature(); - }break; - case (int) NovelNode::PointRefers: - { - auto ref_node = std::dynamic_pointer_cast(node->element()); - return ref_node->referSignature(); - }break; - } - return QString(); - }; - - // 构建完整图结构 + // 构建完整图结构:串联定义节点的顺序 for (auto fidx = 1; fidx < point_items.size(); fidx++) { auto tail_name = get_name(point_items[fidx - 1]); auto head_name = get_name(point_items[fidx]); - auto tail_helper = getElement(tail_name); auto head_helper = getElement(head_name); - tail_helper->appendNext(head_helper); head_helper->inDegree()++; } + + // 构建完整图结构:串联引用节点的顺序 + for(auto point : point_items){ + auto first_name = get_name(point); + auto first_helper = getElement(first_name); + + auto refers_nodes = refers_within(point); + for (auto refer : refers_nodes) { + auto second_name = get_name(refer); + auto second_helper = getElement(second_name); + + first_helper->appendNext(second_helper); + second_helper->inDegree()++; + } + } } // 获取拓扑排序序列 @@ -268,8 +275,7 @@ QString PointGraphCheck::name() const { return "情节网络有效性检查器"; } -PointGraphHelper::PointGraphHelper(std::shared_ptr node) : node_peer(node) { -} +PointGraphHelper::PointGraphHelper(std::shared_ptr node) : node_peer(node) { } std::shared_ptr PointGraphHelper::nodePeer() const { return this->node_peer; @@ -292,16 +298,14 @@ QList> StoryOrderCheck::valid_docs_peak(std auto type_code = pnode->element()->typeMark(); switch ((NovelNode) type_code) { - case NovelNode::GlobalElement: - { + case NovelNode::GlobalElement: { auto children = pnode->children(); for (auto& cinst : children) { values.append(valid_docs_peak(cinst)); } }break; - case NovelNode::Document: - { + case NovelNode::Document: { auto elms_set = pnode->children(); decltype(elms_set) story_set; diff --git a/libSyntax/syntax_novel.cpp b/libSyntax/syntax_novel.cpp index 048655d..be71c50 100644 --- a/libSyntax/syntax_novel.cpp +++ b/libSyntax/syntax_novel.cpp @@ -136,9 +136,22 @@ public: }; +using ReferSyntaxDef = lib_composit::Seqs, Match, Match, Action, Match, Action, Match, Action, + OptMulti, + Match>; +class ReferSyntax : public ElementRule { +public: + ReferSyntax() : ElementRule("point_refer") { } + + // 通过 ElementRule 继承 + QList> expr_rule_parse(std::shared_ptr cursor) const override { + return _children_store->parse(cursor); + } +}; + using PointSyntaxDef = lib_composit::Seqs, Match, Action, - OptMulti, + OptMulti>, Match>; class PointSyntax : public ElementRule { public: @@ -152,23 +165,8 @@ public: -using ReferSyntaxDef = lib_composit::Seqs, Match, Match, Action, Match, Action, Match, Action, - OptMulti, - Match>; -class ReferSyntax : public ElementRule { -public: - ReferSyntax() : ElementRule < PointRefers, (int) NovelNode::PointRefers, ReferSyntaxDef>("point_refer") { } - - // 通过 ElementRule 继承 - QList> expr_rule_parse(std::shared_ptr cursor) const override { - return _children_store->parse(cursor); - } -}; - - - using SliceSyntaxDef = lib_composit::Seqs, Match, Action, - lib_composit::OptMulti>, + lib_composit::OptMulti>, Match>; class SliceSyntax : public ElementRule { public: