This commit is contained in:
codeboss 2025-03-28 22:52:33 +08:00
parent da9d3939b1
commit b500e9d095
7 changed files with 212 additions and 200 deletions

View File

@ -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<PointDef> =
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))

View File

@ -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<AstImport.AstObject,Present.IDomUnit>(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

View File

@ -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);

View File

@ -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
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥}
{故事 故事名称9
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥}
}
}
{故事 故事名称10
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥
{故事 故事名称10
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥
}
}
}
{故事 故事名称11
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥
}
{@节点 故事名称10&剧情名称&节点名称}
}
}
{故事 故事名称4
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥
}
{@节点 故事名称10&剧情名称&节点名称
asldkfj 来看房莱肯}
}
}
{故事 故事名称4
故事介绍段落 aldkfjl flwief
{剧情 剧情名称
剧情介绍
{节点 节点名称
奥龙订饭;爱领克 非两爱看扥
}
{@节点 故事名称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&剧情名称&节点名称
森铃但凡拉动垦局}
}
}

View File

@ -3,7 +3,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>--path "D:\CustomNovels\科学+修仙+创造世界X" --dest E:\</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>--path "D:/Projects/Cpp/WsNovelParser/x64/test_file/" --dest E:\</LocalDebuggerCommandArguments>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>--path "D:\Projects\Cpp\WsNovelParser\x64\test_file" --dest E:\</LocalDebuggerCommandArguments>

View File

