update
This commit is contained in:
parent
74ce31b072
commit
872f874d22
|
@ -1,3 +1,5 @@
|
||||||
*/x64/*
|
*/x64/*
|
||||||
.vs/*
|
.vs/*
|
||||||
x64/*
|
x64/*
|
||||||
|
*/bin/*
|
||||||
|
*/obj/*
|
|
@ -132,7 +132,7 @@ int MatchMode::modeCode() const {
|
||||||
return code_store;
|
return code_store;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MatchMode::usageString() const {
|
QString MatchMode::usagestring() const {
|
||||||
QString usage_string;
|
QString usage_string;
|
||||||
for (auto& item : args_mode)
|
for (auto& item : args_mode)
|
||||||
usage_string += item->placeHolder() + " ";
|
usage_string += item->placeHolder() + " ";
|
||||||
|
@ -140,7 +140,7 @@ QString MatchMode::usageString() const {
|
||||||
return usage_string;
|
return usage_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MatchMode::explanString() const {
|
QString MatchMode::explanstring() const {
|
||||||
QStringList sections;
|
QStringList sections;
|
||||||
sections << " " + _means_explain;
|
sections << " " + _means_explain;
|
||||||
sections << QString(" Switch:");
|
sections << QString(" Switch:");
|
||||||
|
@ -235,8 +235,8 @@ std::shared_ptr<IArgvPack> MatchMode::getUnitViaInitIndex(int pos) {
|
||||||
QString ArgsParser::helperDoc() const {
|
QString ArgsParser::helperDoc() const {
|
||||||
QString help_string;
|
QString help_string;
|
||||||
for (auto& mode : this->match_modes) {
|
for (auto& mode : this->match_modes) {
|
||||||
help_string += "Usage:" + mode->usageString() + "\n";
|
help_string += "Usage:" + mode->usagestring() + "\n";
|
||||||
help_string += mode->explanString() + "\n\n";
|
help_string += mode->explanstring() + "\n\n";
|
||||||
}
|
}
|
||||||
return help_string;
|
return help_string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,14 +162,14 @@ namespace args_parse {
|
||||||
*
|
*
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
QString usageString() const;
|
QString usagestring() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回模式解析字符串.
|
* 返回模式解析字符串.
|
||||||
*
|
*
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
QString explanString() const;
|
QString explanstring() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加参数解析单元.
|
* 添加参数解析单元.
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="AstImport.fs" />
|
||||||
|
<Compile Include="HtmlStruct.fs" />
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,366 @@
|
||||||
|
namespace AstAccess
|
||||||
|
|
||||||
|
open System.Xml
|
||||||
|
open System.Linq
|
||||||
|
|
||||||
|
module AstImport =
|
||||||
|
/// 带有地址的对象
|
||||||
|
type AstObject() =
|
||||||
|
class
|
||||||
|
member this.address() = string(this.GetHashCode ())
|
||||||
|
|
||||||
|
abstract member members:unit -> AstObject list
|
||||||
|
default this.members(): AstObject list = []
|
||||||
|
end
|
||||||
|
|
||||||
|
let rec branch_map_conv (pnode: AstObject, childs: AstObject list) =
|
||||||
|
match childs with
|
||||||
|
| [] -> []
|
||||||
|
| _ ->
|
||||||
|
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
|
||||||
|
| 0 -> 0
|
||||||
|
| _ ->
|
||||||
|
let (_, (_, parent_node)) = prev_nodes.Head
|
||||||
|
depth_seek(branchs, parent_node) + 1
|
||||||
|
|
||||||
|
/// TextWord
|
||||||
|
type TextItem(bind: XmlElement) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
member this.content():string =
|
||||||
|
bind.GetAttribute "text"
|
||||||
|
|
||||||
|
member this.row():int =
|
||||||
|
let tokens_node = bind.ChildNodes.Cast<XmlNode>().Where(
|
||||||
|
fun node -> node.Name.Equals "tokens").ElementAt(0)
|
||||||
|
let token_bind = tokens_node.ChildNodes.Cast<XmlElement>().ElementAt(0)
|
||||||
|
int(token_bind.GetAttribute "row")
|
||||||
|
|
||||||
|
static member GenerateText(text_opt: XmlNode): Option<TextItem> =
|
||||||
|
match text_opt with
|
||||||
|
| :? XmlElement as obj_t when obj_t.Name.Equals "text-section" ->
|
||||||
|
Some(TextItem(obj_t))
|
||||||
|
| _ -> None
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 引用节点
|
||||||
|
type PointRef(bind: XmlElement, texts: TextItem list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = PointRef(bind, [])
|
||||||
|
|
||||||
|
member this.pointRef() =
|
||||||
|
bind.GetAttribute "point"
|
||||||
|
member this.sliceRef() =
|
||||||
|
bind.GetAttribute "slice"
|
||||||
|
member this.storyRef() =
|
||||||
|
bind.GetAttribute "story"
|
||||||
|
member this.appendChild(objs: TextItem list) =
|
||||||
|
PointRef(bind, texts@objs)
|
||||||
|
member this.children() =
|
||||||
|
texts
|
||||||
|
|
||||||
|
override this.members(): AstObject list =
|
||||||
|
texts |> List.map (fun it->it :> AstObject)
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): TextItem list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
match TextItem.GenerateText(child) with
|
||||||
|
| Some text -> text::PointRef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
| None -> PointRef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GeneratePointRef(ref_opt: XmlNode): Option<PointRef> =
|
||||||
|
match ref_opt with
|
||||||
|
| :? XmlElement as refo when refo.Name.Equals "refer" ->
|
||||||
|
let text_objects = PointRef.GenerateFromChildSibling(refo.FirstChild)
|
||||||
|
Some(PointRef(refo, text_objects))
|
||||||
|
| _ -> None
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 定义节点
|
||||||
|
type PointDef(bind: XmlElement, texts: TextItem 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
|
||||||
|
|
||||||
|
override this.members(): AstObject list =
|
||||||
|
texts |> List.map (fun it->it :> AstObject)
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): TextItem list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
match TextItem.GenerateText(child) with
|
||||||
|
| Some text -> text::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))
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
type SliceChildType = |Text of TextItem |Define of PointDef |Refer of PointRef
|
||||||
|
/// 情节节点
|
||||||
|
type SliceDef(bind: XmlElement, objs: AstObject list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = SliceDef(bind, [])
|
||||||
|
|
||||||
|
member this.name() =
|
||||||
|
bind.GetAttribute "name"
|
||||||
|
member this.appendChild(o: SliceChildType) =
|
||||||
|
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
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): SliceChildType list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
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
|
||||||
|
|
||||||
|
match h with
|
||||||
|
| Some value -> value::SliceDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
| _ -> SliceDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GenerateSliceDef(slice_opt: XmlNode): Option<SliceDef> =
|
||||||
|
match slice_opt with
|
||||||
|
| :? XmlElement as slice when slice.Name.Equals "slice" ->
|
||||||
|
let mbrs = SliceDef.GenerateFromChildSibling(slice.FirstChild)
|
||||||
|
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))
|
||||||
|
| _ -> None
|
||||||
|
end
|
||||||
|
|
||||||
|
type StoryChildType = |Text of TextItem |Slice of SliceDef
|
||||||
|
/// 故事节点
|
||||||
|
type StoryDef(bind: XmlElement, objs: AstObject list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = StoryDef(bind, [])
|
||||||
|
|
||||||
|
member this.name() =
|
||||||
|
bind.GetAttribute "name"
|
||||||
|
member this.sort() =
|
||||||
|
int(bind.GetAttribute "sort")
|
||||||
|
member this.appendChild(o: StoryChildType) =
|
||||||
|
match o with
|
||||||
|
|Text t -> StoryDef(bind, objs@[t])
|
||||||
|
|Slice s -> StoryDef(bind, objs@[s])
|
||||||
|
member this.children() = objs
|
||||||
|
|
||||||
|
override this.members(): AstObject list = objs
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): StoryChildType list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
let h = match child.Name with
|
||||||
|
| "text-section" -> Some(Text(TextItem.GenerateText(child).Value))
|
||||||
|
| "slice" -> Some(Slice(SliceDef.GenerateSliceDef(child).Value))
|
||||||
|
| _->None
|
||||||
|
match h with
|
||||||
|
| Some value -> value::StoryDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
| _ -> StoryDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GenerateStoryDef(story_opt: XmlNode): Option<StoryDef> =
|
||||||
|
match story_opt with
|
||||||
|
| :? XmlElement as story when story.Name.Equals "story" ->
|
||||||
|
let children = StoryDef.GenerateFromChildSibling(story.FirstChild)
|
||||||
|
let objs = children |> List.map (
|
||||||
|
fun x ->
|
||||||
|
match x with
|
||||||
|
|Text valx -> valx :> AstObject
|
||||||
|
|Slice valx -> valx :> AstObject
|
||||||
|
)
|
||||||
|
Some(StoryDef(story, objs))
|
||||||
|
| _ -> None
|
||||||
|
end
|
||||||
|
|
||||||
|
type ArticleChildType = |Text of TextItem |Refer of PointRef
|
||||||
|
/// 章节节点
|
||||||
|
type ArticleDef(bind: XmlElement, objs: AstObject list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = ArticleDef(bind, [])
|
||||||
|
|
||||||
|
member this.name() =
|
||||||
|
bind.GetAttribute "name"
|
||||||
|
member this.children() = objs
|
||||||
|
member this.appendChild(o: ArticleChildType list) =
|
||||||
|
let conv item = match item with
|
||||||
|
|Text t -> t :> AstObject
|
||||||
|
|Refer r -> r :> AstObject
|
||||||
|
|
||||||
|
let items = o |> List.map conv
|
||||||
|
ArticleDef(bind, objs@items)
|
||||||
|
|
||||||
|
override this.members(): AstObject list = objs
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): ArticleChildType list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
let data = match child.Name with
|
||||||
|
| "text-section" -> Some(Text(TextItem.GenerateText(child).Value))
|
||||||
|
| "refer" -> Some(Refer(PointRef.GeneratePointRef(child).Value))
|
||||||
|
| _ -> None
|
||||||
|
match data with
|
||||||
|
| Some value -> value::ArticleDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
| None -> ArticleDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GenerateArticleDef(article_opt: XmlNode): Option<ArticleDef> =
|
||||||
|
match article_opt with
|
||||||
|
| :? XmlElement as article when article.Name.Equals "article" ->
|
||||||
|
let mbrs = ArticleDef.GenerateFromChildSibling(article.FirstChild)
|
||||||
|
let conv it = match it with
|
||||||
|
|Text v -> v :> AstObject
|
||||||
|
|Refer v -> v:> AstObject
|
||||||
|
Some(ArticleDef(article, mbrs |> List.map conv))
|
||||||
|
| _ -> None
|
||||||
|
end
|
||||||
|
|
||||||
|
type VolumeChildType = |Text of TextItem |Article of ArticleDef
|
||||||
|
/// 卷宗节点
|
||||||
|
type VolumeDef(bind: XmlElement, objs: AstObject list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = VolumeDef(bind, [])
|
||||||
|
|
||||||
|
member this.name() =
|
||||||
|
bind.GetAttribute "name"
|
||||||
|
member this.children() = objs
|
||||||
|
member this.appendChild(o: VolumeChildType list) =
|
||||||
|
let items = o |> List.map (
|
||||||
|
fun it->
|
||||||
|
match it with
|
||||||
|
|Text t -> t :> AstObject
|
||||||
|
|Article a -> a :> AstObject
|
||||||
|
)
|
||||||
|
VolumeDef(bind, objs@items)
|
||||||
|
|
||||||
|
override this.members(): AstObject list = objs
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): VolumeChildType list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
let data = match child.Name with
|
||||||
|
| "text-section" -> Some(Text(TextItem.GenerateText(child).Value))
|
||||||
|
| "article" -> Some(Article(ArticleDef.GenerateArticleDef(child).Value))
|
||||||
|
| _ -> None
|
||||||
|
match data with
|
||||||
|
| Some value -> value::VolumeDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
| None -> VolumeDef.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GenerateVolumeDef(vol_opt: XmlNode): Option<VolumeDef> =
|
||||||
|
match vol_opt with
|
||||||
|
| :? XmlElement as volume when volume.Name.Equals "volume" ->
|
||||||
|
let mbrs = VolumeDef.GenerateFromChildSibling(volume.FirstChild)
|
||||||
|
let conv data = match data with
|
||||||
|
|Text d -> d :> AstObject
|
||||||
|
|Article d -> d:> AstObject
|
||||||
|
Some(VolumeDef(volume, mbrs |> List.map conv))
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
type ProgramChildType = |Volume of VolumeDef |Story of StoryDef
|
||||||
|
/// 程序节点
|
||||||
|
type Program(bind: XmlElement, objs: AstObject list) =
|
||||||
|
class
|
||||||
|
inherit AstObject()
|
||||||
|
new(bind: XmlElement) = Program(bind, [])
|
||||||
|
|
||||||
|
member this.time() =
|
||||||
|
bind.GetAttribute "time"
|
||||||
|
member this.children() = objs
|
||||||
|
member this.appendChild(o: ProgramChildType list) =
|
||||||
|
let items = o |> List.map (fun it->
|
||||||
|
match it with
|
||||||
|
|Story s -> s :> AstObject
|
||||||
|
|Volume v -> v :> AstObject
|
||||||
|
)
|
||||||
|
Program(bind, objs @items)
|
||||||
|
|
||||||
|
override this.members(): AstObject list = objs
|
||||||
|
|
||||||
|
static member GenerateFromChildSibling(child: XmlNode): ProgramChildType list =
|
||||||
|
match child with
|
||||||
|
| null -> []
|
||||||
|
| _ ->
|
||||||
|
let d = match child.Name with
|
||||||
|
| "volume" -> Some(Volume(VolumeDef.GenerateVolumeDef(child).Value))
|
||||||
|
| "story" -> Some(Story(StoryDef.GenerateStoryDef(child).Value))
|
||||||
|
| _ -> None
|
||||||
|
match d with
|
||||||
|
|Some value -> value::Program.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|None -> Program.GenerateFromChildSibling(child.NextSibling)
|
||||||
|
|
||||||
|
static member GenerateFrom(doc: XmlDocument) =
|
||||||
|
let ast = doc.DocumentElement
|
||||||
|
|
||||||
|
let mbrs = Program.GenerateFromChildSibling(ast.FirstChild)
|
||||||
|
let conv data = match data with
|
||||||
|
|Volume d -> d:>AstObject
|
||||||
|
|Story d -> d :> AstObject
|
||||||
|
Program(ast, mbrs |> List.map conv)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
type AstVisitor =
|
||||||
|
interface
|
||||||
|
abstract member visit:AstObject -> bool
|
||||||
|
end
|
||||||
|
|
||||||
|
type AstVisitEntry(root: AstObject) =
|
||||||
|
class
|
||||||
|
/// 1:node
|
||||||
|
/// 2: node
|
||||||
|
/// 2: node
|
||||||
|
/// 3: node
|
||||||
|
/// 4: node
|
||||||
|
/// ......
|
||||||
|
member private this.visit_internal(nodes: AstObject list, visitor: AstVisitor): bool =
|
||||||
|
match nodes.Length with
|
||||||
|
| 0 -> true
|
||||||
|
| _ ->
|
||||||
|
this.visit_internal(nodes.Head.members(), visitor) && visitor.visit(nodes.Head) && this.visit_internal(nodes.Tail, visitor)
|
||||||
|
|
||||||
|
|
||||||
|
member this.visitWith(visitor: AstVisitor): bool =
|
||||||
|
this.visit_internal([root], visitor)
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,266 @@
|
||||||
|
namespace HtmlStruct
|
||||||
|
|
||||||
|
open AstAccess
|
||||||
|
open System.Xml
|
||||||
|
open System
|
||||||
|
|
||||||
|
module Present =
|
||||||
|
/// 可访问元素
|
||||||
|
type Access(hrefs: string) =
|
||||||
|
class
|
||||||
|
member this.accessLink(): string =
|
||||||
|
hrefs
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 回退访问元素
|
||||||
|
type Backward(hrefs: string) =
|
||||||
|
class
|
||||||
|
member this.backwardLink(): string =
|
||||||
|
hrefs
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 内容元素:分卷、章节、引用节点、故事线、情节、定义节点、引用节点
|
||||||
|
type IDomUnit =
|
||||||
|
interface
|
||||||
|
abstract member name:unit -> string
|
||||||
|
abstract member getHtml:XmlElement -> XmlElement
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 容器节点:分卷、章节、故事线、情节
|
||||||
|
type IContainer =
|
||||||
|
interface
|
||||||
|
abstract member append:List<IDomUnit> -> IContainer
|
||||||
|
end
|
||||||
|
|
||||||
|
/// 访问页面:概括页面、卷宗页面、故事线页面、节点汇总 =================================================
|
||||||
|
type VolumePage(page_hrefs: string, volume: IDomUnit, childs: List<IDomUnit>) =
|
||||||
|
class
|
||||||
|
inherit Access(page_hrefs)
|
||||||
|
new(page_hrefs, volume) = VolumePage(page_hrefs, volume, [])
|
||||||
|
|
||||||
|
interface IDomUnit with
|
||||||
|
member this.name():string =
|
||||||
|
volume.name()
|
||||||
|
member this.getHtml(p: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface IContainer with
|
||||||
|
member this.append(childs: List<IDomUnit>): IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
|
||||||
|
type StoryPage(page_hrefs: string, story: IDomUnit, childs: List<IDomUnit>) =
|
||||||
|
class
|
||||||
|
inherit Access(page_hrefs)
|
||||||
|
new(page_hrefs, story) = StoryPage(page_hrefs, story, [])
|
||||||
|
|
||||||
|
interface IDomUnit with
|
||||||
|
member this.name():string =
|
||||||
|
story.name()
|
||||||
|
member this.getHtml(p: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface IContainer with
|
||||||
|
member this.append(childs: List<IDomUnit>): IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
|
||||||
|
type PointPage(page_hrefs: string, point: IDomUnit, refer_list: List<IDomUnit>) =
|
||||||
|
class
|
||||||
|
inherit Access(page_hrefs)
|
||||||
|
new(page_hrefs, point) = PointPage(page_hrefs, point, [])
|
||||||
|
|
||||||
|
interface IDomUnit with
|
||||||
|
member this.name():string =
|
||||||
|
point.name()
|
||||||
|
member this.getHtml(p: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface IContainer with
|
||||||
|
member this.append(childs: List<IDomUnit>): IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
/// 内容节点 =========================================================================================
|
||||||
|
module Content =
|
||||||
|
type TextContent(word: AstImport.TextItem) =
|
||||||
|
class
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string = ""
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
type PointRefer(refs: AstImport.PointRef, items: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
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
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let refer_assemble (refn: AstImport.PointRef) : PointRefer =
|
||||||
|
let texts = refn.children() |> List.map (fun dom -> TextContent(dom) :> Present.IDomUnit)
|
||||||
|
PointRefer(refn, texts)
|
||||||
|
|
||||||
|
|
||||||
|
type PointDefine(defs: AstImport.PointDef, items: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
let lines = defs.children() |> List.map (fun x->x.content())
|
||||||
|
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string =
|
||||||
|
defs.name()
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let point_assemble (defs: AstImport.PointDef) : PointDefine =
|
||||||
|
let texts = defs.children() |> List.map (fun dom -> TextContent(dom) :> Present.IDomUnit)
|
||||||
|
PointDefine(defs, texts)
|
||||||
|
|
||||||
|
|
||||||
|
type SliceDefine(defs: AstImport.SliceDef, items: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string =
|
||||||
|
defs.name()
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let slice_assemble (defs: AstImport.SliceDef) : SliceDefine =
|
||||||
|
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)
|
||||||
|
| _ -> raise (System.NotImplementedException())
|
||||||
|
)
|
||||||
|
SliceDefine(defs, childs)
|
||||||
|
|
||||||
|
|
||||||
|
type StoryDefine(defs: AstImport.StoryDef, childs: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string =
|
||||||
|
defs.name()
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let story_assemble (defs: AstImport.StoryDef): StoryDefine =
|
||||||
|
let childs = defs.children()
|
||||||
|
|> List.map<AstImport.AstObject, Present.IDomUnit>(fun data ->
|
||||||
|
match data with
|
||||||
|
| :? AstImport.SliceDef as defs -> slice_assemble(defs)
|
||||||
|
| :? AstImport.TextItem as text -> TextContent(text)
|
||||||
|
| _ -> raise (System.NotImplementedException())
|
||||||
|
)
|
||||||
|
StoryDefine(defs, childs)
|
||||||
|
|
||||||
|
|
||||||
|
type ArticleDefine(defs: AstImport.ArticleDef, childs: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string =
|
||||||
|
defs.name()
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let article_assemble (defs: AstImport.ArticleDef) : ArticleDefine =
|
||||||
|
let childs = defs.children()
|
||||||
|
|> List.map<AstImport.AstObject, Present.IDomUnit>(fun data ->
|
||||||
|
match data with
|
||||||
|
| :? AstImport.TextItem as text -> TextContent(text)
|
||||||
|
| :? AstImport.PointRef as refs -> refer_assemble(refs)
|
||||||
|
| _ -> raise (System.NotImplementedException())
|
||||||
|
)
|
||||||
|
ArticleDefine(defs, childs)
|
||||||
|
|
||||||
|
|
||||||
|
type VolumeDefine(defs: AstImport.VolumeDef, childs: List<Present.IDomUnit>) =
|
||||||
|
class
|
||||||
|
interface Present.IDomUnit with
|
||||||
|
member this.name(): string =
|
||||||
|
defs.name()
|
||||||
|
member this.getHtml(pnode: XmlElement): XmlElement =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
interface Present.IContainer with
|
||||||
|
member this.append(childs: List<Present.IDomUnit>): Present.IContainer =
|
||||||
|
raise (System.NotImplementedException())
|
||||||
|
end
|
||||||
|
let volume_assemble (defs: AstImport.VolumeDef): VolumeDefine =
|
||||||
|
let childs = defs.children()
|
||||||
|
|> List.map<AstImport.AstObject, Present.IDomUnit>(fun data ->
|
||||||
|
match data with
|
||||||
|
| :? AstImport.TextItem as text -> TextContent(text)
|
||||||
|
| :? AstImport.ArticleDef as defs -> article_assemble(defs)
|
||||||
|
| _ -> raise (System.NotImplementedException())
|
||||||
|
)
|
||||||
|
VolumeDefine(defs, childs)
|
||||||
|
|
||||||
|
|
||||||
|
type UnitGenerate(root: AstImport.AstObject) =
|
||||||
|
class
|
||||||
|
// ast 节点序列
|
||||||
|
let forwards_map = AstImport.branch_map_conv(root, root.members())
|
||||||
|
// 累积结果
|
||||||
|
let mutable result_nodes: (int*Present.IDomUnit) list = []
|
||||||
|
|
||||||
|
interface AstImport.AstVisitor with
|
||||||
|
member this.visit(obj: AstImport.AstObject): bool =
|
||||||
|
let refs_depth = AstImport.depth_seek(forwards_map, obj)
|
||||||
|
let childs = result_nodes |> List.filter (fun (depth, _) -> depth > refs_depth)
|
||||||
|
|> List.map(fun (_, object) -> object)
|
||||||
|
|
||||||
|
let datas = match obj with
|
||||||
|
| :? AstImport.TextItem as text ->
|
||||||
|
(refs_depth, TextContent(text) :> Present.IDomUnit)::result_nodes
|
||||||
|
| :? AstImport.PointRef as refs ->
|
||||||
|
(refs_depth, PointRefer(refs, childs))::result_nodes
|
||||||
|
| :? AstImport.PointDef as defs ->
|
||||||
|
(refs_depth, PointDefine(defs, childs))::result_nodes
|
||||||
|
| :? AstImport.SliceDef as defs ->
|
||||||
|
(refs_depth, SliceDefine(defs, childs))::result_nodes
|
||||||
|
| :? AstImport.StoryDef as defs ->
|
||||||
|
(refs_depth, StoryDefine(defs, childs))::result_nodes
|
||||||
|
| :? AstImport.ArticleDef as defs ->
|
||||||
|
(refs_depth, ArticleDefine(defs, childs))::result_nodes
|
||||||
|
| :? AstImport.VolumeDef as defs ->
|
||||||
|
(refs_depth, VolumeDefine(defs, childs))::result_nodes
|
||||||
|
| :? AstImport.Program -> result_nodes
|
||||||
|
| _ -> raise (System.NotImplementedException())
|
||||||
|
|
||||||
|
result_nodes <- datas
|
||||||
|
if refs_depth > 0 then
|
||||||
|
result_nodes <- result_nodes |> List.filter(fun (depth, _) -> depth <= refs_depth)
|
||||||
|
true
|
||||||
|
|
||||||
|
member this.contents() =
|
||||||
|
result_nodes |> List.map(fun (_, obj) -> obj)
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
open AstAccess.AstImport
|
||||||
|
open HtmlStruct.Content
|
||||||
|
open System.Xml
|
||||||
|
|
||||||
|
let doc = XmlDocument()
|
||||||
|
doc.Load("E:/storyline.xast")
|
||||||
|
|
||||||
|
let prog = Program.GenerateFrom(doc)
|
||||||
|
|
||||||
|
let entry = AstVisitEntry(prog)
|
||||||
|
let visitor = UnitGenerate(prog)
|
||||||
|
entry.visitWith(visitor) |> ignore
|
||||||
|
|
||||||
|
for it in visitor.contents() do
|
||||||
|
printfn $"Name:{it.name()}"
|
|
@ -38,62 +38,102 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CoreTest", "CoreTest\CoreTe
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19} = {EF557F71-99AA-4F2B-A5F5-1A4518A11C19}
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19} = {EF557F71-99AA-4F2B-A5F5-1A4518A11C19}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AstConv", "AstConv\AstConv.fsproj", "{0C77216C-6484-4C94-BE06-D5D9FF18EA81}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x64.ActiveCfg = Debug|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x64.Build.0 = Debug|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x64.Build.0 = Debug|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x86.ActiveCfg = Debug|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x86.Build.0 = Debug|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x64.ActiveCfg = Release|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x64.Build.0 = Release|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x64.Build.0 = Release|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x86.ActiveCfg = Release|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x86.ActiveCfg = Release|x64
|
||||||
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x86.Build.0 = Release|x64
|
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x86.Build.0 = Release|x64
|
||||||
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x64.ActiveCfg = Debug|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x64.Build.0 = Debug|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x64.Build.0 = Debug|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x86.ActiveCfg = Debug|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x86.Build.0 = Debug|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x64.ActiveCfg = Release|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x64.ActiveCfg = Release|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x64.Build.0 = Release|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x64.Build.0 = Release|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x86.ActiveCfg = Release|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x86.ActiveCfg = Release|x64
|
||||||
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x86.Build.0 = Release|x64
|
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x86.Build.0 = Release|x64
|
||||||
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x64.ActiveCfg = Debug|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x64.Build.0 = Debug|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x64.Build.0 = Debug|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x86.ActiveCfg = Debug|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x86.Build.0 = Debug|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x64.ActiveCfg = Release|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x64.Build.0 = Release|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x64.Build.0 = Release|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x86.ActiveCfg = Release|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x86.ActiveCfg = Release|x64
|
||||||
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x86.Build.0 = Release|x64
|
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x86.Build.0 = Release|x64
|
||||||
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x64.ActiveCfg = Debug|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x64.Build.0 = Debug|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x64.Build.0 = Debug|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x86.ActiveCfg = Debug|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x86.Build.0 = Debug|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x64.ActiveCfg = Release|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x64.Build.0 = Release|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x64.Build.0 = Release|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x86.ActiveCfg = Release|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x86.ActiveCfg = Release|x64
|
||||||
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x86.Build.0 = Release|x64
|
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x86.Build.0 = Release|x64
|
||||||
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x64.ActiveCfg = Debug|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x64.Build.0 = Debug|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x64.Build.0 = Debug|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x86.ActiveCfg = Debug|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x86.Build.0 = Debug|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x64.ActiveCfg = Release|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x64.ActiveCfg = Release|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x64.Build.0 = Release|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x64.Build.0 = Release|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x86.ActiveCfg = Release|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x86.ActiveCfg = Release|x64
|
||||||
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x86.Build.0 = Release|x64
|
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x86.Build.0 = Release|x64
|
||||||
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x64.ActiveCfg = Debug|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x64.Build.0 = Debug|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x64.Build.0 = Debug|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x86.ActiveCfg = Debug|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x86.Build.0 = Debug|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x64.ActiveCfg = Release|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x64.ActiveCfg = Release|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x64.Build.0 = Release|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x64.Build.0 = Release|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x86.ActiveCfg = Release|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x86.ActiveCfg = Release|x64
|
||||||
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x86.Build.0 = Release|x64
|
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x86.Build.0 = Release|x64
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{0C77216C-6484-4C94-BE06-D5D9FF18EA81}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -6,708 +6,9 @@ using namespace example_novel;
|
||||||
using namespace printer;
|
using namespace printer;
|
||||||
using namespace lib_parse;
|
using namespace lib_parse;
|
||||||
|
|
||||||
Access::Access(std::shared_ptr<const ast_gen::ElementAccess> handle)
|
|
||||||
:access_handle(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<const ast_gen::ElementAccess> Access::accessPeers() const {
|
|
||||||
return access_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Access::setPageRefers(const QString& href) {
|
|
||||||
this->summary_refer_store = href;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Access::pageRefers() const {
|
|
||||||
return this->summary_refer_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
Element::Element(std::shared_ptr<const ast_gen::ElementAccess> handle) :Access(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void printer::Element::setSliceRefer(const QString& href) {
|
|
||||||
this->refer_store = href;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString printer::Element::sliceRefers() const {
|
|
||||||
return refer_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
Group::Group(std::shared_ptr<const ast_gen::ElementAccess> handle) : Access(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Group::append(std::shared_ptr<Element> elm) {
|
|
||||||
element_store.append(elm);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<std::shared_ptr<Element>> Group::elements() const {
|
|
||||||
return this->element_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Element> printer::Group::getElement(const QString& signature) const {
|
|
||||||
for (auto& it : elements()) {
|
|
||||||
if (it->accessPeers()->element()->signature() == signature)
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
StoryLine::StoryLine(std::shared_ptr<const ast_gen::ElementAccess> handle) :Group(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryLine::buildPageHTML(QDomElement& parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto storyline_inst = std::dynamic_pointer_cast<const StoryDefine>(syntax_access->element());
|
|
||||||
|
|
||||||
auto doc = parent.ownerDocument();
|
|
||||||
auto dom_storyline = doc.createElement("div");
|
|
||||||
parent.appendChild(dom_storyline);
|
|
||||||
|
|
||||||
auto dom_title = doc.createElement("h1");
|
|
||||||
dom_title.appendChild(doc.createTextNode(storyline_inst->name()));
|
|
||||||
dom_storyline.appendChild(dom_title);
|
|
||||||
|
|
||||||
for (auto& inst_c : syntax_access->children()) {
|
|
||||||
switch ((NovelNode) inst_c->element()->typeMark()) {
|
|
||||||
case NovelNode::TextSection:
|
|
||||||
{
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
||||||
auto dom_p = doc.createElement("p");
|
|
||||||
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
||||||
dom_storyline.appendChild(dom_p);
|
|
||||||
}break;
|
|
||||||
case NovelNode::PointRefers:
|
|
||||||
case NovelNode::PointDefines:
|
|
||||||
{
|
|
||||||
auto element_inst = this->getElement(inst_c->element()->signature());
|
|
||||||
element_inst->buildSliceHTML(dom_storyline);
|
|
||||||
}break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StoryVolume::StoryVolume(std::shared_ptr<const ast_gen::ElementAccess> handle) : Group(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryVolume::buildPageHTML(QDomElement& parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto volume_inst = std::dynamic_pointer_cast<const VolumeDefine>(syntax_access->element());
|
|
||||||
|
|
||||||
auto doc_inst = parent.ownerDocument();
|
|
||||||
auto dom_volume = doc_inst.createElement("div");
|
|
||||||
parent.appendChild(dom_volume);
|
|
||||||
|
|
||||||
auto dom_title = doc_inst.createElement("h1");
|
|
||||||
dom_title.appendChild(doc_inst.createTextNode(volume_inst->name()));
|
|
||||||
dom_volume.appendChild(dom_title);
|
|
||||||
|
|
||||||
std::function<void(QDomElement&, const QList<std::shared_ptr<const ast_gen::ElementAccess>>&)> rich_refer_build =
|
|
||||||
[&](QDomElement& parent_element, const QList<std::shared_ptr<const ast_gen::ElementAccess>> children) {
|
|
||||||
for (auto& child : children) {
|
|
||||||
auto doc_ins = parent_element.ownerDocument();
|
|
||||||
switch ((NovelNode) child->element()->typeMark()) {
|
|
||||||
case NovelNode::TextSection:
|
|
||||||
{
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
||||||
auto dom_p = doc_ins.createElement("p");
|
|
||||||
dom_p.appendChild(doc_ins.createTextNode(text_inst->content()));
|
|
||||||
parent_element.appendChild(dom_p);
|
|
||||||
}break;
|
|
||||||
case NovelNode::ArticleDefine:
|
|
||||||
{
|
|
||||||
auto article_inst = std::dynamic_pointer_cast<const ArticleDefine>(child->element());
|
|
||||||
auto article_group = doc_ins.createElement("div");
|
|
||||||
auto article_head = doc_ins.createElement("h2");
|
|
||||||
article_head.appendChild(doc_ins.createTextNode(article_inst->name() + "{"));
|
|
||||||
article_group.appendChild(article_head);
|
|
||||||
rich_refer_build(article_group, child->children());
|
|
||||||
article_group.appendChild(doc_ins.createTextNode("}"));
|
|
||||||
parent_element.appendChild(article_group);
|
|
||||||
}break;
|
|
||||||
case NovelNode::PointRefers:
|
|
||||||
{
|
|
||||||
auto fragment_inst = std::dynamic_pointer_cast<const PointRefers>(child->element());
|
|
||||||
auto refer_inst = this->getElement(fragment_inst->signature());
|
|
||||||
refer_inst->buildSliceHTML(parent_element);
|
|
||||||
}break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
rich_refer_build(dom_volume, syntax_access->children());
|
|
||||||
}
|
|
||||||
|
|
||||||
FragmentRef::FragmentRef(std::shared_ptr<const ast_gen::ElementAccess> handle) : Element(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void printer::FragmentRef::setHost(std::shared_ptr<Fragment> frag_inst) {
|
|
||||||
this->host_inst = frag_inst;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Fragment> printer::FragmentRef::hostFragment() const {
|
|
||||||
return this->host_inst.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FragmentRef::buildSliceHTML(QDomElement& dom_parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto refer_element = std::dynamic_pointer_cast<const PointRefers>(syntax_access->element());
|
|
||||||
|
|
||||||
auto jump_to_host = this->hostFragment()->pageRefers();
|
|
||||||
auto doc = dom_parent.ownerDocument();
|
|
||||||
|
|
||||||
auto dom_reference = doc.createElement("div");
|
|
||||||
dom_reference.setAttribute("id", QString::number((qulonglong) refer_element.get()));
|
|
||||||
dom_parent.appendChild(dom_reference);
|
|
||||||
|
|
||||||
auto dom_title = doc.createElement("h2");
|
|
||||||
dom_reference.appendChild(dom_title);
|
|
||||||
|
|
||||||
auto dom_href = doc.createElement("a");
|
|
||||||
dom_href.appendChild(doc.createTextNode(refer_element->referSignature()));
|
|
||||||
dom_href.setAttribute("href", "file:///" + jump_to_host);
|
|
||||||
dom_title.appendChild(dom_href);
|
|
||||||
|
|
||||||
std::function<void(QDomElement&, const QList<std::shared_ptr<const ast_gen::ElementAccess>>&)> rich_refer_build =
|
|
||||||
[&](QDomElement& parent_element, const QList<std::shared_ptr<const ast_gen::ElementAccess>> children) {
|
|
||||||
for (auto& child : children) {
|
|
||||||
auto doc_ins = parent_element.ownerDocument();
|
|
||||||
switch ((NovelNode) child->element()->typeMark()) {
|
|
||||||
case NovelNode::TextSection:
|
|
||||||
{
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
||||||
auto dom_p = doc_ins.createElement("p");
|
|
||||||
dom_p.appendChild(doc_ins.createTextNode(text_inst->content()));
|
|
||||||
parent_element.appendChild(dom_p);
|
|
||||||
}break;
|
|
||||||
case NovelNode::ArticleDefine:
|
|
||||||
{
|
|
||||||
auto article_inst = std::dynamic_pointer_cast<const ArticleDefine>(child->element());
|
|
||||||
auto article_group = doc_ins.createElement("div");
|
|
||||||
auto article_head = doc_ins.createElement("h2");
|
|
||||||
article_head.appendChild(doc_ins.createTextNode(article_inst->name() + "{"));
|
|
||||||
article_group.appendChild(article_head);
|
|
||||||
rich_refer_build(article_group, child->children());
|
|
||||||
article_group.appendChild(doc_ins.createTextNode("}"));
|
|
||||||
parent_element.appendChild(article_group);
|
|
||||||
}break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
rich_refer_build(dom_reference, syntax_access->children());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FragmentRef::buildPageHTML(QDomElement& parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto refer_element = std::dynamic_pointer_cast<const PointRefers>(syntax_access->element());
|
|
||||||
|
|
||||||
auto doc = parent.ownerDocument();
|
|
||||||
|
|
||||||
auto refers_dom = doc.createElement("div");
|
|
||||||
parent.appendChild(refers_dom);
|
|
||||||
|
|
||||||
auto title_block = doc.createElement("h2");
|
|
||||||
refers_dom.appendChild(title_block);
|
|
||||||
auto title_refer = doc.createElement("a");
|
|
||||||
title_refer.appendChild(doc.createTextNode(refer_element->signature()));
|
|
||||||
title_refer.setAttribute("href", "file:///" + this->sliceRefers());
|
|
||||||
title_block.appendChild(title_refer);
|
|
||||||
|
|
||||||
std::function<void(QList<std::shared_ptr<const ast_gen::ElementAccess>>)> build_cascade =
|
|
||||||
[&](QList<std::shared_ptr<const ast_gen::ElementAccess>> children_items) {
|
|
||||||
for (auto child : children_items) {
|
|
||||||
if (child->element()->typeMark() == (int) NovelNode::TextSection) {
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(child->element());
|
|
||||||
auto p = doc.createElement("p");
|
|
||||||
p.appendChild(doc.createTextNode(text_inst->content()));
|
|
||||||
refers_dom.appendChild(p);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
build_cascade(child->children());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
build_cascade(syntax_access->children());
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment::Fragment(std::shared_ptr<const ast_gen::ElementAccess> handle) : Element(handle) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fragment::appendRefers(std::shared_ptr<FragmentRef> inst) {
|
|
||||||
this->additionals_store.append(inst);
|
|
||||||
inst->setHost(std::static_pointer_cast<Fragment>(this->shared_from_this()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<std::shared_ptr<FragmentRef>> Fragment::additionals() const {
|
|
||||||
return this->additionals_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fragment::buildSliceHTML(QDomElement& parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto fragment_inst = std::dynamic_pointer_cast<const PointDefines>(syntax_access->element());
|
|
||||||
|
|
||||||
auto doc = parent.ownerDocument();
|
|
||||||
auto dom_fragment = doc.createElement("div");
|
|
||||||
dom_fragment.setAttribute("id", QString::number((qulonglong) fragment_inst.get()));
|
|
||||||
parent.appendChild(dom_fragment);
|
|
||||||
|
|
||||||
auto dom_title = doc.createElement("h2");
|
|
||||||
dom_fragment.appendChild(dom_title);
|
|
||||||
|
|
||||||
auto dom_href = doc.createElement("a");
|
|
||||||
dom_href.appendChild(doc.createTextNode(fragment_inst->name()));
|
|
||||||
dom_href.setAttribute("href", "file:///" + this->pageRefers());
|
|
||||||
dom_title.appendChild(dom_href);
|
|
||||||
|
|
||||||
for (auto& inst_c : syntax_access->children()) {
|
|
||||||
if (NovelNode::TextSection == (NovelNode) inst_c->element()->typeMark()) {
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
||||||
auto dom_p = doc.createElement("p");
|
|
||||||
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
||||||
dom_fragment.appendChild(dom_p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fragment::buildPageHTML(QDomElement& parent) const {
|
|
||||||
auto syntax_access = this->accessPeers();
|
|
||||||
auto fragment_inst = std::dynamic_pointer_cast<const PointDefines>(syntax_access->element());
|
|
||||||
|
|
||||||
auto doc = parent.ownerDocument();
|
|
||||||
auto dom_fragment = doc.createElement("div");
|
|
||||||
parent.appendChild(dom_fragment);
|
|
||||||
|
|
||||||
auto dom_title = doc.createElement("h1");
|
|
||||||
dom_fragment.appendChild(dom_title);
|
|
||||||
|
|
||||||
auto dom_href = doc.createElement("a");
|
|
||||||
dom_href.appendChild(doc.createTextNode(fragment_inst->signature()));
|
|
||||||
dom_href.setAttribute("href", "file:///" + this->sliceRefers());
|
|
||||||
dom_title.appendChild(dom_href);
|
|
||||||
|
|
||||||
for (auto& inst_c : syntax_access->children()) {
|
|
||||||
if (NovelNode::TextSection == (NovelNode) inst_c->element()->typeMark()) {
|
|
||||||
auto text_inst = std::dynamic_pointer_cast<const TextSection>(inst_c->element());
|
|
||||||
auto dom_p = doc.createElement("p");
|
|
||||||
dom_p.appendChild(doc.createTextNode(text_inst->content()));
|
|
||||||
dom_fragment.appendChild(dom_p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& it : this->additionals()) {
|
|
||||||
it->buildPageHTML(dom_fragment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <ast_novel.h>
|
|
||||||
void tools_printer::build_fragments(std::shared_ptr<const ast_gen::ElementAccess> novel_root) {
|
|
||||||
if (novel_root->element()->typeMark() == (int) NovelNode::PointDefines) {
|
|
||||||
auto inst = std::make_shared<Fragment>(novel_root);
|
|
||||||
auto name = novel_root->element()->signature();
|
|
||||||
this->fragment_defines[name] = inst;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst_c : novel_root->children()) {
|
|
||||||
build_fragments(inst_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tools_printer::build_refers_network(std::shared_ptr<const ast_gen::ElementAccess> novel_node) {
|
|
||||||
switch ((NovelNode) novel_node->element()->typeMark()) {
|
|
||||||
case NovelNode::StoryDefine:
|
|
||||||
{
|
|
||||||
auto storyinst = std::make_shared<StoryLine>(novel_node);
|
|
||||||
this->storyline_defines[novel_node->element()->signature()] = storyinst;
|
|
||||||
build_storyline(storyinst);
|
|
||||||
}return;
|
|
||||||
case NovelNode::VolumeDefine:
|
|
||||||
{
|
|
||||||
auto volumeinst = std::make_shared<StoryVolume>(novel_node);
|
|
||||||
this->volume_defines[novel_node->element()->signature()] = volumeinst;
|
|
||||||
build_volumeline(volumeinst);
|
|
||||||
}return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst_c : novel_node->children())
|
|
||||||
build_refers_network(inst_c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tools_printer::build_storyline(std::shared_ptr<StoryLine> line, std::shared_ptr<const ast_gen::ElementAccess> novel_node) {
|
|
||||||
if (!novel_node) {
|
|
||||||
for (auto& inst_c : line->accessPeers()->children()) {
|
|
||||||
build_storyline(line, inst_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch ((NovelNode) novel_node->element()->typeMark()) {
|
|
||||||
case NovelNode::PointDefines:
|
|
||||||
{
|
|
||||||
auto inst = this->fragment_defines[novel_node->element()->signature()];
|
|
||||||
line->append(inst);
|
|
||||||
}return;
|
|
||||||
case NovelNode::PointRefers:
|
|
||||||
{
|
|
||||||
auto refer_node = std::dynamic_pointer_cast<const PointRefers>(novel_node->element());
|
|
||||||
auto refer_fragment = this->fragment_defines[refer_node->referSignature()];
|
|
||||||
auto inst = std::make_shared<FragmentRef>(novel_node);
|
|
||||||
refer_fragment->appendRefers(inst);
|
|
||||||
line->append(inst);
|
|
||||||
}return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst_c : novel_node->children())
|
|
||||||
build_storyline(line, inst_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tools_printer::build_volumeline(std::shared_ptr<StoryVolume> volume, std::shared_ptr<const ast_gen::ElementAccess> novel_node) {
|
|
||||||
if (!novel_node) {
|
|
||||||
for (auto& inst_c : volume->accessPeers()->children())
|
|
||||||
build_volumeline(volume, inst_c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (NovelNode::PointRefers == (NovelNode) novel_node->element()->typeMark()) {
|
|
||||||
auto refer_node = std::dynamic_pointer_cast<const PointRefers>(novel_node->element());
|
|
||||||
auto refer_fragment = this->fragment_defines[refer_node->referSignature()];
|
|
||||||
auto inst = std::make_shared<FragmentRef>(novel_node);
|
|
||||||
refer_fragment->appendRefers(inst);
|
|
||||||
volume->append(inst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst_c : novel_node->children())
|
|
||||||
build_volumeline(volume, inst_c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tools_printer::fragments_anchors_define(const QList<std::shared_ptr<Fragment>>& list, const QDir& root_dir) {
|
|
||||||
auto path = root_dir.filePath("fragments");
|
|
||||||
if (!QDir(path).exists())
|
|
||||||
root_dir.mkdir("fragments");
|
|
||||||
QDir target_dir(path);
|
|
||||||
|
|
||||||
for (auto& it : list) {
|
|
||||||
auto address_x = QString::number((qulonglong) it->accessPeers()->element().get());
|
|
||||||
it->setPageRefers(target_dir.absoluteFilePath(QString("%1.html").arg(address_x)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void(const QList<std::shared_ptr<Element>>&, const QString&)> refers_refresh =
|
|
||||||
[&](const QList<std::shared_ptr<Element>>& items, const QString& summary_href) {
|
|
||||||
for (auto& item : items) {
|
|
||||||
auto element_addr = QString::number((qulonglong) item->accessPeers()->element().get());
|
|
||||||
item->setSliceRefer(summary_href + "#" + element_addr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void tools_printer::storylines_anchors_define(const QList<std::shared_ptr<StoryLine>>& list, const QDir& root_dir) {
|
|
||||||
auto path = root_dir.filePath("storylines");
|
|
||||||
if (!QDir(path).exists())
|
|
||||||
root_dir.mkdir("storylines");
|
|
||||||
QDir target_dir(path);
|
|
||||||
|
|
||||||
for (auto& it : list) {
|
|
||||||
auto address_x = QString::number((qulonglong) it->accessPeers()->element().get());
|
|
||||||
auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x));
|
|
||||||
it->setPageRefers(page_address);
|
|
||||||
refers_refresh(it->elements(), page_address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tools_printer::volumes_anchors_define(const QList<std::shared_ptr<StoryVolume>>& list, const QDir& root_dir) {
|
|
||||||
auto path = root_dir.filePath("volumes");
|
|
||||||
if (!QDir(path).exists())
|
|
||||||
root_dir.mkdir("volumes");
|
|
||||||
QDir target_dir(path);
|
|
||||||
|
|
||||||
for (auto& it : list) {
|
|
||||||
auto address_x = QString::number((qulonglong) it->accessPeers()->element().get());
|
|
||||||
auto page_address = target_dir.absoluteFilePath(QString("%1.html").arg(address_x));
|
|
||||||
it->setPageRefers(page_address);
|
|
||||||
refers_refresh(it->elements(), page_address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get_node_name = [](const std::shared_ptr<Access> item) {
|
|
||||||
return "node_" + QString::number((qulonglong) item->accessPeers()->element().get());
|
|
||||||
};
|
|
||||||
|
|
||||||
QString printer::tools_printer::storylines_paint(const QList<std::shared_ptr<StoryLine>>& lines) {
|
|
||||||
QHash<QString, std::shared_ptr<Access>> node_records;
|
|
||||||
QString nodes_description;
|
|
||||||
for (auto& story : lines) {
|
|
||||||
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
||||||
node_records[story_elem->signature()] = story;
|
|
||||||
nodes_description += get_node_name(story) + QString("[fillcolor=pink,label=\"%1{%2}\",shape=\"cds\"]\n").arg(story_elem->name()).arg(story_elem->sort());
|
|
||||||
|
|
||||||
for (auto& frag : story->elements()) {
|
|
||||||
auto fragment_peers = frag->accessPeers()->element();
|
|
||||||
if (fragment_peers->typeMark() == (int) example_novel::NovelNode::PointDefines) {
|
|
||||||
auto fragment_elem = std::dynamic_pointer_cast<const example_novel::PointDefines>(fragment_peers);
|
|
||||||
auto node_name = fragment_elem->signature();
|
|
||||||
node_records[node_name] = frag;
|
|
||||||
|
|
||||||
nodes_description += get_node_name(frag) + QString("[label=\"{%2}::%1\",shape=\"rect\"]\n")
|
|
||||||
.arg(fragment_elem->name()).arg(story_elem->sort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString arrows_link;
|
|
||||||
for (auto& story : lines) {
|
|
||||||
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
||||||
|
|
||||||
QString previous_node = get_node_name(story);
|
|
||||||
for (auto& frag : story->elements()) {
|
|
||||||
if (example_novel::NovelNode::PointDefines == (example_novel::NovelNode) frag->accessPeers()->element()->typeMark()) {
|
|
||||||
arrows_link += previous_node + "->" + get_node_name(frag) + QString("[label=\"%1{%2}\"]\n")
|
|
||||||
.arg(story_elem->name()).arg(story_elem->sort());
|
|
||||||
previous_node = get_node_name(frag);
|
|
||||||
}
|
|
||||||
else if (example_novel::NovelNode::PointRefers == (example_novel::NovelNode) frag->accessPeers()->element()->typeMark()) {
|
|
||||||
auto frag_refer = std::dynamic_pointer_cast<const example_novel::PointRefers>(frag->accessPeers()->element());
|
|
||||||
auto frag_src = node_records[frag_refer->referSignature()];
|
|
||||||
arrows_link += previous_node + "->" + get_node_name(frag_src) + QString("[label=\"%1{%2}\"]\n")
|
|
||||||
.arg(story_elem->name()).arg(story_elem->sort());
|
|
||||||
previous_node = get_node_name(frag_src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString("digraph{ rankdir = LR \n node[style=filled] \n %1\n %2 }").arg(nodes_description).arg(arrows_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString printer::tools_printer::volumes_paint(const QList<std::shared_ptr<StoryVolume>>& vols, const QList<std::shared_ptr<StoryLine>>& lines) {
|
|
||||||
QHash<QString, std::shared_ptr<Element>> node_records;
|
|
||||||
|
|
||||||
QString clusters_description;
|
|
||||||
for (auto& story : lines) {
|
|
||||||
QString nodes_description;
|
|
||||||
for (auto& frag : story->elements()) {
|
|
||||||
auto fragment_peers = frag->accessPeers()->element();
|
|
||||||
if (fragment_peers->typeMark() == (int) example_novel::NovelNode::PointDefines) {
|
|
||||||
auto fragment_elem = std::dynamic_pointer_cast<const example_novel::PointDefines>(fragment_peers);
|
|
||||||
node_records[fragment_elem->signature()] = frag;
|
|
||||||
nodes_description += get_node_name(frag) + QString("[label=\"%1\",shape=\"ellipse\"]\n").arg(fragment_elem->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto story_elem = std::dynamic_pointer_cast<const example_novel::StoryDefine>(story->accessPeers()->element());
|
|
||||||
clusters_description += QString("subgraph cluster_%1 { label=%3 \n %2 }")
|
|
||||||
.arg((qulonglong) story_elem.get()).arg(nodes_description).arg(story_elem->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto article_cluster = [&node_records](const std::shared_ptr<const ast_gen::ElementAccess> article_access, QList<QString>& arrows_out)->QString {
|
|
||||||
QString nodes_description;
|
|
||||||
for (auto& fragment_access : article_access->children()) {
|
|
||||||
if (fragment_access->element()->typeMark() == (int) example_novel::NovelNode::PointRefers) {
|
|
||||||
auto refer_fragment = std::dynamic_pointer_cast<const example_novel::PointRefers>(fragment_access->element());
|
|
||||||
nodes_description += QString("fragment_%1[label=\"%2\",shape=\"plaintext\"]\n")
|
|
||||||
.arg((qulonglong) refer_fragment.get()).arg(refer_fragment->sliceRefer());
|
|
||||||
auto symbo_refer = node_records[refer_fragment->referSignature()];
|
|
||||||
arrows_out << QString("fragment_%1 -- %2[color=\"red\"]\n").arg((qulonglong) refer_fragment.get()).arg(get_node_name(symbo_refer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto article_define = std::dynamic_pointer_cast<const example_novel::ArticleDefine>(article_access->element());
|
|
||||||
return QString("subgraph cluster_%1{ label=%2 \n %3 }\n").arg((qulonglong) article_access->element().get())
|
|
||||||
.arg(article_define->name()).arg(nodes_description);
|
|
||||||
};
|
|
||||||
|
|
||||||
QString arrows_link;
|
|
||||||
for (auto& vol : vols) {
|
|
||||||
QString members_description;
|
|
||||||
for (auto& eref : vol->accessPeers()->children()) {
|
|
||||||
QList<QString> arrows_temp;
|
|
||||||
switch ((example_novel::NovelNode) eref->element()->typeMark()) {
|
|
||||||
case example_novel::NovelNode::ArticleDefine:
|
|
||||||
members_description += article_cluster(eref, arrows_temp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (auto& arrow : arrows_temp) {
|
|
||||||
arrows_link += arrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto volume_elem = std::dynamic_pointer_cast<const example_novel::VolumeDefine>(vol->accessPeers()->element());
|
|
||||||
clusters_description += QString("subgraph cluster_%1 { label=%3 \n %2 }")
|
|
||||||
.arg((qulonglong) volume_elem.get()).arg(members_description).arg(volume_elem->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString("graph scale{ %1 \n %2}").arg(clusters_description).arg(arrows_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
void printer::tools_printer::plain_html_output(const std::shared_ptr<const ast_gen::ElementAccess> access_ptr, const QDir& destination_dir) const {
|
|
||||||
QTime time_stamp = QTime::currentTime();
|
|
||||||
auto tool = *this;
|
|
||||||
tool.build_fragments(access_ptr);
|
|
||||||
tool.build_refers_network(access_ptr);
|
|
||||||
|
|
||||||
tool.fragments_anchors_define(tool.fragment_defines.values(), destination_dir);
|
|
||||||
tool.storylines_anchors_define(tool.storyline_defines.values(), destination_dir);
|
|
||||||
tool.volumes_anchors_define(tool.volume_defines.values(), destination_dir);
|
|
||||||
|
|
||||||
std::function<void(std::shared_ptr<const printer::Access>)> html_output =
|
|
||||||
[](std::shared_ptr<const printer::Access> inst) {
|
|
||||||
auto target_path = inst->pageRefers();
|
|
||||||
QFile tfile(target_path);
|
|
||||||
if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
QDomDocument doc_inst(QDomImplementation().createDocumentType("html", QString(), QString()));
|
|
||||||
auto html = doc_inst.createElement("html");
|
|
||||||
doc_inst.appendChild(html);
|
|
||||||
|
|
||||||
auto body = doc_inst.createElement("body");
|
|
||||||
html.appendChild(body);
|
|
||||||
|
|
||||||
inst->buildPageHTML(body);
|
|
||||||
|
|
||||||
QTextStream tout(&tfile);
|
|
||||||
doc_inst.save(tout, 2);
|
|
||||||
tout.flush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto& node : tool.fragment_defines)
|
|
||||||
html_output(node);
|
|
||||||
for (auto& node : tool.storyline_defines)
|
|
||||||
html_output(node);
|
|
||||||
for (auto& node : tool.volume_defines)
|
|
||||||
html_output(node);
|
|
||||||
|
|
||||||
QDir::setCurrent(destination_dir.canonicalPath());
|
|
||||||
auto dot_src = tool.storylines_paint(tool.storyline_defines.values());
|
|
||||||
QFile dot_file(QDir::current().filePath("relates.dot"));
|
|
||||||
if (dot_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
QTextStream txt(&dot_file);
|
|
||||||
txt.setCodec("UTF-8");
|
|
||||||
txt << dot_src;
|
|
||||||
txt.flush();
|
|
||||||
}
|
|
||||||
system("dot -Tsvg relates.dot -o relates.svg");
|
|
||||||
|
|
||||||
auto vols_src = tool.volumes_paint(tool.volume_defines.values(), tool.storyline_defines.values());
|
|
||||||
QFile vols_file(QDir::current().filePath("volumes_group.dot"));
|
|
||||||
if (vols_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
QTextStream txt(&vols_file);
|
|
||||||
txt.setCodec("UTF-8");
|
|
||||||
txt << vols_src;
|
|
||||||
txt.flush();
|
|
||||||
}
|
|
||||||
system("fdp -Tsvg volumes_group.dot -o volumes_group.svg");
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
QFile tfile("./index.html");
|
|
||||||
if (tfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
QDomDocument doc_inst(QDomImplementation().createDocumentType("html", QString(), QString()));
|
|
||||||
auto html = doc_inst.createElement("html");
|
|
||||||
doc_inst.appendChild(html);
|
|
||||||
|
|
||||||
auto body = doc_inst.createElement("body");
|
|
||||||
html.appendChild(body);
|
|
||||||
|
|
||||||
auto dom_storyline = doc_inst.createElement("div");
|
|
||||||
auto dom_storyline_title = doc_inst.createElement("h2");
|
|
||||||
dom_storyline_title.appendChild(doc_inst.createTextNode("故事脉络"));
|
|
||||||
dom_storyline.appendChild(dom_storyline_title);
|
|
||||||
body.appendChild(dom_storyline);
|
|
||||||
|
|
||||||
auto lines = tool.storyline_defines.values();
|
|
||||||
std::sort(lines.begin(), lines.end(), [](std::shared_ptr<printer::StoryLine> a, std::shared_ptr<printer::StoryLine> b)->bool {
|
|
||||||
auto a_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(a->accessPeers()->element());
|
|
||||||
auto b_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(b->accessPeers()->element());
|
|
||||||
return a_elm->sort() < b_elm->sort();
|
|
||||||
});
|
|
||||||
for (auto& inst_line : lines) {
|
|
||||||
auto dom_line = doc_inst.createElement("p");
|
|
||||||
dom_storyline.appendChild(dom_line);
|
|
||||||
|
|
||||||
auto line_href = doc_inst.createElement("a");
|
|
||||||
line_href.setAttribute("href", "file:///" + inst_line->pageRefers());
|
|
||||||
auto a_elm = std::dynamic_pointer_cast<const example_novel::StoryDefine>(inst_line->accessPeers()->element());
|
|
||||||
line_href.appendChild(doc_inst.createTextNode(QString("%1.%2").arg(a_elm->sort()).arg(a_elm->signature())));
|
|
||||||
dom_line.appendChild(line_href);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dom_volume = doc_inst.createElement("div");
|
|
||||||
auto dom_volume_title = doc_inst.createElement("h2");
|
|
||||||
dom_volume_title.appendChild(doc_inst.createTextNode("分卷内容"));
|
|
||||||
dom_volume.appendChild(dom_volume_title);
|
|
||||||
body.appendChild(dom_volume);
|
|
||||||
|
|
||||||
for (auto& inst_volume : tool.volume_defines) {
|
|
||||||
auto dom_volume_ref = doc_inst.createElement("p");
|
|
||||||
dom_volume.appendChild(dom_volume_ref);
|
|
||||||
|
|
||||||
auto volume_href = doc_inst.createElement("a");
|
|
||||||
volume_href.setAttribute("href", "file:///" + inst_volume->pageRefers());
|
|
||||||
volume_href.appendChild(doc_inst.createTextNode(inst_volume->accessPeers()->element()->signature()));
|
|
||||||
dom_volume_ref.appendChild(volume_href);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dom_fragment = doc_inst.createElement("div");
|
|
||||||
auto dom_fragment_title = doc_inst.createElement("h2");
|
|
||||||
dom_fragment_title.appendChild(doc_inst.createTextNode("情节集合"));
|
|
||||||
dom_fragment.appendChild(dom_fragment_title);
|
|
||||||
body.appendChild(dom_fragment);
|
|
||||||
|
|
||||||
auto table_cube = doc_inst.createElement("table");
|
|
||||||
dom_fragment.appendChild(table_cube);
|
|
||||||
|
|
||||||
int row_ctrl = 0;
|
|
||||||
QDomElement elm_row;
|
|
||||||
for (auto& inst_frag : tool.fragment_defines) {
|
|
||||||
if (row_ctrl++ % 4 == 0) {
|
|
||||||
elm_row = doc_inst.createElement("tr");
|
|
||||||
table_cube.appendChild(elm_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dom_fragment_ref = doc_inst.createElement("td");
|
|
||||||
elm_row.appendChild(dom_fragment_ref);
|
|
||||||
|
|
||||||
auto frag_href = doc_inst.createElement("a");
|
|
||||||
frag_href.setAttribute("href", "file:///" + inst_frag->pageRefers());
|
|
||||||
frag_href.appendChild(doc_inst.createTextNode(inst_frag->accessPeers()->element()->signature()));
|
|
||||||
dom_fragment_ref.appendChild(frag_href);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dom_relate = doc_inst.createElement("div");
|
|
||||||
auto dom_relate_title = doc_inst.createElement("h2");
|
|
||||||
dom_relate_title.appendChild(doc_inst.createTextNode("联系图"));
|
|
||||||
dom_relate.appendChild(dom_relate_title);
|
|
||||||
body.appendChild(dom_relate);
|
|
||||||
|
|
||||||
auto img = doc_inst.createElement("img");
|
|
||||||
img.setAttribute("src", "file:///" + QDir::current().filePath("relates.svg"));
|
|
||||||
dom_relate.appendChild(img);
|
|
||||||
dom_relate.appendChild(doc_inst.createElement("br"));
|
|
||||||
img = doc_inst.createElement("img");
|
|
||||||
img.setAttribute("src", "file:///" + QDir::current().filePath("volumes_group.svg"));
|
|
||||||
dom_relate.appendChild(img);
|
|
||||||
|
|
||||||
QTextStream tout(&tfile);
|
|
||||||
doc_inst.save(tout, 2);
|
|
||||||
tout.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto current_stamp = QTime::currentTime();
|
|
||||||
qDebug().noquote() << QString("%html构建消耗时间:%1 ms。").arg(time_stamp.msecsTo(current_stamp));
|
|
||||||
qDebug().noquote() << "%编译成功:" << destination_dir.absoluteFilePath("index.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printer::AstGenerate::append_tokens(QDomElement _elm, std::shared_ptr<const ast_gen::SyntaxElement> inst) {
|
void printer::AstGenerate::append_tokens(QDomElement _elm, std::shared_ptr<const ast_gen::SyntaxElement> inst) {
|
||||||
auto dom_tokens = doc.createElement("tokens");
|
auto dom_tokens = doc.createElement("tokens");
|
||||||
|
|
|
@ -8,175 +8,6 @@
|
||||||
#include <parse_novel.h>
|
#include <parse_novel.h>
|
||||||
|
|
||||||
namespace printer {
|
namespace printer {
|
||||||
/**
|
|
||||||
* 概括页面
|
|
||||||
* 故事分卷汇总
|
|
||||||
* 故事脉络汇总
|
|
||||||
* 故事脉络关系图.
|
|
||||||
*
|
|
||||||
* 故事脉络发展页面
|
|
||||||
* 故事剧情节点汇总
|
|
||||||
* 内容展示
|
|
||||||
*
|
|
||||||
* 剧情节点汇总页面
|
|
||||||
* 引用来源汇总
|
|
||||||
* 各节点内容展示
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 所有可访问元素的基类:卷宗、章节、故事线、剧情、节点、引用等
|
|
||||||
*/
|
|
||||||
class Access : public std::enable_shared_from_this<Access> {
|
|
||||||
public:
|
|
||||||
Access(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
virtual ~Access() = default;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 获取绑定的语法元素
|
|
||||||
* @return 元素内存指针
|
|
||||||
*/
|
|
||||||
std::shared_ptr<const ast_gen::ElementAccess> accessPeers() const;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 设置汇总页面路径
|
|
||||||
* @param href 页面路径
|
|
||||||
*/
|
|
||||||
void setPageRefers(const QString& href);
|
|
||||||
QString pageRefers() const;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 获取汇总页面的HTML
|
|
||||||
*/
|
|
||||||
virtual void buildPageHTML(QDomElement& doc) const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<const ast_gen::ElementAccess> access_handle;
|
|
||||||
QString summary_refer_store;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 可访问片段元素:故事片段本篇,故事片段引用
|
|
||||||
*/
|
|
||||||
class Element : public Access {
|
|
||||||
public:
|
|
||||||
Element(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
virtual ~Element() = default;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 设置片段URL,从故事汇总页面跳转回出处页面
|
|
||||||
*/
|
|
||||||
virtual void setSliceRefer(const QString& href);
|
|
||||||
virtual QString sliceRefers() const;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 获取故事片段出处的节点HTML
|
|
||||||
*/
|
|
||||||
virtual void buildSliceHTML(QDomElement &doc) const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString refer_store;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 可访问集合的基类:故事线、剧情节点、故事卷宗
|
|
||||||
*/
|
|
||||||
class Group : public Access {
|
|
||||||
public:
|
|
||||||
Group(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
virtual ~Group() = default;
|
|
||||||
|
|
||||||
void append(std::shared_ptr<Element> elm);
|
|
||||||
QList<std::shared_ptr<Element>> elements() const;
|
|
||||||
std::shared_ptr<Element> getElement(const QString& signature) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<std::shared_ptr<Element>> element_store;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StoryLine : public Group {
|
|
||||||
public:
|
|
||||||
StoryLine(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
|
|
||||||
// 通过 Group 继承
|
|
||||||
void buildPageHTML(QDomElement& doc) const override;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class StoryVolume : public Group {
|
|
||||||
public:
|
|
||||||
StoryVolume(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
|
|
||||||
// 通过 Group 继承
|
|
||||||
void buildPageHTML(QDomElement& doc) const override;
|
|
||||||
|
|
||||||
};
|
|
||||||
class Fragment;
|
|
||||||
/*
|
|
||||||
* @brief 情节片段引用定义
|
|
||||||
*/
|
|
||||||
class FragmentRef : public Element {
|
|
||||||
public:
|
|
||||||
FragmentRef(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
|
|
||||||
void setHost(std::shared_ptr<Fragment> frag_inst);
|
|
||||||
std::shared_ptr<Fragment> hostFragment() const;
|
|
||||||
|
|
||||||
// 通过 Access 继承
|
|
||||||
void buildPageHTML(QDomElement& doc) const override;
|
|
||||||
|
|
||||||
// 通过 Element 继承
|
|
||||||
void buildSliceHTML(QDomElement& doc) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::weak_ptr<Fragment> host_inst;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 情节片段本篇定义,存储情节引用定义
|
|
||||||
*/
|
|
||||||
class Fragment : public Element{
|
|
||||||
private:
|
|
||||||
QList<std::shared_ptr<FragmentRef>> additionals_store;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Fragment(std::shared_ptr<const ast_gen::ElementAccess> handle);
|
|
||||||
|
|
||||||
void appendRefers(std::shared_ptr<FragmentRef> inst);
|
|
||||||
QList<std::shared_ptr<FragmentRef>> additionals() const;
|
|
||||||
|
|
||||||
// 通过 Access 继承
|
|
||||||
void buildPageHTML(QDomElement& doc) const override;
|
|
||||||
|
|
||||||
// 通过 Element 继承
|
|
||||||
void buildSliceHTML(QDomElement& doc) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class tools_printer {
|
|
||||||
public:
|
|
||||||
QHash<QString, std::shared_ptr<Fragment>> fragment_defines;
|
|
||||||
QHash<QString, std::shared_ptr<StoryLine>> storyline_defines;
|
|
||||||
QHash<QString, std::shared_ptr<StoryVolume>> volume_defines;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void build_fragments(std::shared_ptr<const ast_gen::ElementAccess> novel_root);
|
|
||||||
|
|
||||||
void build_refers_network(std::shared_ptr<const ast_gen::ElementAccess> novel_node);
|
|
||||||
|
|
||||||
void build_storyline(std::shared_ptr<StoryLine> line, std::shared_ptr<const ast_gen::ElementAccess> novel_node = nullptr);
|
|
||||||
void build_volumeline(std::shared_ptr<StoryVolume> line, std::shared_ptr<const ast_gen::ElementAccess> novel_node = nullptr);
|
|
||||||
|
|
||||||
void fragments_anchors_define(const QList<std::shared_ptr<Fragment>> &list, const QDir &destdir);
|
|
||||||
void storylines_anchors_define(const QList<std::shared_ptr<StoryLine>> &list, const QDir &destdir);
|
|
||||||
void volumes_anchors_define(const QList<std::shared_ptr<StoryVolume>> &list, const QDir &destdir);
|
|
||||||
|
|
||||||
QString storylines_paint(const QList<std::shared_ptr<StoryLine>> &lines);
|
|
||||||
QString volumes_paint(const QList<std::shared_ptr<StoryVolume>> &vols, const QList<std::shared_ptr<StoryLine>> &lines);
|
|
||||||
|
|
||||||
void plain_html_output(const std::shared_ptr<const ast_gen::ElementAccess> root, const QDir &destinationdir) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Ast输出构建器.
|
* @brief Ast输出构建器.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -34,8 +34,7 @@ int main(int argc, char* argv[]) {
|
||||||
args_parser << build_mode;
|
args_parser << build_mode;
|
||||||
*build_mode << make_shared<IndexParam>("nsc", "程序名称")
|
*build_mode << make_shared<IndexParam>("nsc", "程序名称")
|
||||||
<< make_shared<FloatKeyValue>("path", "指定源代码目录")
|
<< make_shared<FloatKeyValue>("path", "指定源代码目录")
|
||||||
<< make_shared<FloatKeyValue>("dest", "指定生成目录")
|
<< make_shared<FloatKeyValue>("dest", "指定生成目录");
|
||||||
<< make_shared<FloatOption>("html", "生成html文件格式取代AST", true);
|
|
||||||
|
|
||||||
|
|
||||||
auto p_result = args_parser.parse(argc, argv);
|
auto p_result = args_parser.parse(argc, argv);
|
||||||
|
@ -49,7 +48,6 @@ int main(int argc, char* argv[]) {
|
||||||
{
|
{
|
||||||
auto src_dir = dynamic_pointer_cast<FloatKeyValue>(p_result->getUnitViaKey("path"));
|
auto src_dir = dynamic_pointer_cast<FloatKeyValue>(p_result->getUnitViaKey("path"));
|
||||||
auto dst_dir = dynamic_pointer_cast<FloatKeyValue>(p_result->getUnitViaKey("dest"));
|
auto dst_dir = dynamic_pointer_cast<FloatKeyValue>(p_result->getUnitViaKey("dest"));
|
||||||
auto html_opt = dynamic_pointer_cast<FloatOption>(p_result->getUnitViaKey("html"));
|
|
||||||
|
|
||||||
auto source_dir = QDir(src_dir->value().toString());
|
auto source_dir = QDir(src_dir->value().toString());
|
||||||
if (!source_dir.exists()) {
|
if (!source_dir.exists()) {
|
||||||
|
@ -93,11 +91,7 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (html_opt->value().toInt() == 1 && access_ptr) {
|
if (access_ptr) {
|
||||||
printer::tools_printer tool;
|
|
||||||
tool.plain_html_output(access_ptr, destination_dir);
|
|
||||||
}
|
|
||||||
else if (access_ptr) {
|
|
||||||
QTime time_stamp = QTime::currentTime();
|
QTime time_stamp = QTime::currentTime();
|
||||||
lib_parse::VisitEntry control;
|
lib_parse::VisitEntry control;
|
||||||
auto visitor = make_shared<printer::AstGenerate>(source_dir);
|
auto visitor = make_shared<printer::AstGenerate>(source_dir);
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace lib_syntax {
|
||||||
MatchCursor(std::shared_ptr<const MatchCursor> other_ptr);
|
MatchCursor(std::shared_ptr<const MatchCursor> other_ptr);
|
||||||
virtual ~MatchCursor() = default;
|
virtual ~MatchCursor() = default;
|
||||||
|
|
||||||
bool operator>(const MatchCursor & other) const;
|
bool operator>(const MatchCursor& other) const;
|
||||||
|
|
||||||
virtual std::shared_ptr<const MatchCursor> previous() const;
|
virtual std::shared_ptr<const MatchCursor> previous() const;
|
||||||
virtual QString filePath() const;
|
virtual QString filePath() const;
|
||||||
|
@ -195,7 +195,8 @@ namespace lib_syntax {
|
||||||
std::shared_ptr<const lib_token::ITokenProcess> _define_peers;
|
std::shared_ptr<const lib_token::ITokenProcess> _define_peers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__token_match_impl(std::shared_ptr<const lib_token::ITokenProcess> define) : _define_peers(define) { }
|
__token_match_impl(std::shared_ptr<const lib_token::ITokenProcess> define) : _define_peers(define) {
|
||||||
|
}
|
||||||
|
|
||||||
// IBasicRule interface
|
// IBasicRule interface
|
||||||
public:
|
public:
|
||||||
|
@ -293,7 +294,8 @@ namespace lib_syntax {
|
||||||
class ElementRule : public ExprRule {
|
class ElementRule : public ExprRule {
|
||||||
public:
|
public:
|
||||||
ElementRule(const QString& rule_name)
|
ElementRule(const QString& rule_name)
|
||||||
:ExprRule(rule_name, mark), _children_store(std::make_shared<R>()) { }
|
:ExprRule(rule_name, mark), _children_store(std::make_shared<R>()) {
|
||||||
|
}
|
||||||
|
|
||||||
virtual QList<std::shared_ptr<const IBasicRule>> children() const {
|
virtual QList<std::shared_ptr<const IBasicRule>> children() const {
|
||||||
return QList<std::shared_ptr<const IBasicRule>>() << this->_children_store;
|
return QList<std::shared_ptr<const IBasicRule>>() << this->_children_store;
|
||||||
|
@ -337,16 +339,10 @@ namespace lib_syntax {
|
||||||
[](std::shared_ptr<const MatchCursor> ins) { return !ins->parseFailure(); });
|
[](std::shared_ptr<const MatchCursor> ins) { return !ins->parseFailure(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!branch_procs.size())
|
// 表达式匹配结尾
|
||||||
branch_procs = nbranch;
|
if (branch_procs.size()) {
|
||||||
|
|
||||||
|
|
||||||
decltype(nbranch) results_fnl;
|
decltype(nbranch) results_fnl;
|
||||||
for (auto curs : branch_procs) {
|
for (auto curs : branch_procs) {
|
||||||
if (curs->parseFailure()) {
|
|
||||||
results_fnl.append(curs);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto t_end = curs->token();
|
auto t_end = curs->token();
|
||||||
auto w_end = curs->words();
|
auto w_end = curs->words();
|
||||||
|
|
||||||
|
@ -363,9 +359,11 @@ namespace lib_syntax {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return results_fnl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return results_fnl;
|
// 匹配失败
|
||||||
|
return branch_procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue