#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 &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 &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 &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() << 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 &seqs, int c)->ParseResult { auto nmidx = c - 1, defidx = c - 2; // 语法节点定义 auto node = this->storyChainParser()->currNode(); auto storypoint = new NodeStoryPoint(static_cast(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 &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 &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() << 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 &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(parent()); } bool NodeStoryPoint::check(QList &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(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 NodeStoryPoint::name() const { return QList() << store_name << static_cast(parent())->name()[0]; } NodeStoryDesGroup::NodeStoryDesGroup(DesNode * parent_refer) : Result::DesNode(parent_refer->doc(), NODE_DESCRIPTION_GROUP, parent_refer){} bool NodeStoryDesGroup::check(QList &) 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 &) 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 &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 &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); }