2022-11-17 08:26:05 +00:00
|
|
|
|
#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
|
|
|
|
|
{
|
2022-11-25 01:18:54 +00:00
|
|
|
|
auto nodes = doc()->core()->queryStoryChain(name()[0]);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
if(nodes.size() > 1){
|
2022-12-08 19:43:42 +00:00
|
|
|
|
ErrorMessage ins(this);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
ins.Reason = "重复定义脉络";
|
2022-11-25 01:18:54 +00:00
|
|
|
|
ins.Text = name()[0];
|
2022-11-17 08:26:05 +00:00
|
|
|
|
ins.FilePath = doc()->filePath();
|
|
|
|
|
ins.CodeRow = refered().first()->row();
|
|
|
|
|
ins.CodeCol = refered().first()->column();
|
|
|
|
|
reasons << ins;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes.size() == 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString NodeStoryChain::toString() const
|
|
|
|
|
{
|
2022-11-25 01:18:54 +00:00
|
|
|
|
auto desc_string = QString(depth(), ' ') + "#脉络 " + name()[0] + " {";
|
2022-11-17 08:26:05 +00:00
|
|
|
|
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)
|
2022-11-25 01:18:54 +00:00
|
|
|
|
: Result::NamedNode(name, chain->doc(), NODE_STORYPOINT, chain){ store_name = name; }
|
2022-11-17 08:26:05 +00:00
|
|
|
|
|
|
|
|
|
NodeStoryChain * NodeStoryPoint::storyChain() const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<NodeStoryChain*>(parent());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NodeStoryPoint::check(QList<ErrorMessage> &reasons) const
|
|
|
|
|
{
|
|
|
|
|
auto chain = parent();
|
2022-11-25 01:18:54 +00:00
|
|
|
|
auto nodes = chain->doc()->core()->queryStoryPoint(chain, name()[0]);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
|
2022-12-08 19:43:42 +00:00
|
|
|
|
if(nodes.size() > 1){
|
|
|
|
|
ErrorMessage ins(this);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
ins.Reason = "重复定义脉络节点";
|
2022-11-25 01:18:54 +00:00
|
|
|
|
ins.Text = static_cast<NamedNode*>(chain)->name()[0] +":"+ name()[0];
|
2022-11-17 08:26:05 +00:00
|
|
|
|
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 = "";
|
2022-11-25 01:18:54 +00:00
|
|
|
|
desc_string += QString(depth(), ' ') + "#节点 " + name()[0] + " {";
|
2022-11-17 08:26:05 +00:00
|
|
|
|
for (auto it : children())
|
|
|
|
|
desc_string += "\n" + QString(depth(), ' ') + it->toString();
|
|
|
|
|
desc_string += "\n"+QString(depth(), ' ') + "}";
|
|
|
|
|
|
2022-11-25 01:18:54 +00:00
|
|
|
|
return desc_string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<QString> NodeStoryPoint::name() const
|
|
|
|
|
{
|
|
|
|
|
return QList<QString>() << store_name << static_cast<NamedNode*>(parent())->name()[0];
|
2022-11-17 08:26:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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"},
|
2022-11-25 01:18:54 +00:00
|
|
|
|
// {"{引用符}", "@"},
|
2022-11-17 08:26:05 +00:00
|
|
|
|
}, "{无法识别}");
|
|
|
|
|
|
|
|
|
|
auto chain_parser = new NodeStoryChainParser(pjt);
|
|
|
|
|
appendParser(chain_parser);
|
|
|
|
|
}
|