2022-11-17 08:26:05 +00:00
|
|
|
|
#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
|
|
|
|
|
{
|
2022-12-08 19:43:42 +00:00
|
|
|
|
return this->index_store;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int NodeStoryBoard::indexValue(bool &valid) const
|
|
|
|
|
{
|
|
|
|
|
return index_store.toInt(&valid);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NodeStoryBoard::check(QList<ErrorMessage> &reasons) const
|
|
|
|
|
{
|
2022-11-25 01:18:54 +00:00
|
|
|
|
auto nodes = doc()->core()->queryStoryBoard(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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-08 19:43:42 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-17 08:26:05 +00:00
|
|
|
|
return nodes.size() == 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString NodeStoryBoard::toString() const
|
|
|
|
|
{
|
2022-12-08 19:43:42 +00:00
|
|
|
|
bool ignore;
|
|
|
|
|
QString des = "#故事 "+name()[0] + " " + QString("%1").arg(indexValue(ignore)) +" {";
|
2022-11-17 08:26:05 +00:00
|
|
|
|
for(auto n : children())
|
|
|
|
|
des += "\n" + n->toString();
|
|
|
|
|
des += "\n}";
|
|
|
|
|
|
|
|
|
|
return des;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NodeStoryFragmentRefer::NodeStoryFragmentRefer(NodeStoryBoard * const parent_node, const QString &name)
|
2022-11-25 01:18:54 +00:00
|
|
|
|
: Result::NamedNode(name, parent_node->doc(), NODE_FRAGMENTREFERENCE, parent_node) { fragment_name = name; }
|
2022-11-17 08:26:05 +00:00
|
|
|
|
|
|
|
|
|
void NodeStoryFragmentRefer::setUnit(const QString &name){
|
|
|
|
|
this->unit_name_store = name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString NodeStoryFragmentRefer::unit() const{
|
|
|
|
|
return this->unit_name_store;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-08 19:43:42 +00:00
|
|
|
|
QString NodeStoryFragmentRefer::fragment() const
|
|
|
|
|
{
|
|
|
|
|
return this->fragment_name;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-17 08:26:05 +00:00
|
|
|
|
bool NodeStoryFragmentRefer::check(QList<ErrorMessage> &reasons) const
|
|
|
|
|
{
|
|
|
|
|
auto unitx = doc()->core()->queryStoryUnit(unit());
|
|
|
|
|
if(!unitx.size()){
|
2022-12-08 19:43:42 +00:00
|
|
|
|
ErrorMessage ins(this);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
ins.Reason = "指定的单元不存在";
|
|
|
|
|
ins.Text = unit();
|
|
|
|
|
ins.FilePath = doc()->filePath();
|
|
|
|
|
ins.CodeRow = refered().first()->row();
|
|
|
|
|
ins.CodeCol = refered().first()->column();
|
|
|
|
|
reasons << ins;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-25 01:18:54 +00:00
|
|
|
|
auto fragment = doc()->core()->queryStoryFragment(unitx[0], name()[0]);
|
2022-11-17 08:26:05 +00:00
|
|
|
|
if(!fragment.size()){
|
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 = unit() + ":" + 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 fragment.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString NodeStoryFragmentRefer::toString() const
|
|
|
|
|
{
|
2022-11-25 01:18:54 +00:00
|
|
|
|
QString des = QString(depth(), ' ') + "@情节 " + name()[0] + " " + unit() + " {";
|
2022-11-17 08:26:05 +00:00
|
|
|
|
for(auto &c : children())
|
|
|
|
|
des += "\n" + QString(depth(), ' ') + c->toString();
|
|
|
|
|
|
|
|
|
|
return des + "\n"+QString(depth(), ' ') + "}";
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-25 01:18:54 +00:00
|
|
|
|
QList<QString> NodeStoryFragmentRefer::name() const
|
|
|
|
|
{
|
|
|
|
|
return QList<QString>() << fragment_name << unit_name_store;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-17 08:26:05 +00:00
|
|
|
|
NodeStoryBoardParser::NodeStoryBoardParser(Result::ParseCore *core)
|
|
|
|
|
:Syntax::XSyntaxBase("情节引用"), project_ins(core)
|
|
|
|
|
{
|
|
|
|
|
set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
|
|
|
|
|
auto rule = addRule("进入作品解析", 0, [this](const QList<LexResult> &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<LexResult> &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<LexResult> &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<Syntax::SyntaxParser*>()
|
|
|
|
|
<< 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<LexResult> &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<NodeStoryBoard*>(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<LexResult> &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<LexResult> &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<Syntax::SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this));
|
|
|
|
|
}
|