This commit is contained in:
codeboss 2025-02-19 13:43:34 +08:00
parent 74ce31b072
commit 872f874d22
12 changed files with 723 additions and 896 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
*/x64/*
.vs/*
x64/*
*/bin/*
*/obj/*

View File

@ -132,7 +132,7 @@ int MatchMode::modeCode() const {
return code_store;
}
QString MatchMode::usageString() const {
QString MatchMode::usagestring() const {
QString usage_string;
for (auto& item : args_mode)
usage_string += item->placeHolder() + " ";
@ -140,7 +140,7 @@ QString MatchMode::usageString() const {
return usage_string;
}
QString MatchMode::explanString() const {
QString MatchMode::explanstring() const {
QStringList sections;
sections << " " + _means_explain;
sections << QString(" Switch:");
@ -235,8 +235,8 @@ std::shared_ptr<IArgvPack> MatchMode::getUnitViaInitIndex(int pos) {
QString ArgsParser::helperDoc() const {
QString help_string;
for (auto& mode : this->match_modes) {
help_string += "Usage:" + mode->usageString() + "\n";
help_string += mode->explanString() + "\n\n";
help_string += "Usage:" + mode->usagestring() + "\n";
help_string += mode->explanstring() + "\n\n";
}
return help_string;
}

View File

@ -162,14 +162,14 @@ namespace args_parse {
*
* \return
*/
QString usageString() const;
QString usagestring() const;
/**
* .
*
* \return
*/
QString explanString() const;
QString explanstring() const;
/**
* .

14
AstConv/AstConv.fsproj Normal file
View File

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

366
AstConv/AstImport.fs Normal file
View File

@ -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
/// 1node
/// 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

266
AstConv/HtmlStruct.fs Normal file
View File

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

15
AstConv/Program.fs Normal file
View File

@ -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()}"

View File

@ -38,62 +38,102 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CoreTest", "CoreTest\CoreTe
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19} = {EF557F71-99AA-4F2B-A5F5-1A4518A11C19}
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AstConv", "AstConv\AstConv.fsproj", "{0C77216C-6484-4C94-BE06-D5D9FF18EA81}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
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.Build.0 = 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}.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.Build.0 = Release|x64
{1EF577E8-D92D-4926-9207-1567137BB672}.Release|x86.ActiveCfg = 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.Build.0 = 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}.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.Build.0 = Release|x64
{EF557F71-99AA-4F2B-A5F5-1A4518A11C19}.Release|x86.ActiveCfg = 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.Build.0 = 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}.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.Build.0 = Release|x64
{C3AADEB5-3695-4DF4-B8E1-D37F928F3B2F}.Release|x86.ActiveCfg = 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.Build.0 = 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}.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.Build.0 = Release|x64
{1FF80476-26C9-42FB-BFF6-D587C4941964}.Release|x86.ActiveCfg = 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.Build.0 = 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}.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.Build.0 = Release|x64
{386F6D42-C6EB-4973-9511-181472391B21}.Release|x86.ActiveCfg = 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.Build.0 = 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}.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.Build.0 = Release|x64
{9B3EEB2A-26D7-4B2C-B890-505715283400}.Release|x86.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -6,708 +6,9 @@ using namespace example_novel;
using namespace printer;
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 <QTime>
#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) {
auto dom_tokens = doc.createElement("tokens");

View File

@ -8,175 +8,6 @@
#include <parse_novel.h>
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输出构建器.
*/

View File

@ -34,8 +34,7 @@ int main(int argc, char* argv[]) {
args_parser << build_mode;
*build_mode << make_shared<IndexParam>("nsc", "程序名称")
<< make_shared<FloatKeyValue>("path", "指定源代码目录")
<< make_shared<FloatKeyValue>("dest", "指定生成目录")
<< make_shared<FloatOption>("html", "生成html文件格式取代AST", true);
<< make_shared<FloatKeyValue>("dest", "指定生成目录");
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 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());
if (!source_dir.exists()) {
@ -93,11 +91,7 @@ int main(int argc, char* argv[]) {
}
}
if (html_opt->value().toInt() == 1 && access_ptr) {
printer::tools_printer tool;
tool.plain_html_output(access_ptr, destination_dir);
}
else if (access_ptr) {
if (access_ptr) {
QTime time_stamp = QTime::currentTime();
lib_parse::VisitEntry control;
auto visitor = make_shared<printer::AstGenerate>(source_dir);

View File

@ -52,7 +52,7 @@ namespace lib_syntax {
MatchCursor(std::shared_ptr<const MatchCursor> other_ptr);
virtual ~MatchCursor() = default;
bool operator>(const MatchCursor & other) const;
bool operator>(const MatchCursor& other) const;
virtual std::shared_ptr<const MatchCursor> previous() const;
virtual QString filePath() const;
@ -195,7 +195,8 @@ namespace lib_syntax {
std::shared_ptr<const lib_token::ITokenProcess> _define_peers;
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
public:
@ -293,7 +294,8 @@ namespace lib_syntax {
class ElementRule : public ExprRule {
public:
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 {
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(); });
}
if (!branch_procs.size())
branch_procs = nbranch;
decltype(nbranch) results_fnl;
for (auto curs : branch_procs) {
if (curs->parseFailure()) {
results_fnl.append(curs);
}
else {
// 表达式匹配结尾
if (branch_procs.size()) {
decltype(nbranch) results_fnl;
for (auto curs : branch_procs) {
auto t_end = curs->token();
auto w_end = curs->words();
@ -363,9 +359,11 @@ namespace lib_syntax {
break;
}
}
return results_fnl;
}
return results_fnl;
// 匹配失败
return branch_procs;
}
protected: