#include "StoryBoardDocumentParser.h" #include "StoryChainDocumentParser.h" using namespace Lex; using namespace Parse; using namespace Syntax; using namespace Syntax::Defines; using namespace Parse::Result; NodeStoryBoard::NodeStoryBoard(Result::DocCore *doc, const QString &name) : Result::NamedNode(name, doc, NODE_STORYBOARD, nullptr){} void NodeStoryBoard::setIndex(const QString &val) { index_store = val; } QString NodeStoryBoard::index() const { return this->index_store; } int NodeStoryBoard::indexValue(bool &valid) const { return index_store.toInt(&valid); } bool NodeStoryBoard::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryBoard(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 is_valid = false; indexValue(is_valid); if(!is_valid){ ErrorMessage msg(this); msg.CodeRow = refered().first()->row(); msg.CodeCol = refered().first()->column(); msg.FilePath = doc()->filePath(); msg.Text = index(); msg.Reason = "指定故事编排索引格式错误"; reasons << msg; return false; } return nodes.size() == 1; } QString NodeStoryBoard::toString() const { bool ignore; QString des = "#故事 "+name()[0] + " " + QString("%1").arg(indexValue(ignore)) +" {"; for(auto n : children()) des += "\n" + n->toString(); des += "\n}"; return des; } NodeStoryFragmentRefer::NodeStoryFragmentRefer(NodeStoryBoard * const parent_node, const QString &name) : Result::NamedNode(name, parent_node->doc(), NODE_FRAGMENTREFERENCE, parent_node) { fragment_name = name; } void NodeStoryFragmentRefer::setUnit(const QString &name){ this->unit_name_store = name; } QString NodeStoryFragmentRefer::unit() const{ return this->unit_name_store; } QString NodeStoryFragmentRefer::fragment() const { return this->fragment_name; } bool NodeStoryFragmentRefer::check(QList &reasons) const { auto unitx = doc()->core()->queryStoryUnit(unit()); if(!unitx.size()){ ErrorMessage ins(this); ins.Reason = "指定的单元不存在"; ins.Text = unit(); ins.FilePath = doc()->filePath(); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); reasons << ins; return false; } auto fragment = doc()->core()->queryStoryFragment(unitx[0], name()[0]); if(!fragment.size()){ ErrorMessage ins(this); ins.Reason = "指定的情节不存在"; ins.Text = unit() + ":" + name()[0]; ins.FilePath = doc()->filePath(); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); reasons << ins; } return fragment.size(); } QString NodeStoryFragmentRefer::toString() const { QString des = QString(depth(), ' ') + "@情节 " + name()[0] + " " + unit() + " {"; for(auto &c : children()) des += "\n" + QString(depth(), ' ') + c->toString(); return des + "\n"+QString(depth(), ' ') + "}"; } QList NodeStoryFragmentRefer::name() const { return QList() << fragment_name << unit_name_store; } NodeStoryBoardParser::NodeStoryBoardParser(Result::ParseCore *core) :Syntax::XSyntaxBase("情节引用"), project_ins(core) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); auto rule = addRule("进入作品解析", 0, [this](const QList &seqs, int cnt)->ParseResult { auto mbunit = seqs[cnt-1]; auto nmunit = seqs[cnt-2]; auto defunit = seqs[cnt-3]; auto node = new NodeStoryBoard(docRef(), nmunit.Text); node->setIndex(mbunit.Text); refocusNode(node); auto word0 = new Words(node, docRef(), nmunit.Text, nmunit.StartRow, nmunit.StartCol); auto word1 = new Words(node, docRef(), defunit.Text, defunit.StartRow, defunit.StartCol); auto word2 = new Words(node, docRef(), mbunit.Text, mbunit.StartRow, mbunit.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 NodeStoryPureTextDesGroupParser(this) << new NodeStoryFragmentReferParser(this)); } Result::ParseCore *NodeStoryBoardParser::project() const{return project_ins;} StoryBoardDocumentParser::StoryBoardDocumentParser(Result::ParseCore *core) { appendTokensDefine({ {"{故事定义}","#故事"}, {"{情节引用}", "@情节"}, {"{描述文本}", "[^#@\\{\\}\\n]+"}, {"{左界限}","\\{"}, {"{右界限}","\\}"}, {"{换行符}","\\n"}, }, "{无法识别}"); auto ins = new NodeStoryBoardParser(core); appendParser(ins); } NodeStoryFragmentReferParser::NodeStoryFragmentReferParser(XSyntaxBase *parent) : Syntax::XSyntaxBase("情节引用") { set_common_expression("::换行前缀", {Elm("{换行符}"), Elm("{换行符}", true)}); auto rule = addRule("进入情节引用", 0, [this, parent](const QList &seqs, int cnt)->ParseResult { auto unit_u = seqs[cnt-1]; auto name_u = seqs[cnt-2]; auto def_u = seqs[cnt-3]; auto pnode = static_cast(parent->currNode()); auto tnode = new NodeStoryFragmentRefer(pnode, name_u.Text); tnode->setUnit(unit_u.Text); pnode->appendChild(tnode); refocusNode(tnode); auto word0 = new Words(tnode, docRef(), def_u.Text, def_u.StartRow, def_u.StartCol); auto word1 = new Words(tnode, docRef(), name_u.Text, name_u.StartRow, name_u.StartCol); auto word2 = new Words(tnode, docRef(), unit_u.Text, unit_u.StartRow, unit_u.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 NodeStoryPureTextDesGroupParser(this)); }