QtNovelUI/libParse/StoryChainDocumentParser.cpp

300 lines
9.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StoryChainDocumentParser.h"
using namespace Parse;
using namespace Lex;
using namespace Syntax;
using namespace Syntax::Defines;
using namespace Parse::Result;
// storychain 解析器================================================
NodeStoryChainParser::NodeStoryChainParser(ParseCore *core)
: XSyntaxBase("文学脉络"), pjt_ref(core)
{
set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
auto rule = addRule("文学脉络定义", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmidx = cnt - 1, defidx = cnt - 2;
// 构建语法节点
auto storychain = new NodeStoryChain(this->docRef(), seqs[nmidx].Text);
this->refocusNode(storychain);
// 收集词语
auto words0 = new Words(storychain, this->docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol);
auto words1 = new Words(storychain, this->docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
docRef()->append(words0);
docRef()->append(words1);
return ParseResult::SelfManipulate;
});
rule->addExpression("脉络定义基础", { Elm("{脉络定义}"), Elm("{描述文本}", true) });
rule->addExpression("脉络定义拓展", { Exp("::换行前缀"), Exp("脉络定义基础", true)});
rule = addRule("脉络成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmidx = cnt - 1;
// 获取语法节点
auto storychain = this->currNode();
// 收集词语
auto word = new Words(storychain, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
docRef()->append(word);
return ParseResult::EnterNext;
});
rule->addExpression("基础脉络界限", { Elm("{左界限}", true) });
rule->addExpression("拓展脉络界限", { Exp("::换行前缀"), Exp("基础脉络界限", true) });
rule = addRule("完成脉络解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmidx = cnt - 1;
// 获取语法节点
auto storychain = this->currNode();
// 收集词语
auto word = new Words(storychain, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
docRef()->append(word);
return ParseResult::Completed;
});
rule->addExpression("基础脉络跳出", { Elm("{右界限}", true) });
rule->addExpression("拓展脉络跳出", { Exp("::换行前缀"), Exp("基础脉络跳出", true) });
addChild(QList<SyntaxParser*>() << new NodeStoryPointParser(this) << new NodeStoryPureTextDesGroupParser(this));
}
ParseCore * NodeStoryChainParser::project() const
{
return pjt_ref;
}
// storypoint解析器=================================================
NodeStoryPointParser::NodeStoryPointParser(NodeStoryChainParser *chain)
: XSyntaxBase("脉络驻点"), parent_parser(chain)
{
set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
auto rule = addRule("脉络驻点定义", 0, [this](const QList<LexResult> &seqs, int c)->ParseResult {
auto nmidx = c - 1, defidx = c - 2;
// 语法节点定义
auto node = this->storyChainParser()->currNode();
auto storypoint = new NodeStoryPoint(static_cast<NodeStoryChain*>(node), seqs[nmidx].Text);
node->appendChild(storypoint);
this->refocusNode(storypoint);
// 词语收集
auto word0 = new Words(storypoint, node->doc(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol);
auto word1 = new Words(storypoint, node->doc(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
node->doc()->append(word0);
node->doc()->append(word1);
return ParseResult::SelfManipulate;
});
rule->addExpression("基础节点定义", { Elm("{节点定义}"), Elm("{描述文本}", true) });
rule->addExpression("拓展节点定义", { Exp("::换行前缀"), Exp("基础节点定义", true) });
rule = addRule("节点成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmidx = cnt - 1;
auto word = new Words(this->currNode(), this->storyChainParser()->docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
this->docRef()->append(word);
return ParseResult::EnterNext;
});
rule->addExpression("基础节点界限", { Elm("{左界限}", true) });
rule->addExpression("拓展节点界限", { Exp("::换行前缀"), Exp("基础节点界限", true) });
rule = addRule("完成节点解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
{
auto nmidx = cnt - 1;
auto word = new Words(this->currNode(), this->storyChainParser()->docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
this->docRef()->append(word);
return ParseResult::Completed;
});
rule->addExpression("基础节点跳出", { Elm("{右界限}", true) });
rule->addExpression("拓展节点跳出", { Exp("::换行前缀"), Exp("基础节点跳出", true) });
addChild(QList<SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this));
}
NodeStoryChainParser * NodeStoryPointParser::storyChainParser() const
{
return parent_parser;
}
DocCore * NodeStoryPointParser::docRef() const
{
return this->storyChainParser()->docRef();
}
NodeStoryChain::NodeStoryChain(DocCore * doc, const QString & name)
: Result::NamedNode(name, doc, NODE_STORYCHAIN){}
QString NodeStoryChain::srcPath() const
{
return doc()->filePath();
}
bool NodeStoryChain::check(QList<ErrorMessage> &reasons) const
{
auto nodes = doc()->core()->queryStoryChain(name()[0]);
if(nodes.size() > 1){
ErrorMessage ins(this);
ins.Reason = "重复定义脉络";
ins.Text = name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
reasons << ins;
}
return nodes.size() == 1;
}
QString NodeStoryChain::toString() const
{
auto desc_string = QString(depth(), ' ') + "#脉络 " + name()[0] + " {";
for (auto it : children())
desc_string += "\n"+ QString(depth(), ' ') + it->toString();
desc_string +="\n"+ QString(depth(), ' ') + "}";
return desc_string;
}
NodeStoryPoint::NodeStoryPoint(NodeStoryChain * chain, const QString & name)
: Result::NamedNode(name, chain->doc(), NODE_STORYPOINT, chain){ store_name = name; }
NodeStoryChain * NodeStoryPoint::storyChain() const
{
return static_cast<NodeStoryChain*>(parent());
}
bool NodeStoryPoint::check(QList<ErrorMessage> &reasons) const
{
auto chain = parent();
auto nodes = chain->doc()->core()->queryStoryPoint(chain, name()[0]);
if(nodes.size() > 1){
ErrorMessage ins(this);
ins.Reason = "重复定义脉络节点";
ins.Text = static_cast<NamedNode*>(chain)->name()[0] +""+ name()[0];
ins.FilePath = doc()->filePath();
ins.CodeRow = refered().first()->row();
ins.CodeCol = refered().first()->column();
reasons << ins;
}
return nodes.size() == 1;
}
QString NodeStoryPoint::toString() const
{
QString desc_string = "";
desc_string += QString(depth(), ' ') + "#节点 " + name()[0] + " {";
for (auto it : children())
desc_string += "\n" + QString(depth(), ' ') + it->toString();
desc_string += "\n"+QString(depth(), ' ') + "}";
return desc_string;
}
QList<QString> NodeStoryPoint::name() const
{
return QList<QString>() << store_name << static_cast<NamedNode*>(parent())->name()[0];
}
NodeStoryDesGroup::NodeStoryDesGroup(DesNode * parent_refer)
: Result::DesNode(parent_refer->doc(), NODE_DESCRIPTION_GROUP, parent_refer){}
bool NodeStoryDesGroup::check(QList<ErrorMessage> &) const
{
return true;
}
QString NodeStoryDesGroup::toString() const
{
QString desc = QString(depth(), ' ') ;
for (auto &it : children())
desc += it->toString() + " ";
return desc;
}
NodeStoryDesBlock::NodeStoryDesBlock(DesNode *parent_node, const QString &text)
: Result::DesNode(parent_node->doc(), NODE_DESCRIPTION_BLOCK, parent_node),
text_block(text){}
bool NodeStoryDesBlock::check(QList<ErrorMessage> &) const
{
return true;
}
QString NodeStoryDesBlock::toString() const
{
return text_block;
}
NodeStoryPureTextDesGroupParser::NodeStoryPureTextDesGroupParser(XSyntaxBase * pparser)
: XSyntaxBase("描述块"), parent_parser(pparser)
{
set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
auto rule = addRule("提取文本", 0, [this, pparser](const QList<LexResult> &seqs, int cnt)->ParseResult {
auto curr_node = new NodeStoryDesGroup(pparser->currNode());
refocusNode(curr_node);
pparser->currNode()->appendChild(curr_node);
for (auto idx = 0; idx < cnt; ++idx)
if (seqs[idx].Token != "{换行符}") {
auto node_blk = new NodeStoryDesBlock(curr_node, seqs[idx].Text);
curr_node->appendChild(node_blk);
auto word = new Words(node_blk, docRef(), seqs[idx].Text, seqs[idx].StartRow, seqs[idx].StartCol);
docRef()->append(word);
}
return ParseResult::Completed;
});
rule->addExpression("基础提取文本", { Elm("{描述文本}"), Elm("{描述文本}", true) });
rule->addExpression("拓展提取文本", { Exp("::换行前缀"), Exp("基础提取文本", true) });
//rule = addRule("完成提取", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
// refocusNode(nullptr);
// return ParseResult::Completed;
//});
// rule->addExpression("基础文本提取跳出", { Elm("{换行符}", true) });
}
StoryChainDocumentParser::StoryChainDocumentParser(ParseCore * pjt)
{
appendTokensDefine({
{"{脉络定义}","#脉络"},
{"{节点定义}", "#节点"},
{"{描述文本}", "[^#@\\{\\}\\n]+"},
{"{左界限}","\\{"},
{"{右界限}","\\}"},
{"{换行符}","\\n"},
// {"{引用符}", "@"},
}, "{无法识别}");
auto chain_parser = new NodeStoryChainParser(pjt);
appendParser(chain_parser);
}