@ -54,8 +54,7 @@ void FragmentExistsCheck::exists_check(std::shared_ptr<ElementsCache> root, std:
}
example_novel::FragmentExistsCheck::FragmentExistsCheck()
:_nodes_cache(std::make_shared<ElementsCache>()) {
}
:_nodes_cache(std::make_shared<ElementsCache>()) { }
void FragmentExistsCheck::validCheck(std::shared_ptr<const ElementAccess> root) const {
const_cast<FragmentExistsCheck*>(this)->nodes_regist(this->_nodes_cache, root);
@ -128,6 +127,7 @@ void PointGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) cons
const_cast<PointGraphCheck*>(this)->fragments_sort_list.clear();
auto self = std::const_pointer_cast<PointGraphCheck>(this->shared_from_this());
// 提取所有故事线
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)> story_peak
= [&](std::shared_ptr<const ElementAccess> root)->QList<std::shared_ptr<const ElementAccess>> {
QList<std::shared_ptr<const ElementAccess>> return_temp;
@ -144,27 +144,41 @@ void PointGraphCheck::validCheck(std::shared_ptr<const ElementAccess> root) cons
return return_temp;
};
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)>
points_extract = [](std::shared_ptr<const ElementAccess> story) {
// 提取所有节点定义
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)> points_extract
= [&](std::shared_ptr<const ElementAccess> story) {
QList<std::shared_ptr<const ElementAccess>> return_temp;
auto story_children = story->children();
QList<std::shared_ptr<const ElementAccess>> slice_list;
std::copy_if(story_children.begin(), story_children.end(),
std::back_inserter(slice_list), [](std::shared_ptr<const ElementAccess> 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<const ElementAccess> ins) {
return ins->element()->typeMark() == (int) NovelNode::PointDefines &&
ins->element()->typeMark() == (int) NovelNode::PointRefers;
});
// 提取节点内包含的引用节点
std::function<QList<std::shared_ptr<const ElementAccess>>(std::shared_ptr<const ElementAccess>)> refers_within
= [&](std::shared_ptr<const ElementAccess> defs) {
QList<std::shared_ptr<const ElementAccess>> 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<const ElementAccess> root) cons
// 构建情节节点列表
for (auto point_primitive : point_items) {
switch (point_primitive->element()->typeMark()) {
case (int) NovelNode::PointDefines:
{
auto target_node = std::dynamic_pointer_cast<const PointDefines>(point_primitive->element());
auto finst = std::make_shared<PointGraphHelper>(target_node);
self->setElement(finst);
}break;
default: break;
}
auto target_node = std::dynamic_pointer_cast<const PointDefines>(point_primitive->element());
auto finst = std::make_shared<PointGraphHelper>(target_node);
self->setElement(finst);
}
}
// 获取绑定节点名称
auto get_name = [](std::shared_ptr<const ElementAccess> node)->QString {
switch (node->element()->typeMark()) {
case (int) NovelNode::PointDefines: {
auto def_node = std::dynamic_pointer_cast<const PointDefines>(node->element());
return def_node->signature();
}break;
case (int) NovelNode::PointRefers: {
auto ref_node = std::dynamic_pointer_cast<const PointRefers>(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<const ElementAccess> node)->QString {
switch (node->element()->typeMark()) {
case (int) NovelNode::PointDefines:
{
auto def_node = std::dynamic_pointer_cast<const PointDefines>(node->element());
return def_node->signature();
}break;
case (int) NovelNode::PointRefers:
{
auto ref_node = std::dynamic_pointer_cast<const PointRefers>(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<const PointDefines> node) : node_peer(node) {
}
PointGraphHelper::PointGraphHelper(std::shared_ptr<const PointDefines> node) : node_peer(node) { }
std::shared_ptr<const PointDefines> PointGraphHelper::nodePeer() const {
return this->node_peer;
@ -292,16 +298,14 @@ QList<std::shared_ptr<const ElementAccess>> 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;

View File

@ -136,9 +136,22 @@ public:
};
using ReferSyntaxDef = lib_composit::Seqs<Match<LBracket>, Match<ReferMk>, Match<PointWord>, Action<PointRefers, NameText, ref_story_set>, Match<SplitMk>, Action<PointRefers, NameText, ref_slice_set>, Match<SplitMk>, Action<PointRefers, NameText, ref_point_set>,
OptMulti<DeclSyntax>,
Match<RBracket>>;
class ReferSyntax : public ElementRule<PointRefers, (int) NovelNode::PointRefers, ReferSyntaxDef> {
public:
ReferSyntax() : ElementRule<PointRefers, (int) NovelNode::PointRefers, ReferSyntaxDef>("point_refer") { }
// 通过 ElementRule 继承
QList<std::shared_ptr<const MatchCursor>> expr_rule_parse(std::shared_ptr<const MatchCursor> cursor) const override {
return _children_store->parse(cursor);
}
};
using PointSyntaxDef = lib_composit::Seqs<Match<LBracket>, Match<PointWord>, Action<PointDefines, NameText, point_nm_set>,
OptMulti<DeclSyntax>,
OptMulti<Any<ReferSyntax, DeclSyntax>>,
Match<RBracket>>;
class PointSyntax : public ElementRule<PointDefines, (int) NovelNode::PointDefines, PointSyntaxDef> {
public:
@ -152,23 +165,8 @@ public:
using ReferSyntaxDef = lib_composit::Seqs<Match<LBracket>, Match<ReferMk>, Match<PointWord>, Action<PointRefers, NameText, ref_story_set>, Match<SplitMk>, Action<PointRefers, NameText, ref_slice_set>, Match<SplitMk>, Action<PointRefers, NameText, ref_point_set>,
OptMulti<DeclSyntax>,
Match<RBracket>>;
class ReferSyntax : public ElementRule<PointRefers, (int) NovelNode::PointRefers, ReferSyntaxDef> {
public:
ReferSyntax() : ElementRule < PointRefers, (int) NovelNode::PointRefers, ReferSyntaxDef>("point_refer") { }
// 通过 ElementRule 继承
QList<std::shared_ptr<const MatchCursor>> expr_rule_parse(std::shared_ptr<const MatchCursor> cursor) const override {
return _children_store->parse(cursor);
}
};
using SliceSyntaxDef = lib_composit::Seqs<Match<LBracket>, Match<SliceWord>, Action<FragmentSlice, NameText, slice_nm_set>,
lib_composit::OptMulti<Any<PointSyntax, ReferSyntax, DeclSyntax>>,
lib_composit::OptMulti<Any<PointSyntax, DeclSyntax>>,
Match<RBracket>>;
class SliceSyntax : public ElementRule<FragmentSlice, (int) NovelNode::FragmentSlice, SliceSyntaxDef> {
public: