#include "StoryUnitDocumentParser.h" using namespace Parse; using namespace Parse::Result; using namespace Lex; using namespace Syntax; using namespace Syntax::Defines; NodeStoryUnit::NodeStoryUnit(DocCore * doc, const QString & name) : Result::NamedNode(name, doc, NODE_STORYUNIT, nullptr){} bool NodeStoryUnit::check(QList &reasons) const { auto unit_nodes = doc()->core()->queryStoryUnit(name()[0]); if(unit_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 unit_nodes.size() == 1; } QString NodeStoryUnit::toString() const { QString rets = "#单元 " + name()[0] + "{"; for (auto &it : children()) rets += "\n" + it->toString(); rets += "\n}"; return rets; } NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name, const QString &order) : Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){ store_name = name; order_text = order; } QString NodeStoryFragment::order() const { return order_text; } double NodeStoryFragment::orderValue(bool &isvalid) const { return order_text.toDouble(&isvalid); } bool NodeStoryFragment::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryFragment(parent(), 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; } bool isvalid = false; this->orderValue(isvalid); if(!isvalid){ ErrorMessage msg(this); msg.CodeRow = refered().first()->row(); msg.CodeCol = refered().first()->column(); msg.FilePath = doc()->filePath(); msg.Text = this->order(); msg.Reason = "指定情节序列格式错误"; reasons << msg; return false; } return nodes.size() == 1; } QString NodeStoryFragment::toString() const { QString rets = QString(depth(), ' ') + "#情节 " + name()[0] +" " + order() + "{"; for (auto &cin : children()) rets += "\n" + QString(depth(), ' ') + cin->toString(); return rets + "\n"+QString(depth(), ' ') + "}"; } QList NodeStoryFragment::name() const { return QList() << store_name << static_cast(parent())->name()[0]; } NodeStoryPointRefer::NodeStoryPointRefer(DesNode * parent, const QString & chain, const QString & point) : Result::DesNode(parent->doc(), NODE_POINTREFERENCE, parent), chain_name(chain), point_name(point) {} QString NodeStoryPointRefer::chainName() const { return chain_name; } QString NodeStoryPointRefer::pointName() const { return point_name; } bool NodeStoryPointRefer::check(QList &reasons) const { auto chain = doc()->core()->queryStoryChain(chainName()); if(!chain.size()){ ErrorMessage ins(this); ins.Reason = "指定脉络不存在"; ins.Text = chainName(); ins.FilePath = doc()->filePath(); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); reasons << ins; return false; } else{ auto point = doc()->core()->queryStoryPoint(chain[0], pointName()); if(!point.size()){ ErrorMessage ins(this); ins.Reason = "指定脉络节点不存在"; ins.Text = chainName() + ":" + pointName(); ins.FilePath = doc()->filePath(); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); reasons << ins; } return point.size(); } } QString NodeStoryPointRefer::toString() const { return QString("{@节点 %1 %2}").arg(chain_name).arg(point_name); } NodeStoryUnitParser::NodeStoryUnitParser(ParseCore * core) : XSyntaxBase("故事单元"), pjt_core(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 node = new NodeStoryUnit(this->docRef(), seqs[nmidx].Text); this->refocusNode(node); auto word0 = new Words(node, docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol); auto word1 = new Words(node, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol); docRef()->append(word0); docRef()->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 node = currNode(); auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].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 node = currNode(); auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol); docRef()->append(word); return ParseResult::Completed; }); rule->addExpression("基础跳出单元解析", { Elm("{右界限}", true) }); rule->addExpression("拓展跳出单元解析", { Exp("::换行前缀"), Exp("基础跳出单元解析", true) }); addChild(QList() << new NodeStoryMixedDesGroupParser(this) << new NodeStoryFragmentParser(this)); } ParseCore * NodeStoryUnitParser::project() const { return pjt_core; } StoryUnitDocumentParser::StoryUnitDocumentParser(ParseCore * ins) { appendTokensDefine({ {"{单元定义}", "#单元"}, {"{情节定义}", "#情节"}, {"{注解定义}", "#注解"}, {"{节点引用}", "\\{@节点"}, {"{描述文本}", "[^#@\\{\\}\\n]+"}, {"{左界限}", "\\{"}, {"{右界限}", "\\}"}, {"{换行符}", "\\n"}, }, "{无法识别}"); auto chain_parser = new NodeStoryUnitParser(ins); appendParser(chain_parser); } NodeStoryFragmentParser::NodeStoryFragmentParser(NodeStoryUnitParser * pparser) : XSyntaxBase("故事情节"), parent_parser(pparser) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); auto rule = addRule("进入情节解析", 0, [this](const QList &seqs, int cnt)->ParseResult { auto nmidx = cnt - 2, defidx = cnt - 3, ordidx=cnt-1; auto parent_parser = nodeStoryUnitParser(); auto node = new NodeStoryFragment(static_cast(parent_parser->currNode()), seqs[nmidx].Text, seqs[ordidx].Text); this->refocusNode(node); parent_parser->currNode()->appendChild(node); auto word0 = new Words(node, docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol); auto word1 = new Words(node, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol); auto word2 = new Words(node, docRef(), seqs[ordidx].Text, seqs[ordidx].StartRow, seqs[ordidx].StartCol); docRef()->append(word0); docRef()->append(word1); docRef()->append(word2); return ParseResult::SelfManipulate; }); rule->addExpression("基础情节解析", { Elm("{情节定义}"), Elm("{描述文本}1"), Elm("{描述文本}2", true) }); rule->addExpression("拓展情节解析", { Exp("::换行前缀"), Exp("基础情节解析", true) }); rule = addRule("情节成分解析", 1, [this](const QList &seqs, int cnt)->ParseResult { auto node = currNode(); auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].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 node = currNode(); auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol); docRef()->append(word); return ParseResult::Completed; }); rule->addExpression("基础跳出情节解析", { Elm("{右界限}", true) }); rule->addExpression("拓展跳出情节解析", { Exp("::换行前缀"),Exp("基础跳出情节解析", true) }); addChild(QList() << new NodeStoryMixedDesGroupParser(this) /*<< new NodeStoryFragmentCommentParser(this)*/); } NodeStoryUnitParser * NodeStoryFragmentParser::nodeStoryUnitParser() const { return parent_parser; } DocCore * NodeStoryFragmentParser::docRef() const { return parent_parser->docRef(); } #include "StoryChainDocumentParser.h" NodeStoryMixedDesGroupParser::NodeStoryMixedDesGroupParser(XSyntaxBase * parent) : XSyntaxBase("描述块", MatchType::Outline), parent_parser(parent), unique_tidy(new NodeStoryLinePrefixParser (this)) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); set_common_expression("::基础引用定义", { Elm("{节点引用}"),Elm("{描述文本}1"), Elm("{描述文本}2"), Elm("{右界限}", true) }); set_common_expression("::基础文本块定义", {Elm("{描述文本}"), Elm("{描述文本}", true) }); auto rule = addRule("进入描述块解析", 0, [this](const QList &seqs, int cnt)->ParseResult { auto state = seqs[0].Token == QString("{换行符}"); unique_tidy->setMatchEnable(state); auto group = new NodeStoryDesGroup(parent_parser->currNode()); parent_parser->currNode()->appendChild(group); this->refocusNode(group); return ParseResult::EnterNext; }); rule->addExpression("文本块混合定义x", { Exp("::基础引用定义", true), Exp("::基础引用定义"), Exp("::基础文本块定义", true), Exp("::基础引用定义")}); rule->addExpression("文本块混合定义y", {Exp("::基础文本块定义", true), Exp("::基础引用定义"),Exp("::基础引用定义", true), Exp("::基础文本块定义")} ); rule->addExpression("拓展文本块x", { Exp("::换行前缀"), Exp("文本块混合定义x", true)}); rule->addExpression("拓展文本块y", { Exp("::换行前缀"), Exp("文本块混合定义y", true)}); addChild(QList() << unique_tidy << new NodeStoryTextSpanParser(this) << new NodeStoryPointReferParser(this)); } void NodeStoryMixedDesGroupParser::reset() { XSyntaxBase::reset(); } NodeStoryTextSpanParser::NodeStoryTextSpanParser(XSyntaxBase *parent) : Syntax::XSyntaxBase("文本块"), parent_parser(parent) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); auto rule = addRule("解析TextSpan", 0, [this](const QList &seqs, int cnt)->ParseResult { auto pnode = parent_parser->currNode(); for(auto idx=0; idxunknowns(); if(seqs[idx].Token != "{换行符}"){ node = new NodeStoryDesBlock(pnode, seqs[idx].Text); pnode->appendChild(node); } auto word = new Words(node, 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)}); } NodeStoryPointReferParser::NodeStoryPointReferParser(XSyntaxBase *parent) : Syntax::XSyntaxBase("节点引用"), parent_parser(parent) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); auto rule = addRule("解析节点引用", 0, [this](const QList &seqs, int cnt)->ParseResult { auto pnode = parent_parser->currNode(); auto chain_unit = seqs[cnt-3]; auto point_unit = seqs[cnt-2]; auto refer = new NodeStoryPointRefer(pnode, chain_unit.Text, point_unit.Text); pnode->appendChild(refer); auto word3 = new Words(refer, docRef(), seqs[cnt-1].Text, seqs[cnt-1].StartRow, seqs[cnt-1].StartCol); auto word2 = new Words(refer, docRef(), point_unit.Text, point_unit.StartRow, point_unit.StartCol); auto word1 = new Words(refer, docRef(), chain_unit.Text, chain_unit.StartRow, chain_unit.StartCol); auto word0 = new Words(refer, docRef(), seqs[cnt-4].Text, seqs[cnt-4].StartRow, seqs[cnt-4].StartCol); docRef()->append(word3); docRef()->append(word2); docRef()->append(word1); docRef()->append(word0); return ParseResult::Completed; }); rule->addExpression("基础引用定义", { Elm("{节点引用}"),Elm("{描述文本}1"), Elm("{描述文本}2"), Elm("{右界限}", true) }); // rule->addExpression("拓展引用定义", {Exp("::换行前缀"), Exp("基础引用定义",true)}); } /** * 故事情节有序注释,单独解析 * #注解 注解名 序列名 值 { * 注解段落 * 注解段落 * } */ //NodeStoryFragmentCommentParser::NodeStoryFragmentCommentParser(Syntax::SyntaxParser *pparser) // : Syntax::XSyntaxBase("有序注解", MatchType::Entirely), pparser(pparser) //{ // set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); // auto rule = this->addRule("进入注解", 0, [this](const QList &seqs, int cnt)->ParseResult{ // auto nmidx = cnt - 3; // auto oridx = cnt - 2; // auto vidx = cnt - 1; // auto pnode = this->pparser->currNode(); // auto comment = new NodeStoryFragmentComment(pnode, seqs[oridx].Text, seqs[nmidx].Text); // comment->resetValue(seqs[vidx].Text); // pnode->appendChild(comment); // refocusNode(comment); // auto word0 = new Words(comment, docRef(), seqs[cnt-4].Text, seqs[cnt-4].StartRow, seqs[cnt-4].StartCol); // auto word1 = new Words(comment, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol); // auto word2 = new Words(comment, docRef(), seqs[oridx].Text, seqs[oridx].StartRow, seqs[oridx].StartCol); // auto word3 = new Words(comment, docRef(), seqs[vidx].Text, seqs[vidx].StartRow, seqs[vidx].StartCol); // docRef()->append(word0); // docRef()->append(word1); // docRef()->append(word2); // docRef()->append(word3); // return ParseResult::SelfManipulate; // }); // rule->addExpression("基础注解定义", {Elm("{注解定义}"), Elm{"{描述文本}1"}, Elm{"{描述文本}2"}, Elm{"{描述文本}3", true}}); // rule->addExpression("拓展注解定义", {Exp("::换行前缀"), Exp("基础注解定义", true)}); // rule = addRule("进入成分解析", 1, [this](const QList &seqs, int cnt)->ParseResult { // auto node = currNode(); // auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].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 node = currNode(); // auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol); // docRef()->append(word); // return ParseResult::Completed; // }); // rule->addExpression("基础跳出成分解析", { Elm("{右界限}", true) }); // rule->addExpression("拓展跳出成分解析", { Exp("::换行前缀"),Exp("基础跳出成分解析", true) }); // addChild(QList() << new NodeStoryMixedDesGroupParser(this)); //} NodeStoryLinePrefixParser::NodeStoryLinePrefixParser(SyntaxParser *pparent) : Syntax::XSyntaxBase("换行符清理", MatchType::Entirely), critical_rule(nullptr) { critical_rule = addRule("清理换行符", 0, [this](const QList &seqs, int cnt)->ParseResult { this->setMatchEnable(false); return ParseResult::Completed; }); critical_rule->addExpression("清理换行符x", {Elm{"{换行符}"},Elm{"{换行符}", true}}); } void NodeStoryLinePrefixParser::setMatchEnable(bool v) { critical_rule->setEnable(v); }