同步当前状态
This commit is contained in:
parent
0aa8fc8764
commit
c1435484d3
|
@ -1,28 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define NODE_UNKNOWNHOST 0 // 未知
|
||||
|
||||
#define NODE_STORYCHAIN 1 // 故事脉络
|
||||
#define NODE_STORYPOINT 2 // 故事节点
|
||||
#define NODE_DESCRIPTION_GROUP 3 // 描述集(段落)
|
||||
#define NODE_DESCRIPTION_BLOCK 4 // 描述块(普通)
|
||||
|
||||
|
||||
#define NODE_STORYUNIT 5 // 故事单元
|
||||
#define NODE_STORYFRAGMENT 6 // 故事情节
|
||||
#define NODE_POINTREFERENCE 7 // 节点引用
|
||||
#define NODE_ORDEREDCOMMENT 8 // 情节序列注释
|
||||
|
||||
|
||||
#define NODE_STORYBOARD 9 // 故事大纲
|
||||
#define NODE_FRAGMENTREFERENCE 10 // 情节引用
|
||||
|
||||
#define NODE_STORYDEPICTION 11 // 卷宗叙述节点
|
||||
|
||||
|
||||
#define DOC_STORYBOARD 0xa0001 // 故事板
|
||||
#define DOC_STORYUNIT 0xa0002 // 故事单元
|
||||
#define DOC_STORYCHAIN 0xa0003 // 故事脉络
|
||||
#define DOC_VOLUMEOUTLINE 0xa0004 // 卷宗大纲
|
||||
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
#include "LexFoundation.h"
|
||||
#include <tuple>
|
||||
|
||||
using namespace Lex;
|
||||
|
||||
LexFoundation::LexFoundation(QList<LexDef> seqence, const QString UnknownToken)
|
||||
: unknown_token(UnknownToken), lexical_seq(seqence)
|
||||
{
|
||||
empty_seq << '\t' << '\b' << ' ' << '\r' << EOF;
|
||||
}
|
||||
|
||||
typedef int lexunit_index;
|
||||
typedef int match_start;
|
||||
|
||||
QList<LexResult> LexFoundation::push(int row, int col, const QChar w)
|
||||
{
|
||||
QList<LexResult> result;
|
||||
|
||||
QString remains = "";
|
||||
if (!empty_seq.contains(w)) {
|
||||
code_acc << XChar(w, row, col);
|
||||
if (w != '\n')
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
if (!code_acc.size())
|
||||
return result;
|
||||
}
|
||||
|
||||
for (auto c : code_acc)
|
||||
remains += c.value();
|
||||
|
||||
auto mid_result = lexical_parse(remains);
|
||||
for (auto &r : mid_result) {
|
||||
auto char_start = code_acc[r.index_at_segment];
|
||||
r.StartRow = char_start.row();
|
||||
r.StartCol = char_start.col();
|
||||
auto char_end = code_acc[r.index_at_segment + r.Text.length() - 1];
|
||||
r.EndRow = char_end.row();
|
||||
r.EndCol = char_end.col();
|
||||
}
|
||||
|
||||
code_acc.clear();
|
||||
return mid_result;
|
||||
}
|
||||
|
||||
QList<LexResult> LexFoundation::lexical_parse(const QString & segment)
|
||||
{
|
||||
// 获取匹配词法分析
|
||||
QList<LexResult> result;
|
||||
QList<std::tuple<match_start, lexunit_index>> match_results;
|
||||
int lex_index = -1;
|
||||
for (auto lex : lexical_seq) {
|
||||
lex_index++;
|
||||
QRegExp exp(lex.RegExpression);
|
||||
auto match_index = exp.indexIn(segment);
|
||||
if (match_index != -1)
|
||||
match_results.append(std::make_tuple(match_index, lex_index));
|
||||
}
|
||||
|
||||
// 没有匹配结果,返回未定义
|
||||
if (!match_results.size())
|
||||
{
|
||||
LexResult rst;
|
||||
rst.index_at_segment = 0;
|
||||
rst.Token = this->unknown_token;
|
||||
rst.Text = segment;
|
||||
result << rst;
|
||||
return result;
|
||||
}
|
||||
|
||||
// 获取“匹配索引”,“词法优先级”获取最佳匹配结果,最小
|
||||
std::tuple<match_start, lexunit_index> min_elm = std::make_tuple(INT32_MAX, INT32_MAX);
|
||||
for (auto item : match_results) {
|
||||
if (std::get<0>(item) < std::get<0>(min_elm))
|
||||
min_elm = item;
|
||||
else if (std::get<0>(item) == std::get<0>(min_elm) &&
|
||||
std::get<1>(item) < std::get<1>(min_elm))
|
||||
min_elm = item;
|
||||
}
|
||||
|
||||
// 发现无效匹配局部,标记前部为未知
|
||||
if (std::get<0>(min_elm) != 0) {
|
||||
LexResult rst;
|
||||
rst.index_at_segment = 0;
|
||||
rst.Token = this->unknown_token;
|
||||
rst.Text = segment.mid(0, std::get<0>(min_elm));
|
||||
result << rst;
|
||||
}
|
||||
|
||||
// 重新匹配,获取完全匹配信息
|
||||
auto lex_unit = lexical_seq[std::get<1>(min_elm)];
|
||||
QRegExp exp(lex_unit.RegExpression);
|
||||
auto match_start = exp.indexIn(segment);
|
||||
auto match_len = exp.matchedLength();
|
||||
|
||||
// 获取匹配词法分析结果
|
||||
LexResult rst;
|
||||
rst.Token = lex_unit.TokenType;
|
||||
rst.Text = segment.mid(match_start, match_len);
|
||||
rst.index_at_segment = match_start;
|
||||
result << rst;
|
||||
|
||||
// 迭代匹配剩余字符串
|
||||
auto last = segment.mid(match_start + match_len);
|
||||
if(last.length()){
|
||||
auto xrst = lexical_parse(last);
|
||||
for (auto &t : xrst)
|
||||
t.index_at_segment += match_start;
|
||||
result.append(xrst);
|
||||
}
|
||||
|
||||
|
||||
// 返回结果
|
||||
return result;
|
||||
}
|
||||
|
||||
XChar::XChar(QChar c, int row, int col)
|
||||
: value_store(c), row_index(row), col_index(col) {}
|
||||
|
||||
QChar XChar::value() const
|
||||
{
|
||||
return value_store;
|
||||
}
|
||||
|
||||
int XChar::row() const
|
||||
{
|
||||
return row_index;
|
||||
}
|
||||
|
||||
int XChar::col() const
|
||||
{
|
||||
return col_index;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
namespace Lex {
|
||||
class LexFoundation;
|
||||
|
||||
/**
|
||||
* 解析基准定义单元.
|
||||
*/
|
||||
struct LexDef
|
||||
{
|
||||
QString TokenType; // Token字符
|
||||
QString RegExpression; // 词法解析表达式
|
||||
};
|
||||
|
||||
/**
|
||||
* 词法分析结果.
|
||||
*/
|
||||
struct LexResult
|
||||
{
|
||||
QString Token; // Token字符
|
||||
QString Text; // 内容
|
||||
int StartRow, StartCol, EndRow, EndCol; // 波及范围
|
||||
|
||||
friend class LexFoundation;
|
||||
private:
|
||||
int index_at_segment;
|
||||
};
|
||||
|
||||
/**
|
||||
* 字符提取富信息单元.
|
||||
*/
|
||||
class XChar
|
||||
{
|
||||
public:
|
||||
explicit XChar(QChar c, int row, int col);
|
||||
QChar value() const;
|
||||
int row() const;
|
||||
int col() const;
|
||||
|
||||
private:
|
||||
QChar value_store;
|
||||
int row_index, col_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* 基础词法分析器.
|
||||
*/
|
||||
class LexFoundation
|
||||
{
|
||||
public:
|
||||
explicit LexFoundation(QList<LexDef> seqence, const QString UnknownToken);
|
||||
virtual ~LexFoundation() = default;
|
||||
|
||||
/**
|
||||
* 词法分析器累积解析单个字符流.
|
||||
*
|
||||
* \param row 行
|
||||
* \param col 列
|
||||
* \param w 字符
|
||||
* \return 累积适配结果,空累积,
|
||||
*/
|
||||
QList<LexResult> push(int row, int col, const QChar w);
|
||||
|
||||
private:
|
||||
QString unknown_token;
|
||||
QList<QChar> empty_seq;
|
||||
|
||||
QList<XChar> code_acc;
|
||||
QList<LexDef> lexical_seq;
|
||||
|
||||
QList<LexResult> lexical_parse(const QString &segment);
|
||||
};
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include "SyntaxBase.h"
|
||||
|
||||
namespace Syntax
|
||||
{
|
||||
/**
|
||||
* 基础解析器框架.
|
||||
*/
|
||||
class ParseFrame
|
||||
{
|
||||
public:
|
||||
explicit ParseFrame();
|
||||
virtual ~ParseFrame() = default;
|
||||
|
||||
QList<Parse::Result::DesNode*> analysis(Parse::Result::DocCore *doc, const QString &path);
|
||||
|
||||
protected:
|
||||
void appendTokensDefine(QList<Lex::LexDef> seqs, const QString &unknown_token);
|
||||
void appendParser(Syntax::SyntaxParser* u);
|
||||
|
||||
private:
|
||||
QString unknown_token;
|
||||
QList<Lex::LexDef> token_seqs;
|
||||
QList<SyntaxParser*> cascade_parsers;
|
||||
|
||||
ParseResult ParseFrame::inner_parse(QList<Lex::LexResult> &lex_seqence,
|
||||
QList<Syntax::SyntaxParser*> parsers,
|
||||
QList<Parse::Result::DesNode*> &nodes_out);
|
||||
};
|
||||
}
|
|
@ -1,288 +0,0 @@
|
|||
#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<QString>& reasons) const
|
||||
{
|
||||
auto nodes = doc()->core()->queryStoryChain(name());
|
||||
if(nodes.size() > 1){
|
||||
for(auto &it : nodes)
|
||||
reasons << QString("重复定义脉络:%1,{src=%2 (row=%3, col=%4)}")
|
||||
.arg(name(), it->doc()->filePath())
|
||||
.arg(it->refered().first()->row()).arg(it->refered().first()->column());
|
||||
}
|
||||
|
||||
return nodes.size() == 1;
|
||||
}
|
||||
|
||||
QString NodeStoryChain::toString() const
|
||||
{
|
||||
auto desc_string = QString(depth(), ' ') + "#脉络 " + name() + " {";
|
||||
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){}
|
||||
|
||||
NodeStoryChain * NodeStoryPoint::storyChain() const
|
||||
{
|
||||
return static_cast<NodeStoryChain*>(parent());
|
||||
}
|
||||
|
||||
bool NodeStoryPoint::check(QList<QString>& reasons) const
|
||||
{
|
||||
auto chain = parent();
|
||||
auto nodes = chain->doc()->core()->queryStoryPoint(chain, name());
|
||||
|
||||
if(nodes.size() > 1){
|
||||
for(auto &it : nodes)
|
||||
reasons << QString("重复定义节点:%1,{src=%2 (row=%3, col=%4)}")
|
||||
.arg(name(), it->doc()->filePath())
|
||||
.arg(it->refered().first()->row()).arg(it->refered().first()->column());
|
||||
}
|
||||
|
||||
return nodes.size() == 1;
|
||||
}
|
||||
|
||||
QString NodeStoryPoint::toString() const
|
||||
{
|
||||
QString desc_string = "";
|
||||
desc_string += QString(depth(), ' ') + "#节点 " + name() + " {";
|
||||
for (auto it : children())
|
||||
desc_string += "\n" + QString(depth(), ' ') + it->toString();
|
||||
desc_string += "\n"+QString(depth(), ' ') + "}";
|
||||
|
||||
return desc_string;
|
||||
}
|
||||
|
||||
NodeStoryDesGroup::NodeStoryDesGroup(DesNode * parent_refer)
|
||||
: Result::DesNode(parent_refer->doc(), NODE_DESCRIPTION_GROUP, parent_refer){}
|
||||
|
||||
bool NodeStoryDesGroup::check(QList<QString>&) 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<QString>&) 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"},
|
||||
{"{引用符}", "@"},
|
||||
}, "{无法识别}");
|
||||
|
||||
auto chain_parser = new NodeStoryChainParser(pjt);
|
||||
appendParser(chain_parser);
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* StoryChain文件定义.
|
||||
*/
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include "ParseFrame.h"
|
||||
#include "XSyntaxBase.h"
|
||||
#include "ComnDef.h"
|
||||
|
||||
|
||||
namespace Parse
|
||||
{
|
||||
class NodeStoryPoint;
|
||||
|
||||
/**
|
||||
* 故事脉络节点定义.
|
||||
*/
|
||||
class NodeStoryChain : public Result::NamedNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 构建一个新的脉络节点.
|
||||
*
|
||||
* \param src_path 源文件路径
|
||||
*/
|
||||
explicit NodeStoryChain(Result::DocCore *doc, const QString &name);
|
||||
virtual ~NodeStoryChain() = default;
|
||||
|
||||
/**
|
||||
* 获取此解析节点关联的源文件路径.
|
||||
*
|
||||
* \return 路径字符串
|
||||
*/
|
||||
virtual QString srcPath() const;
|
||||
|
||||
|
||||
// 通过 NamedNode 继承
|
||||
virtual bool check(QList<QString>& reasons) const override;
|
||||
virtual QString toString() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事脉络定制解析器.
|
||||
*/
|
||||
class NodeStoryChainParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryChainParser(Result::ParseCore *core);
|
||||
virtual ~NodeStoryChainParser() = default;
|
||||
|
||||
Result::ParseCore* project() const;
|
||||
|
||||
private:
|
||||
Result::ParseCore *pjt_ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事节点.
|
||||
*/
|
||||
class NodeStoryPoint : public Result::NamedNode
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryPoint(NodeStoryChain *chain, const QString &name);
|
||||
virtual ~NodeStoryPoint() = default;
|
||||
|
||||
/**
|
||||
* 获取此解析节点依附的脉络节点
|
||||
*
|
||||
* \return 脉络节点
|
||||
*/
|
||||
virtual NodeStoryChain* storyChain() const;
|
||||
|
||||
// 通过 NamedNode 继承
|
||||
virtual bool check(QList<QString>& reasons) const override;
|
||||
virtual QString toString() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事节点定制解析器.
|
||||
*/
|
||||
class NodeStoryPointParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryPointParser(NodeStoryChainParser *chain);
|
||||
virtual ~NodeStoryPointParser() = default;
|
||||
|
||||
NodeStoryChainParser* storyChainParser() const;
|
||||
virtual Result::DocCore* docRef() const override;
|
||||
|
||||
private:
|
||||
NodeStoryChainParser *const parent_parser;
|
||||
};
|
||||
|
||||
/**
|
||||
* 节点描述内容节点.
|
||||
*/
|
||||
class NodeStoryDesGroup : public Result::DesNode
|
||||
{
|
||||
public:
|
||||
NodeStoryDesGroup(DesNode *parent_refer);
|
||||
virtual ~NodeStoryDesGroup() = default;
|
||||
|
||||
// 通过 DesNode 继承
|
||||
virtual bool check(QList<QString>&) const override;
|
||||
virtual QString toString() const override;
|
||||
};
|
||||
|
||||
class NodeStoryPureTextDesGroupParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryPureTextDesGroupParser(XSyntaxBase *pparser);
|
||||
virtual ~NodeStoryPureTextDesGroupParser() = default;
|
||||
|
||||
private:
|
||||
XSyntaxBase *const parent_parser;
|
||||
};
|
||||
|
||||
/**
|
||||
* 描述内容文字块.
|
||||
*/
|
||||
class NodeStoryDesBlock : public Result::DesNode
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryDesBlock(DesNode *parent_node, const QString &text);
|
||||
virtual ~NodeStoryDesBlock() = default;
|
||||
|
||||
// 通过 DesNode 继承
|
||||
virtual bool check(QList<QString>&) const override;
|
||||
virtual QString toString() const override;
|
||||
|
||||
private:
|
||||
QString text_block;
|
||||
};
|
||||
|
||||
class StoryChainDocumentParser : public Syntax::ParseFrame
|
||||
{
|
||||
public:
|
||||
StoryChainDocumentParser(Result::ParseCore *pjt);
|
||||
virtual ~StoryChainDocumentParser() = default;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,458 +0,0 @@
|
|||
#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<QString>& reasons) const
|
||||
{
|
||||
auto unit_nodes = doc()->core()->queryStoryUnit(name());
|
||||
|
||||
if(unit_nodes.size() > 1){
|
||||
for(auto &it : unit_nodes)
|
||||
reasons << QString("重复定义单元:%1,{src=%2 (row=%3, col=%4)}")
|
||||
.arg(name(), it->doc()->filePath())
|
||||
.arg(it->refered().first()->row()).arg(it->refered().first()->column());
|
||||
}
|
||||
return unit_nodes.size() == 1;
|
||||
}
|
||||
|
||||
QString NodeStoryUnit::toString() const
|
||||
{
|
||||
QString rets = "#单元 " + name() + "{";
|
||||
for (auto &it : children())
|
||||
rets += "\n" + it->toString();
|
||||
rets += "\n}";
|
||||
return rets;
|
||||
}
|
||||
|
||||
|
||||
NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name)
|
||||
: Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){}
|
||||
|
||||
bool NodeStoryFragment::check(QList<QString>& reasons) const
|
||||
{
|
||||
auto nodes = doc()->core()->queryStoryFragment(parent(), name());
|
||||
if(nodes.size() > 1){
|
||||
for(auto &it : nodes)
|
||||
reasons << QString("重复定义情节:%1,{src=%2 (row=%3, col=%4)}")
|
||||
.arg(name(), it->doc()->filePath())
|
||||
.arg(it->refered().first()->row()).arg(it->refered().first()->column());
|
||||
}
|
||||
|
||||
return nodes.size() == 1;
|
||||
}
|
||||
|
||||
QString NodeStoryFragment::toString() const
|
||||
{
|
||||
QString rets = QString(depth(), ' ') + "#情节 " + name() + "{";
|
||||
for (auto cin : children())
|
||||
rets += "\n" + QString(depth(), ' ') + cin->toString();
|
||||
return rets + "\n"+QString(depth(), ' ') + "}";
|
||||
}
|
||||
|
||||
|
||||
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<QString>& reasons) const
|
||||
{
|
||||
auto chain = doc()->core()->queryStoryChain(chainName());
|
||||
if(!chain.size()){
|
||||
reasons << QString("指定脉络不存在:%1{src=%2(row=%3,col=%4)}")
|
||||
.arg(chainName(), doc()->filePath())
|
||||
.arg(refered().first()->row()).arg(refered().first()->column());
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
auto point = doc()->core()->queryStoryPoint(chain[0], pointName());
|
||||
if(!point.size())
|
||||
reasons << QString("指定节点不存在:%1:%2{src=%3(row=%3,col=%4)}")
|
||||
.arg(chainName(), pointName(), doc()->filePath())
|
||||
.arg(refered().first()->row()).arg(refered().first()->column());
|
||||
|
||||
return point.size();
|
||||
}
|
||||
}
|
||||
|
||||
QString NodeStoryPointRefer::toString() const
|
||||
{
|
||||
return QString("{@节点 %1 %2}").arg(chain_name).arg(point_name);
|
||||
}
|
||||
|
||||
//NodeStoryFragmentComment::NodeStoryFragmentComment(DesNode * parent,
|
||||
// const QString &order, const QString & name)
|
||||
// : parent_ins(parent), name_store(name), order_name(order)
|
||||
//{
|
||||
//}
|
||||
|
||||
//QString NodeStoryFragmentComment::order() const
|
||||
//{
|
||||
// return order_name;
|
||||
//}
|
||||
|
||||
//DocCore * NodeStoryFragmentComment::document() const
|
||||
//{
|
||||
// return parent_ins->document();
|
||||
//}
|
||||
|
||||
//int NodeStoryFragmentComment::typeValue() const
|
||||
//{
|
||||
// return NODE_ORDEREDCOMMENT;
|
||||
//}
|
||||
|
||||
//DesNode * NodeStoryFragmentComment::parent() const
|
||||
//{
|
||||
// return parent_ins;
|
||||
//}
|
||||
|
||||
//void NodeStoryFragmentComment::appendChild(DesNode * ins)
|
||||
//{
|
||||
// children_nodes << ins;
|
||||
//}
|
||||
|
||||
//QList<DesNode*> NodeStoryFragmentComment::children() const
|
||||
//{
|
||||
// return children_nodes;
|
||||
//}
|
||||
|
||||
//bool NodeStoryFragmentComment::check(QList<QString>& reasons) const
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//QString NodeStoryFragmentComment::toString() const
|
||||
//{
|
||||
// auto xrets = QString(depth(), ' ') + "#注解 " + name() +" "+ order() +" "+ orderValue() + "{";
|
||||
// for (auto it : children_nodes)
|
||||
// xrets += "\n" + QString(depth(), ' ') + it->toString();
|
||||
// xrets += "\n" + QString(depth(), ' ') + "}";
|
||||
|
||||
// return xrets;
|
||||
//}
|
||||
|
||||
//QString NodeStoryFragmentComment::name() const
|
||||
//{
|
||||
// return name_store;
|
||||
//}
|
||||
|
||||
//QString NodeStoryFragmentComment::orderValue() const
|
||||
//{
|
||||
// return order_value;
|
||||
//}
|
||||
|
||||
//void NodeStoryFragmentComment::resetValue(const QString &value)
|
||||
//{
|
||||
// this->order_value = value;
|
||||
//}
|
||||
|
||||
NodeStoryUnitParser::NodeStoryUnitParser(ParseCore * core)
|
||||
: XSyntaxBase("故事单元"), pjt_core(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 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<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<SyntaxParser*>() << 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<LexResult> &seqs, int cnt)->ParseResult {
|
||||
auto nmidx = cnt - 1, defidx = cnt - 2;;
|
||||
|
||||
auto parent_parser = nodeStoryUnitParser();
|
||||
auto node = new NodeStoryFragment(static_cast<NodeStoryUnit*>(parent_parser->currNode()), seqs[nmidx].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);
|
||||
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<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<SyntaxParser*>() << 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<LexResult> &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<SyntaxParser*>() << 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<LexResult> &seqs, int cnt)->ParseResult {
|
||||
auto pnode = parent_parser->currNode();
|
||||
for(auto idx=0; idx<cnt; ++idx){
|
||||
DesNode *node = docRef()->unknowns();
|
||||
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<LexResult> &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<LexResult> &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<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<SyntaxParser*>() << new NodeStoryMixedDesGroupParser(this));
|
||||
//}
|
||||
|
||||
|
||||
NodeStoryLinePrefixParser::NodeStoryLinePrefixParser(SyntaxParser *pparent)
|
||||
: Syntax::XSyntaxBase("换行符清理", MatchType::Entirely), critical_rule(nullptr)
|
||||
{
|
||||
critical_rule = addRule("清理换行符", 0, [this](const QList<LexResult> &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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "XSyntaxBase.h"
|
||||
#include "ParseFrame.h"
|
||||
#include "SyntaxBase.h"
|
||||
|
||||
namespace Parse {
|
||||
/**
|
||||
* 故事单元.
|
||||
*/
|
||||
class NodeStoryUnit : public Result::NamedNode
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryUnit(Result::DocCore *doc, const QString &name);
|
||||
virtual ~NodeStoryUnit() = default;
|
||||
|
||||
// 通过 DesNode 继承
|
||||
virtual bool check(QList<QString>& reasons) const override;
|
||||
virtual QString toString() const override;
|
||||
};
|
||||
|
||||
/** 故事单元解析器 */
|
||||
class NodeStoryUnitParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryUnitParser(Result::ParseCore *core);
|
||||
|
||||
Result::ParseCore* project() const;
|
||||
|
||||
private:
|
||||
Result::ParseCore *const pjt_core;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事情节节点.
|
||||
*/
|
||||
class NodeStoryFragment : public Result::NamedNode
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryFragment(NodeStoryUnit* unit, const QString &name);
|
||||
virtual ~NodeStoryFragment() = default;
|
||||
|
||||
// 通过 NamedNode 继承
|
||||
virtual bool check(QList<QString>& reasons) const override;
|
||||
virtual QString toString() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事情节解析器.
|
||||
*/
|
||||
class NodeStoryFragmentParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryFragmentParser(NodeStoryUnitParser *pparser);
|
||||
|
||||
NodeStoryUnitParser * nodeStoryUnitParser() const;
|
||||
Result::DocCore * docRef() const;
|
||||
|
||||
private:
|
||||
NodeStoryUnitParser *const parent_parser;
|
||||
};
|
||||
|
||||
/**
|
||||
* 故事脉络节点引用.
|
||||
*/
|
||||
class NodeStoryPointRefer : public Result::DesNode
|
||||
{
|
||||
public:
|
||||
explicit NodeStoryPointRefer(DesNode *parent, const QString &chain, const QString &point);
|
||||
virtual ~NodeStoryPointRefer() = default;
|
||||
|
||||
QString chainName() const;
|
||||
QString pointName() const;
|
||||
|
||||
// 通过 DesNode 继承
|
||||
virtual bool check(QList<QString>& reasons) const override;
|
||||
virtual QString toString() const override;
|
||||
|
||||
private:
|
||||
QString chain_name;
|
||||
QString point_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 特殊用途的解析器,目标是移除指定标记的
|
||||
*/
|
||||
class NodeStoryLinePrefixParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryLinePrefixParser(SyntaxParser* pparent);
|
||||
|
||||
void setMatchEnable(bool v);
|
||||
|
||||
private:
|
||||
Syntax::ParseRule *critical_rule;
|
||||
};
|
||||
|
||||
class NodeStoryMixedDesGroupParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryMixedDesGroupParser(Syntax::XSyntaxBase * parent);
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
private:
|
||||
Syntax::XSyntaxBase *const parent_parser;
|
||||
NodeStoryLinePrefixParser *const unique_tidy;
|
||||
};
|
||||
|
||||
|
||||
class NodeStoryTextSpanParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryTextSpanParser(Syntax::XSyntaxBase *parent);
|
||||
private:
|
||||
Syntax::XSyntaxBase *const parent_parser;
|
||||
};
|
||||
|
||||
class NodeStoryPointReferParser : public Syntax::XSyntaxBase
|
||||
{
|
||||
public:
|
||||
NodeStoryPointReferParser(Syntax::XSyntaxBase *parent);
|
||||
|
||||
private:
|
||||
Syntax::XSyntaxBase *const parent_parser;
|
||||
};
|
||||
|
||||
// /**
|
||||
// * 故事情节有序注释,单独解析
|
||||
// * #注解 注解名 序列名 值 {
|
||||
// * 注解段落
|
||||
// * 注解段落
|
||||
// * }
|
||||
// */
|
||||
// class NodeStoryFragmentComment : public Result::NamedNode
|
||||
// {
|
||||
// public:
|
||||
// NodeStoryFragmentComment(DesNode *parent, const QString &order, const QString &name);
|
||||
// virtual ~NodeStoryFragmentComment() = default;
|
||||
|
||||
// QString order() const;
|
||||
|
||||
// // 通过 NamedNode 继承
|
||||
// inline virtual int depth() const override
|
||||
// {
|
||||
// return parent_ins->depth() + 1;
|
||||
// }
|
||||
// virtual Result::DocCore * document() const override;
|
||||
// virtual int typeValue() const override;
|
||||
// virtual DesNode * parent() const override;
|
||||
// virtual void appendChild(DesNode * ins) override;
|
||||
// virtual QList<DesNode*> children() const override;
|
||||
// virtual bool check(QList<QString>& reasons) const override;
|
||||
// virtual QString toString() const override;
|
||||
// virtual QString name() const override;
|
||||
|
||||
// QString orderValue() const;
|
||||
// void resetValue(const QString &value);
|
||||
|
||||
// private:
|
||||
// DesNode *const parent_ins;
|
||||
// QString name_store;
|
||||
// QString order_name;
|
||||
// QString order_value;
|
||||
|
||||
// QList<DesNode*> children_nodes;
|
||||
// };
|
||||
|
||||
// class NodeStoryFragmentCommentParser : public Syntax::XSyntaxBase
|
||||
// {
|
||||
// public:
|
||||
// NodeStoryFragmentCommentParser(Syntax::SyntaxParser* pparser);
|
||||
// private:
|
||||
// Syntax::SyntaxParser *const pparser;
|
||||
// };
|
||||
|
||||
|
||||
class StoryUnitDocumentParser : public Syntax::ParseFrame
|
||||
{
|
||||
public:
|
||||
StoryUnitDocumentParser(Result::ParseCore *ins);
|
||||
};
|
||||
}
|
|
@ -1,320 +0,0 @@
|
|||
#include "SyntaxBase.h"
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace Parse;
|
||||
using namespace Lex;
|
||||
using namespace Syntax;
|
||||
using namespace Parse::Result;
|
||||
|
||||
namespace Parse {
|
||||
class Unknown : public DesNode
|
||||
{
|
||||
public:
|
||||
explicit Unknown(DocCore *ins) : DesNode(ins, NODE_UNKNOWNHOST, nullptr){}
|
||||
|
||||
// 通过 DesNode 继承
|
||||
virtual bool check(QList<QString>&) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual QString toString() const override
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NamedNode::NamedNode(const QString &name, DocCore *core, int type, DesNode *pnode)
|
||||
: Result::DesNode(core, type, pnode), name_store(name){}
|
||||
|
||||
QString NamedNode::name() const
|
||||
{
|
||||
return name_store;
|
||||
}
|
||||
|
||||
DesNode::DesNode(DocCore *core, int type_value, DesNode *pnode)
|
||||
: doc_store(core), type_value(type_value), parent_node(pnode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DesNode::~DesNode()
|
||||
{
|
||||
for(auto &i : children())
|
||||
delete i;
|
||||
children_nodes.clear();
|
||||
}
|
||||
|
||||
int DesNode::depth() const
|
||||
{
|
||||
if(parent_node==nullptr)
|
||||
return 0;
|
||||
return parent_node->depth() + 1;
|
||||
}
|
||||
|
||||
DocCore *DesNode::doc() const
|
||||
{
|
||||
return this->doc_store;
|
||||
}
|
||||
|
||||
int DesNode::typeValue() const
|
||||
{
|
||||
return type_value;
|
||||
}
|
||||
|
||||
DesNode *DesNode::parent() const
|
||||
{
|
||||
return parent_node;
|
||||
}
|
||||
|
||||
void DesNode::appendChild(DesNode *ins)
|
||||
{
|
||||
children_nodes << ins;
|
||||
}
|
||||
|
||||
QList<DesNode *> DesNode::children() const
|
||||
{
|
||||
return children_nodes;
|
||||
}
|
||||
|
||||
void DesNode::registerWords(Words *ins)
|
||||
{
|
||||
words_collection << ins;
|
||||
}
|
||||
|
||||
QList<Words *> DesNode::refered() const
|
||||
{
|
||||
return words_collection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParseCore::ParseCore(const QString &name)
|
||||
: name_store(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ParseCore::registerNode(DocCore *doc, DesNode *node)
|
||||
{
|
||||
if(!nodes_map.contains(doc))
|
||||
nodes_map[doc] = new QList<DesNode*>();
|
||||
|
||||
nodes_map[doc]->append(node);
|
||||
}
|
||||
|
||||
void ParseCore::clearNodes(DocCore *ins)
|
||||
{
|
||||
if(!nodes_map.contains(ins))
|
||||
return;
|
||||
|
||||
auto c = nodes_map[ins];
|
||||
for(auto i : *c)
|
||||
delete i;
|
||||
|
||||
c->clear();
|
||||
}
|
||||
|
||||
QList<DocCore *> ParseCore::allDocuments() const
|
||||
{
|
||||
return nodes_map.keys();
|
||||
}
|
||||
|
||||
QList<DesNode *> ParseCore::queryRootNodes(DocCore *doc) const
|
||||
{
|
||||
if(!nodes_map.contains(doc))
|
||||
return QList<DesNode*>();
|
||||
|
||||
return *nodes_map[doc];
|
||||
}
|
||||
|
||||
DocCore *ParseCore::queryDocument(const QFileInfo &file_src) const
|
||||
{
|
||||
for(auto &d : nodes_map.keys()){
|
||||
auto anchor_file = d->filePath();
|
||||
if(anchor_file == file_src.absoluteFilePath())
|
||||
return d;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ParseCore::deleteDocument(DocCore *ins)
|
||||
{
|
||||
ins->clear();
|
||||
nodes_map.remove(ins);
|
||||
delete ins;
|
||||
}
|
||||
|
||||
QList<Result::DesNode*> ParseCore::queryStoryChain(const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
auto keys = nodes_map.keys();
|
||||
for(auto &k : keys)
|
||||
if(k->docType() == DocType::STORYCHAIN)
|
||||
for(auto &n : *nodes_map[k]){
|
||||
if(n->typeValue()==NODE_STORYCHAIN &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
}
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
QList<Result::DesNode*> ParseCore::queryStoryPoint(DesNode *chain, const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
for(auto &n : chain->children())
|
||||
if(n->typeValue() == NODE_STORYPOINT &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
QList<Result::DesNode*> ParseCore::queryStoryUnit(const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
auto keys = nodes_map.keys();
|
||||
for(auto &k : keys)
|
||||
if(k->docType() == DocType::STORYUNIT)
|
||||
for(auto &n : *nodes_map[k]){
|
||||
if(n->typeValue()==NODE_STORYUNIT &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
}
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
QList<Result::DesNode*> ParseCore::queryStoryFragment(DesNode *unit, const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
for(auto &n : unit->children())
|
||||
if(n->typeValue() == NODE_STORYFRAGMENT &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
return retlist;
|
||||
}
|
||||
|
||||
QList<Result::DesNode*> ParseCore::queryStoryBoard(const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
|
||||
auto keys = nodes_map.keys();
|
||||
for(auto &k : keys)
|
||||
if(k->docType() == DocType::STORYBOARD)
|
||||
for(auto &n : *nodes_map[k]){
|
||||
if(n->typeValue() == NODE_STORYBOARD &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
}
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
QList<DesNode *> ParseCore::queryStoryDepiction(const QString &name) const
|
||||
{
|
||||
QList<Result::DesNode*> retlist;
|
||||
for(auto &it : nodes_map.keys()) {
|
||||
if(it->docType() == DocType::STORYOUTLINES)
|
||||
for(auto &n : *nodes_map[it])
|
||||
if(n->typeValue() == NODE_STORYDEPICTION &&
|
||||
static_cast<NamedNode*>(n)->name() == name)
|
||||
retlist << n;
|
||||
}
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
|
||||
Words::Words(Result::DesNode *host, DocCore *doc, const QString & value, int row, int col)
|
||||
: value_store(value), row_store(row), col_store(col), desnode_store(host), docpresent_store(doc)
|
||||
{
|
||||
host->registerWords(this);
|
||||
}
|
||||
|
||||
int Words::row() const
|
||||
{
|
||||
return row_store;
|
||||
}
|
||||
|
||||
int Words::column() const
|
||||
{
|
||||
return col_store;
|
||||
}
|
||||
|
||||
int Words::length() const
|
||||
{
|
||||
return value_store.length();
|
||||
}
|
||||
|
||||
DesNode * Words::host() const
|
||||
{
|
||||
return desnode_store;
|
||||
}
|
||||
|
||||
DocCore * Words::doc() const
|
||||
{
|
||||
return docpresent_store;
|
||||
}
|
||||
|
||||
QString Words::toString() const
|
||||
{
|
||||
return value_store;
|
||||
}
|
||||
|
||||
DocCore::DocCore(ParseCore * core, DocType type, const QFileInfo & path)
|
||||
: unknown_host(new Unknown(this)), core_store(core),
|
||||
file_path_store(path.absoluteFilePath()), type_store(type)
|
||||
{
|
||||
}
|
||||
|
||||
DesNode * DocCore::unknowns() const
|
||||
{
|
||||
return unknown_host;
|
||||
}
|
||||
|
||||
ParseCore * DocCore::core() const
|
||||
{
|
||||
return core_store;
|
||||
}
|
||||
|
||||
DocType DocCore::docType() const
|
||||
{
|
||||
return type_store;
|
||||
}
|
||||
|
||||
QString DocCore::filePath() const
|
||||
{
|
||||
return file_path_store;
|
||||
}
|
||||
|
||||
QString DocCore::fileName() const
|
||||
{
|
||||
return QFileInfo(file_path_store).fileName();
|
||||
}
|
||||
|
||||
void DocCore::clear()
|
||||
{
|
||||
for(auto &it : words_store)
|
||||
delete it;
|
||||
|
||||
words_store.clear();
|
||||
core()->clearNodes(this);
|
||||
}
|
||||
|
||||
int DocCore::append(Words * ins)
|
||||
{
|
||||
words_store << ins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Words * DocCore::getWords(int row, int col) const
|
||||
{
|
||||
for (auto it : words_store)
|
||||
if (it->row() == row && it->column() <= col && it->column() + it->length() >= col)
|
||||
return it;
|
||||
|
||||
return nullptr;
|
||||
}
|
|
@ -1,399 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "LexFoundation.h"
|
||||
#include "ComnDef.h"
|
||||
|
||||
namespace Parse
|
||||
{
|
||||
namespace Result {
|
||||
class ParseCore;
|
||||
class DesNode;
|
||||
class NamedNode;
|
||||
class DocCore;
|
||||
}
|
||||
|
||||
|
||||
namespace Result
|
||||
{
|
||||
/**
|
||||
* 词语块,可以通过文档未知直接获取.
|
||||
*/
|
||||
class Words
|
||||
{
|
||||
public:
|
||||
explicit Words(Result::DesNode* host, Result::DocCore *doc, const QString &value, int row, int col);
|
||||
virtual ~Words() = default;
|
||||
|
||||
/**
|
||||
* 起始行位置.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual int row() const;
|
||||
|
||||
/**
|
||||
* 起始列位置.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual int column() const;
|
||||
|
||||
/**
|
||||
* 次愉快长度.
|
||||
*
|
||||
* \return 字符数量
|
||||
*/
|
||||
virtual int length() const;
|
||||
|
||||
/**
|
||||
* 获取依托节点,悬空节点返回nullptr.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual Result::DesNode* host() const;
|
||||
|
||||
/**
|
||||
* 隶属文档实例.
|
||||
*
|
||||
* \return 实例
|
||||
*/
|
||||
virtual Result::DocCore* doc() const;
|
||||
|
||||
/**
|
||||
* 获取文本内容.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual QString toString() const;
|
||||
|
||||
private:
|
||||
QString value_store;
|
||||
int row_store, col_store;
|
||||
Result::DesNode *desnode_store;
|
||||
Result::DocCore *docpresent_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* 描述性的节点,如文本节点和引用节点.
|
||||
*/
|
||||
class DesNode
|
||||
{
|
||||
public:
|
||||
DesNode(DocCore *core, int type_value, DesNode *pnode = nullptr);
|
||||
virtual ~DesNode();
|
||||
|
||||
/**
|
||||
* 节点树深度,根节点深度为0
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
int depth() const;
|
||||
/**
|
||||
* 承载文档源实例.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
DocCore* doc() const;
|
||||
|
||||
/**
|
||||
* 类型标记.
|
||||
*
|
||||
* \return 标记值
|
||||
*/
|
||||
int typeValue() const;
|
||||
|
||||
/**
|
||||
* 获取该节点的父节点.
|
||||
*
|
||||
* \return 父节点实例
|
||||
*/
|
||||
DesNode* parent() const;
|
||||
|
||||
/**
|
||||
* 添加子节点
|
||||
*
|
||||
* \param ins 节点实例
|
||||
*/
|
||||
void appendChild(DesNode *ins);
|
||||
|
||||
/**
|
||||
* 获取所有子节点
|
||||
*
|
||||
* \return 子节点集合
|
||||
*/
|
||||
QList<DesNode*> children() const;
|
||||
|
||||
/**
|
||||
* @brief 注册引用本节点的词语
|
||||
* @param ins
|
||||
*/
|
||||
void registerWords(Words *ins);
|
||||
|
||||
/**
|
||||
* @brief 获取所有引用本节点的词语
|
||||
* @return
|
||||
*/
|
||||
QList<Words*> refered() const;
|
||||
|
||||
/**
|
||||
* 检查项目错误.
|
||||
*
|
||||
* \return true,没有错误
|
||||
*/
|
||||
virtual bool check(QList<QString> &reasons) const = 0;
|
||||
|
||||
/**
|
||||
* 返回本节点的代表文本内容.
|
||||
*
|
||||
* \return 文本内容
|
||||
*/
|
||||
virtual QString toString() const = 0;
|
||||
|
||||
private:
|
||||
DocCore *const doc_store;
|
||||
int type_value;
|
||||
DesNode *const parent_node;
|
||||
|
||||
QList<DesNode*> children_nodes;
|
||||
QList<Words*> words_collection;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 声明描述节点.
|
||||
*/
|
||||
class NamedNode : public Result::DesNode
|
||||
{
|
||||
public:
|
||||
NamedNode(const QString &name, DocCore *core, int type, DesNode *pnode = nullptr);
|
||||
virtual ~NamedNode() = default;
|
||||
|
||||
/**
|
||||
* 获取此节点的名称.
|
||||
*
|
||||
* \return 名称字符串
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
private:
|
||||
QString name_store;
|
||||
|
||||
};
|
||||
|
||||
enum class DocType
|
||||
{
|
||||
STORYBOARD = DOC_STORYBOARD,
|
||||
STORYUNIT = DOC_STORYUNIT,
|
||||
STORYCHAIN = DOC_STORYCHAIN,
|
||||
STORYOUTLINES = DOC_VOLUMEOUTLINE
|
||||
};
|
||||
|
||||
/**
|
||||
* 文档实例专用于文档高亮渲染和语法补全.
|
||||
*/
|
||||
class DocCore
|
||||
{
|
||||
public:
|
||||
explicit DocCore(ParseCore* core, DocType type, const QFileInfo &path);
|
||||
virtual ~DocCore() = default;
|
||||
|
||||
/**
|
||||
* 无法识别的节点归并.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
Result::DesNode* unknowns() const;
|
||||
|
||||
/**
|
||||
* 项目实例.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
ParseCore* core() const;
|
||||
|
||||
/**
|
||||
* @brief 文档类型
|
||||
* @return
|
||||
*/
|
||||
DocType docType() const;
|
||||
|
||||
/**
|
||||
* 源文件路径.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
QString filePath() const;
|
||||
|
||||
/**
|
||||
* 文件名.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
QString fileName() const;
|
||||
|
||||
/**
|
||||
* 清除所有的词语节点和内容节点.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* 对文档实例添加节点实例.
|
||||
*
|
||||
* \param ins 节点实例
|
||||
* \return 0 - 添加成功
|
||||
*/
|
||||
int append(Words *ins);
|
||||
|
||||
|
||||
/**
|
||||
* 通过位置获取词语.
|
||||
*
|
||||
* \param row 行位置
|
||||
* \param col 列位置
|
||||
* \return 字符号
|
||||
*/
|
||||
Words* getWords(int row, int col) const;
|
||||
|
||||
private:
|
||||
Result::DesNode *const unknown_host;
|
||||
ParseCore *const core_store;
|
||||
QString file_path_store;
|
||||
DocType type_store;
|
||||
|
||||
QList<Words*> words_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析实例核心.
|
||||
*/
|
||||
class ParseCore
|
||||
{
|
||||
private:
|
||||
QString name_store;
|
||||
QHash<DocCore*, QList<DesNode*>*> nodes_map;
|
||||
|
||||
public:
|
||||
explicit ParseCore(const QString &name);
|
||||
virtual ~ParseCore() = default;
|
||||
|
||||
virtual void registerNode(DocCore *doc, DesNode *node);
|
||||
virtual void clearNodes(DocCore *ins);
|
||||
|
||||
virtual QList<DocCore *> allDocuments() const;
|
||||
|
||||
virtual QList<DesNode*> queryRootNodes(DocCore *doc) const;
|
||||
|
||||
/**
|
||||
* 获取文档内存实例,如果不存在指定实例,返回nullptr.
|
||||
*
|
||||
* \param file_path 文档路径
|
||||
* \return 实例
|
||||
*/
|
||||
virtual Result::DocCore* queryDocument(const QFileInfo &file_src) const;
|
||||
virtual void deleteDocument(Result::DocCore *ins);
|
||||
|
||||
virtual QList<Result::DesNode*> queryStoryChain(const QString & name) const;
|
||||
virtual QList<Result::DesNode*> queryStoryPoint(Result::DesNode* chain, const QString &name) const;
|
||||
|
||||
virtual QList<Result::DesNode*> queryStoryUnit(const QString &name) const;
|
||||
virtual QList<Result::DesNode*> queryStoryFragment(Result::DesNode *unit, const QString &name) const;
|
||||
|
||||
virtual QList<Result::DesNode*> queryStoryBoard(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @brief 获取卷宗大纲叙述节点
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
virtual QList<Result::DesNode*> queryStoryDepiction(const QString &name) const;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace Syntax {
|
||||
|
||||
|
||||
/**
|
||||
* 解析结果标志.
|
||||
*/
|
||||
enum class ParseResult
|
||||
{
|
||||
SelfManipulate = 1,
|
||||
EnterNext = 2,
|
||||
Completed = 3,
|
||||
Failed = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析器接口.
|
||||
*/
|
||||
class SyntaxParser
|
||||
{
|
||||
public:
|
||||
virtual ~SyntaxParser() = default;
|
||||
|
||||
/**
|
||||
* 设置当前活动的Doc实例.
|
||||
*
|
||||
* \param ins
|
||||
*/
|
||||
virtual void docActive(Parse::Result::DocCore *ins) = 0;
|
||||
|
||||
/**
|
||||
* 当前指向的文档.
|
||||
*
|
||||
* \return 文档实例
|
||||
*/
|
||||
virtual Parse::Result::DocCore* docRef() const = 0;
|
||||
/**
|
||||
* 适配当前解析.
|
||||
*
|
||||
* \param seqs
|
||||
* \return
|
||||
*/
|
||||
virtual bool applied(const QList<Lex::LexResult>& seqs) = 0;
|
||||
|
||||
/**
|
||||
* 重置解析器
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
|
||||
/**
|
||||
* 针对性的解析当前Token序列,对已经解析过的序列做摘除处理,返回下一步可能用到的解析器列表。
|
||||
*
|
||||
* \param seqs 标记序列
|
||||
* \param next_ps 下一步需要用到的解析器
|
||||
* \return 解析操作类型
|
||||
*/
|
||||
virtual ParseResult parse(QList<Lex::LexResult>& seqs)= 0;
|
||||
|
||||
/**
|
||||
* 子解析器集合.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual QList<SyntaxParser*> children() const = 0;
|
||||
|
||||
/**
|
||||
* 当前聚焦的节点.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
virtual Parse::Result::DesNode* currNode() const = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* 设置子元素解析器,内部元素解析器集合.
|
||||
*
|
||||
* \param parsers 解析器集合
|
||||
*/
|
||||
virtual void addChild(QList<SyntaxParser*> parsers) = 0;
|
||||
};
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
#include "WordsPeak.h"
|
||||
#include <QDebug>
|
||||
|
||||
using namespace Lex;
|
||||
|
||||
ExStream::ExStream() :file_target(nullptr), text_input(nullptr),
|
||||
current_line(""), current_row(-1), current_col(0) {}
|
||||
|
||||
ExStream::~ExStream() {
|
||||
if (file_target)
|
||||
delete file_target;
|
||||
if (text_input)
|
||||
delete text_input;
|
||||
}
|
||||
|
||||
int ExStream::initSource(const QString & path)
|
||||
{
|
||||
if (file_target)
|
||||
delete file_target;
|
||||
if (text_input)
|
||||
delete text_input;
|
||||
|
||||
if (!QFile(path).exists())
|
||||
return -1;
|
||||
|
||||
file_target = new QFile(path);
|
||||
if (!file_target->open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return -2;
|
||||
|
||||
text_input = new QTextStream(file_target);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::tuple<ExStream::n_row, ExStream::n_col, QChar> ExStream::read()
|
||||
{
|
||||
if (current_col >= current_line.length()) {
|
||||
if (!text_input->atEnd()) {
|
||||
current_row++;
|
||||
current_col = 0;
|
||||
current_line = text_input->readLine() + '\n';
|
||||
}
|
||||
else {
|
||||
return std::make_tuple(-1, -1, EOF);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_tuple(current_row, current_col, current_line[current_col++]);
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
#include <QFile>
|
||||
#include <tuple>
|
||||
|
||||
namespace Lex {
|
||||
class ExStream
|
||||
{
|
||||
public:
|
||||
typedef int n_row;
|
||||
typedef int n_col;
|
||||
explicit ExStream();
|
||||
virtual ~ExStream();
|
||||
|
||||
/**
|
||||
* 初始化文件指向.
|
||||
*
|
||||
* \param path 源文件
|
||||
* \return -2无法打开:-1:文件不存在,0:成功
|
||||
*/
|
||||
int initSource(const QString &path);
|
||||
|
||||
/**
|
||||
* 在文件文本流中读取一个字符.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
std::tuple<n_row, n_col, QChar> read();
|
||||
|
||||
private:
|
||||
QFile * file_target;
|
||||
QTextStream* text_input;
|
||||
|
||||
QString current_line;
|
||||
int current_row, current_col;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,435 +0,0 @@
|
|||
#include "XSyntaxBase.h"
|
||||
|
||||
using namespace Parse;
|
||||
using namespace Parse::Result;
|
||||
using namespace Syntax;
|
||||
using namespace Lex;
|
||||
using namespace Defines;
|
||||
|
||||
Link::Link(const QString & alias, Element * elm)
|
||||
: alias_name(alias), host_ins(elm), tail_mark(false) {}
|
||||
|
||||
QString Link::aliasName() const { return alias_name; }
|
||||
|
||||
QString Link::refer() const
|
||||
{
|
||||
return name(this->aliasName());
|
||||
}
|
||||
|
||||
QString Link::name(const QString & s)
|
||||
{
|
||||
QRegExp exp("^([^0-9]+)[0-9]*$");
|
||||
if (exp.indexIn(s) == -1)
|
||||
return "";
|
||||
return exp.capturedTexts()[1];
|
||||
}
|
||||
|
||||
Element * Link::host() const { return host_ins; }
|
||||
|
||||
bool Link::tailTest() const { return tail_mark; }
|
||||
|
||||
void Link::markTail(bool v)
|
||||
{
|
||||
tail_mark = v;
|
||||
}
|
||||
|
||||
void Link::appendNext(Link * ins) { next_inss << ins; }
|
||||
|
||||
QList<Link*> Link::nextElements() const { return next_inss; }
|
||||
|
||||
std::tuple<Element::rst_mark, Element::match_len>
|
||||
Link::linkCheck(const QList<LexResult>& tokens, int offset) const
|
||||
{
|
||||
// 本节点匹配失败,剩余标记长度不足
|
||||
if (tokens.size() <= offset)
|
||||
return std::make_tuple(false, 0);
|
||||
|
||||
// 节点元素匹配,获取匹配结果
|
||||
auto rst0 = host()->elementCheck(tokens, offset);
|
||||
if (!std::get<0>(rst0))
|
||||
return rst0;
|
||||
|
||||
// 本节点匹配成功,尝试下一节点匹配,调用参数向下传递
|
||||
for (auto inss : next_inss) {
|
||||
auto rst1 = inss->linkCheck(tokens, offset + std::get<1>(rst0));
|
||||
|
||||
// 随后节点完全匹配,返回累积匹配结果
|
||||
if (std::get<0>(rst1))
|
||||
return std::make_tuple(true, std::get<1>(rst0) + std::get<1>(rst1));
|
||||
}
|
||||
|
||||
// 解析链上的允许结尾,本节点是尾结点则成功,否则失败
|
||||
if (tailTest())
|
||||
return rst0;
|
||||
else
|
||||
return std::make_tuple(false, std::get<1>(rst0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验标记序列是否符合语法定义.
|
||||
*
|
||||
* \param tokens 标记序列
|
||||
* \param offset 偏移量
|
||||
* \return tuple(完全匹配指示,最大匹配长度)
|
||||
*/
|
||||
Element::Element(const QString & token)
|
||||
: value_store(token) {}
|
||||
|
||||
|
||||
QString Element::name() const
|
||||
{
|
||||
return Link::name(value_store);
|
||||
}
|
||||
|
||||
DefType Element::type() const
|
||||
{
|
||||
return DefType::ELEMENT;
|
||||
}
|
||||
|
||||
std::tuple<Element::rst_mark, Element::match_len>
|
||||
Element::elementCheck(const QList<LexResult>& tokens, int offset) const
|
||||
{
|
||||
auto u = tokens[offset];
|
||||
|
||||
if (u.Token == name())
|
||||
return std::make_tuple(true, 1);
|
||||
return std::make_tuple(false, 0);
|
||||
}
|
||||
|
||||
Expression::Expression(const QString & name)
|
||||
: Element(name), name_store(name), chain_store(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Link * Expression::parseFlow() const
|
||||
{
|
||||
return chain_store;
|
||||
}
|
||||
|
||||
void Expression::resetLinks(Link * entry)
|
||||
{
|
||||
chain_store = entry;
|
||||
}
|
||||
|
||||
DefType Expression::type() const
|
||||
{
|
||||
return DefType::EXPRESSION;
|
||||
}
|
||||
|
||||
std::tuple<Element::rst_mark, Element::match_len>
|
||||
Expression::elementCheck(const QList<LexResult>& tokens, int offset) const
|
||||
{
|
||||
if (!chain_store)
|
||||
return std::make_tuple(false, 0);
|
||||
|
||||
return chain_store->linkCheck(tokens, offset);
|
||||
}
|
||||
|
||||
ParseRule::ParseRule(XSyntaxBase * host, const QString & rule_name, unsigned short level,
|
||||
std::function<ParseResult(const QList<LexResult>&, int)> exc)
|
||||
: enable_state(true), host_ins(host), level_store(level),
|
||||
name_store(rule_name), exc_store(exc) {}
|
||||
|
||||
int ParseRule::level() const
|
||||
{
|
||||
return level_store;
|
||||
}
|
||||
|
||||
QString ParseRule::name() const
|
||||
{
|
||||
return name_store;
|
||||
}
|
||||
|
||||
void ParseRule::setEnable(bool v)
|
||||
{
|
||||
this->enable_state = v;
|
||||
}
|
||||
|
||||
void Syntax::ParseRule::addExpression(const QString &name, const QList<Elm> &defines)
|
||||
{
|
||||
// 生成表达式实例
|
||||
auto exp = host_ins->get_expression(Link::name(name));
|
||||
|
||||
// 逐个构建表达式或者元素
|
||||
QList<Link*> link_rebuilds;
|
||||
for (auto& def_it : defines) {
|
||||
// 校验既有元素回环
|
||||
auto size0 = link_rebuilds.size();
|
||||
for (auto prv_it : link_rebuilds) {
|
||||
if (prv_it->aliasName() == def_it.aliasName()) {
|
||||
link_rebuilds << prv_it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有找到元素回环
|
||||
if (size0 == link_rebuilds.size()) {
|
||||
Link* tins = nullptr;
|
||||
if (def_it.type() == DefType::ELEMENT)
|
||||
tins = new Link(def_it.aliasName(), host_ins->get_element(def_it.refer()));
|
||||
else
|
||||
tins = new Link(def_it.aliasName(), host_ins->get_expression(def_it.refer()));
|
||||
|
||||
link_rebuilds << tins;
|
||||
}
|
||||
|
||||
// 标记结尾可能性
|
||||
if (!link_rebuilds.last()->tailTest())
|
||||
link_rebuilds.last()->markTail(def_it.isTail());
|
||||
}
|
||||
|
||||
// 匹配链构建
|
||||
for (auto idx = 1; idx < link_rebuilds.size(); ++idx) {
|
||||
auto prv_it = link_rebuilds[idx - 1];
|
||||
prv_it->appendNext(link_rebuilds[idx]);
|
||||
}
|
||||
|
||||
exp->resetLinks(link_rebuilds.first());
|
||||
expression_list << exp;
|
||||
}
|
||||
|
||||
std::tuple<bool, int> ParseRule::tokensMatch(const QList<LexResult>& token) const
|
||||
{
|
||||
if(enable_state)
|
||||
for (auto expx : expression_list) {
|
||||
auto result = expx->elementCheck(token, 0);
|
||||
if (std::get<0>(result)) {
|
||||
return std::make_tuple(true, std::get<1>(result));
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_tuple(false, 0);
|
||||
}
|
||||
|
||||
ParseResult ParseRule::syntaxTrigger(const QList<LexResult>& srcs, int count) {
|
||||
return exc_store(srcs, count);
|
||||
}
|
||||
|
||||
XSyntaxBase::XSyntaxBase(const QString & section, MatchType type)
|
||||
: target_type(type), section_name(section), current_level(INT_MAX), current_node(nullptr) {}
|
||||
|
||||
ParseRule * XSyntaxBase::addRule(const QString & name, unsigned short level,
|
||||
std::function<ParseResult(const QList<LexResult>&, int)> exc)
|
||||
{
|
||||
if (!rule_collect.contains(name)) {
|
||||
auto rule = new ParseRule(this, name, level, exc);
|
||||
rule_collect[name] = rule;
|
||||
}
|
||||
return rule_collect[name];
|
||||
}
|
||||
|
||||
inline Expression * XSyntaxBase::get_expression(const QString & name) {
|
||||
if (!expressions_store.contains(name)) {
|
||||
auto u = new Expression(name);
|
||||
expressions_store[name] = u;
|
||||
}
|
||||
return expressions_store[name];
|
||||
}
|
||||
|
||||
inline Element * XSyntaxBase::get_element(const QString & name)
|
||||
{
|
||||
if (!elements_store.contains(name)) {
|
||||
auto u = new Element(name);
|
||||
elements_store[name] = u;
|
||||
}
|
||||
return elements_store[name];
|
||||
}
|
||||
|
||||
void XSyntaxBase::addChild(QList<SyntaxParser*> parsers)
|
||||
{
|
||||
this->child_parsers.append(parsers);
|
||||
}
|
||||
|
||||
void XSyntaxBase::docActive(DocCore * ins)
|
||||
{
|
||||
src_ref = ins;
|
||||
for (auto &it : children())
|
||||
it->docActive(ins);
|
||||
}
|
||||
|
||||
DocCore * XSyntaxBase::docRef() const
|
||||
{
|
||||
return src_ref;
|
||||
}
|
||||
|
||||
bool XSyntaxBase::applied(const QList<LexResult>& seqs)
|
||||
{
|
||||
// 求取最小等级的parse-rule
|
||||
ParseRule* first_rule = *rule_collect.cbegin();
|
||||
for (auto &rule : rule_collect) {
|
||||
if (rule->level() <= first_rule->level())
|
||||
first_rule = rule;
|
||||
}
|
||||
|
||||
// 执行准入匹配,在最小等级匹配规则上进行匹配结算
|
||||
for (auto &rule : rule_collect) {
|
||||
if (rule->level() != first_rule->level())
|
||||
continue;
|
||||
|
||||
auto result = rule->tokensMatch(seqs);
|
||||
|
||||
if (std::get<0>(result)) {
|
||||
current_level = rule->level();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void XSyntaxBase::reset()
|
||||
{
|
||||
// 重置标记
|
||||
current_level = INT_MAX;
|
||||
|
||||
for (auto &x : rule_collect)
|
||||
if (current_level > x->level())
|
||||
current_level = x->level();
|
||||
|
||||
current_node = nullptr;
|
||||
}
|
||||
|
||||
ParseResult XSyntaxBase::parse(QList<LexResult>& seqs)
|
||||
{
|
||||
// 求取符合等级的parse-rule
|
||||
QList<ParseRule*> rules_set;
|
||||
for (auto &rule : rule_collect) {
|
||||
if (rule->level() >= current_level)
|
||||
rules_set << rule;
|
||||
}
|
||||
|
||||
std::tuple<bool, int, ParseRule*> max_result = std::make_tuple(false, 0, nullptr);
|
||||
// 使用符合等级的解析规则解析
|
||||
for (auto &rule : rules_set) {
|
||||
auto result = rule->tokensMatch(seqs);
|
||||
if (std::get<0>(result) && current_level <= rule->level()) {
|
||||
current_level = rule->level();
|
||||
max_result = std::make_tuple(true, std::get<1>(result), rule);
|
||||
}
|
||||
}
|
||||
|
||||
if (!std::get<0>(max_result)) {
|
||||
if (target_type == MatchType::Outline)
|
||||
return ParseResult::Completed;
|
||||
return ParseResult::Failed;
|
||||
}
|
||||
else { // 匹配成功
|
||||
if (target_type == MatchType::Outline) {
|
||||
if (current_node == nullptr) {
|
||||
return std::get<2>(max_result)->syntaxTrigger(seqs, std::get<1>(max_result));
|
||||
}
|
||||
else {
|
||||
return ParseResult::Completed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto xresult = std::get<2>(max_result)->syntaxTrigger(seqs, std::get<1>(max_result));
|
||||
|
||||
if (target_type == MatchType::Entirely) {
|
||||
auto count = std::get<1>(max_result);
|
||||
while (count--)
|
||||
seqs.removeFirst();
|
||||
}
|
||||
return xresult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<SyntaxParser*> XSyntaxBase::children() const
|
||||
{
|
||||
return child_parsers;
|
||||
}
|
||||
|
||||
void XSyntaxBase::refocusNode(DesNode * ins)
|
||||
{
|
||||
current_node = ins;
|
||||
}
|
||||
|
||||
Expression *XSyntaxBase::set_common_expression(const QString &name, const QList<Defines::Elm> &defines)
|
||||
{
|
||||
if (expressions_store.contains(Link::name(name)))
|
||||
return nullptr;
|
||||
|
||||
auto ins = get_expression(Link::name(name));
|
||||
// 逐个构建表达式或者元素
|
||||
QList<Link*> link_rebuilds;
|
||||
for (auto& def_it : defines) {
|
||||
// 校验既有元素回环
|
||||
auto size0 = link_rebuilds.size();
|
||||
for (auto prv_it : link_rebuilds) {
|
||||
if (prv_it->aliasName() == def_it.aliasName()) {
|
||||
link_rebuilds << prv_it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有找到元素回环
|
||||
if (size0 == link_rebuilds.size()) {
|
||||
Link* tins = nullptr;
|
||||
if (def_it.type() == DefType::ELEMENT)
|
||||
tins = new Link(def_it.aliasName(), get_element(def_it.refer()));
|
||||
else
|
||||
tins = new Link(def_it.aliasName(), get_expression(def_it.refer()));
|
||||
|
||||
link_rebuilds << tins;
|
||||
}
|
||||
|
||||
// 标记结尾可能性
|
||||
link_rebuilds.last()->markTail(def_it.isTail());
|
||||
}
|
||||
|
||||
// 匹配链构建
|
||||
for (auto idx = 1; idx < link_rebuilds.size(); ++idx) {
|
||||
auto prv_it = link_rebuilds[idx - 1];
|
||||
prv_it->appendNext(link_rebuilds[idx]);
|
||||
}
|
||||
|
||||
ins->resetLinks(link_rebuilds.first());
|
||||
return ins;
|
||||
}
|
||||
|
||||
void XSyntaxBase::resetMatch(MatchType mtype)
|
||||
{
|
||||
this->target_type = mtype;
|
||||
}
|
||||
|
||||
DesNode * XSyntaxBase::currNode() const
|
||||
{
|
||||
return current_node;
|
||||
}
|
||||
|
||||
Elm::Elm(const QString &alias_name, bool tail_mark)
|
||||
: name_store(alias_name), tail_mark(tail_mark),
|
||||
type_define(DefType::ELEMENT) {}
|
||||
|
||||
QString Elm::aliasName() const
|
||||
{
|
||||
return this->name_store;
|
||||
}
|
||||
|
||||
QString Elm::refer() const
|
||||
{
|
||||
return Link::name(this->name_store);
|
||||
}
|
||||
|
||||
|
||||
bool Elm::isTail() const
|
||||
{
|
||||
return tail_mark;
|
||||
}
|
||||
|
||||
DefType Elm::type() const
|
||||
{
|
||||
return type_define;
|
||||
}
|
||||
|
||||
Exp::Exp(const QString& alias_name, bool tail_mark)
|
||||
: Elm(alias_name, tail_mark)
|
||||
{
|
||||
type_define = DefType::EXPRESSION;
|
||||
}
|
||||
|
||||
DefType Exp::type() const
|
||||
{
|
||||
return type_define;
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
#pragma once
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include "LexFoundation.h"
|
||||
#include "SyntaxBase.h"
|
||||
|
||||
namespace Syntax
|
||||
{
|
||||
/**
|
||||
*专用于定义语法树的命名空间
|
||||
*/
|
||||
namespace Defines
|
||||
{
|
||||
/**
|
||||
* @brief 元素定义类型
|
||||
*/
|
||||
enum class DefType
|
||||
{
|
||||
ELEMENT,
|
||||
EXPRESSION
|
||||
};
|
||||
|
||||
/**
|
||||
* 元素定义声明.
|
||||
*/
|
||||
class Elm
|
||||
{
|
||||
public:
|
||||
explicit Elm(const QString &alias_name, bool tail_mark = false);
|
||||
virtual ~Elm() = default;
|
||||
|
||||
/**
|
||||
* 定义名称,定义别名.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
QString aliasName() const;
|
||||
/**
|
||||
* 引用.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
QString refer() const;
|
||||
/**
|
||||
* 匹配类型.
|
||||
*
|
||||
* \return 元素或表达式
|
||||
*/
|
||||
virtual DefType type() const;
|
||||
|
||||
/**
|
||||
* 是否具有结尾标记.
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
bool isTail() const;
|
||||
|
||||
private:
|
||||
QString name_store;
|
||||
bool tail_mark;
|
||||
|
||||
protected:
|
||||
DefType type_define;
|
||||
};
|
||||
|
||||
/**
|
||||
* 表达式定义声明.
|
||||
*/
|
||||
class Exp : public Elm
|
||||
{
|
||||
public:
|
||||
explicit Exp(const QString &alias_name, bool tail_mark = false);
|
||||
virtual ~Exp() = default;
|
||||
|
||||
virtual DefType type() const override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验元素,单个token校验.
|
||||
*/
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
typedef bool rst_mark;
|
||||
typedef int match_len;
|
||||
|
||||
explicit Element(const QString &token);
|
||||
virtual ~Element() = default;
|
||||
|
||||
QString name() const;
|
||||
virtual Defines::DefType type() const;
|
||||
|
||||
/**
|
||||
* 校验标记序列是否符合语法定义.
|
||||
*
|
||||
* \param tokens 标记序列
|
||||
* \param offset 偏移量
|
||||
* \return tuple(完全匹配指示,最大匹配长度)
|
||||
*/
|
||||
virtual std::tuple<rst_mark, match_len>
|
||||
elementCheck(const QList<Lex::LexResult> &tokens, int offset) const;
|
||||
|
||||
private:
|
||||
QString value_store;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 语法匹配调用链
|
||||
*/
|
||||
class Link
|
||||
{
|
||||
public:
|
||||
Link(const QString &alias, Element *elm);
|
||||
virtual ~Link() = default;
|
||||
|
||||
static QString name(const QString &s);
|
||||
QString aliasName() const;
|
||||
QString refer() const;
|
||||
Element* host() const;
|
||||
|
||||
bool tailTest() const;
|
||||
void markTail(bool v);
|
||||
|
||||
void appendNext(Link* ins);
|
||||
QList<Link*> nextElements() const;
|
||||
|
||||
virtual std::tuple<Element::rst_mark, Element::match_len>
|
||||
linkCheck(const QList<Lex::LexResult> &tokens, int offset) const;
|
||||
|
||||
private:
|
||||
QString alias_name;
|
||||
Element *const host_ins;
|
||||
bool tail_mark;
|
||||
|
||||
QList<Link*> next_inss;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 校验表达式,多个语法元素顺序校验
|
||||
*/
|
||||
class Expression : public Element
|
||||
{
|
||||
public:
|
||||
explicit Expression(const QString &name);
|
||||
virtual ~Expression() = default;
|
||||
|
||||
Link* parseFlow() const;
|
||||
void resetLinks(Link* entry);
|
||||
|
||||
virtual Defines::DefType type() const override;
|
||||
|
||||
/**
|
||||
* 校验标记序列是否符合语法定义.
|
||||
*
|
||||
* \param tokens 标记序列
|
||||
* \param offset 偏移量
|
||||
* \return tuple(完全匹配指示,最大匹配长度)
|
||||
*/
|
||||
virtual std::tuple<rst_mark, match_len>
|
||||
elementCheck(const QList<Lex::LexResult> &tokens, int offset) const override;
|
||||
|
||||
private:
|
||||
QString name_store;
|
||||
Link* chain_store;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class XSyntaxBase;
|
||||
|
||||
/**
|
||||
* @brief 定义解析规则,支持多范式表达式匹配
|
||||
*/
|
||||
class ParseRule
|
||||
{
|
||||
public:
|
||||
ParseRule(XSyntaxBase *host, const QString &rule_name, unsigned short level,
|
||||
std::function<ParseResult(const QList<Lex::LexResult>&, int)>);
|
||||
virtual ~ParseRule() = default;
|
||||
|
||||
int level() const;
|
||||
QString name() const;
|
||||
void setEnable(bool v);
|
||||
|
||||
void addExpression(const QString &name, const QList<Defines::Elm> &_defines);
|
||||
std::tuple<bool, int> tokensMatch(const QList<Lex::LexResult> &token) const;
|
||||
ParseResult syntaxTrigger(const QList<Lex::LexResult>& srcs, int count);
|
||||
|
||||
private:
|
||||
bool enable_state;
|
||||
XSyntaxBase *const host_ins;
|
||||
int level_store;
|
||||
QString name_store;
|
||||
QList<Expression*> expression_list;
|
||||
|
||||
std::function<ParseResult(const QList<Lex::LexResult>&, int)> exc_store;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 解析器的语法匹配形式
|
||||
*/
|
||||
enum class MatchType
|
||||
{
|
||||
Outline,
|
||||
Entirely
|
||||
};
|
||||
|
||||
/**
|
||||
* 基础解析器模型.
|
||||
*/
|
||||
class XSyntaxBase : public Syntax::SyntaxParser
|
||||
{
|
||||
public:
|
||||
explicit XSyntaxBase(const QString §ion, MatchType type = MatchType::Entirely);
|
||||
|
||||
Expression* get_expression(const QString &name);
|
||||
Element *get_element(const QString &name);
|
||||
|
||||
// 通过 Parse::SyntaxParser 继承
|
||||
virtual void docActive(Parse::Result::DocCore *ins) override;
|
||||
virtual Parse::Result::DocCore *docRef() const override;
|
||||
virtual bool applied(const QList<Lex::LexResult>& seqs) override;
|
||||
virtual void reset() override;
|
||||
virtual ParseResult parse(QList<Lex::LexResult>& seqs) override;
|
||||
virtual QList<Syntax::SyntaxParser*> children() const override;
|
||||
|
||||
virtual Parse::Result::DesNode * currNode() const override;
|
||||
|
||||
protected:
|
||||
ParseRule* addRule(const QString &name, unsigned short level, std::function<ParseResult(const QList<Lex::LexResult>&, int)> exc);
|
||||
virtual void addChild(QList<Syntax::SyntaxParser*> parsers) override;
|
||||
void refocusNode(Parse::Result::DesNode *ins);
|
||||
|
||||
Expression* set_common_expression(const QString &name, const QList<Defines::Elm> &defines);
|
||||
void resetMatch(MatchType mtype);
|
||||
|
||||
private:
|
||||
MatchType target_type;
|
||||
QString section_name;
|
||||
int current_level;
|
||||
Parse::Result::DesNode *current_node;
|
||||
Parse::Result::DocCore *src_ref;
|
||||
|
||||
QHash<QString, Element*> elements_store;
|
||||
QHash<QString, Expression*> expressions_store;
|
||||
QList<Syntax::SyntaxParser*> child_parsers;
|
||||
|
||||
QHash<QString, ParseRule*> rule_collect;
|
||||
};
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue