QtNovelUI/DesParser/XSyntaxBase.cpp

415 lines
9.4 KiB
C++
Raw Normal View History

2022-11-06 00:37:50 +00:00
#include "XSyntaxBase.h"
using namespace Parse;
2022-11-06 11:40:11 +00:00
using namespace Parse::Result;
2022-11-06 00:37:50 +00:00
using namespace Syntax;
using namespace Lex;
using namespace Defines;
Link::Link(const QString & alias, Element * elm)
2022-11-06 10:15:55 +00:00
: alias_name(alias), host_ins(elm), tail_mark(false) {}
2022-11-06 00:37:50 +00:00
QString Link::aliasName() const { return alias_name; }
QString Link::refer() const
{
2022-11-06 10:15:55 +00:00
return name(this->aliasName());
2022-11-06 00:37:50 +00:00
}
QString Link::name(const QString & s)
{
2022-11-06 10:15:55 +00:00
QRegExp exp("^([^0-9]+)[0-9]*$");
if (exp.indexIn(s) == -1)
return "";
return exp.capturedTexts()[1];
2022-11-06 00:37:50 +00:00
}
Element * Link::host() const { return host_ins; }
bool Link::tailTest() const { return tail_mark; }
void Link::markTail(bool v)
{
2022-11-06 10:15:55 +00:00
tail_mark = v;
2022-11-06 00:37:50 +00:00
}
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
{
2022-11-06 10:15:55 +00:00
// 本节点匹配失败,剩余标记长度不足
if (tokens.size() <= offset)
return std::make_tuple(false, 0);
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
// 节点元素匹配,获取匹配结果
auto rst0 = host()->elementCheck(tokens, offset);
if (!std::get<0>(rst0))
return rst0;
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
// 本节点匹配成功,尝试下一节点匹配,调用参数向下传递
for (auto inss : next_inss) {
auto rst1 = inss->linkCheck(tokens, offset + std::get<1>(rst0));
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
// 随后节点完全匹配,返回累积匹配结果
if (std::get<0>(rst1))
return std::make_tuple(true, std::get<1>(rst0) + std::get<1>(rst1));
}
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
// 解析链上的允许结尾,本节点是尾结点则成功,否则失败
if (tailTest())
return rst0;
else
return std::make_tuple(false, std::get<1>(rst0));
2022-11-06 00:37:50 +00:00
}
/**
* .
*
* \param tokens
* \param offset
* \return tuple()
*/
Element::Element(const QString & token)
2022-11-06 10:15:55 +00:00
: value_store(token) {}
2022-11-06 00:37:50 +00:00
QString Element::name() const
{
2022-11-06 10:15:55 +00:00
return Link::name(value_store);
2022-11-06 00:37:50 +00:00
}
DefType Element::type() const
{
2022-11-06 10:15:55 +00:00
return DefType::ELEMENT;
2022-11-06 00:37:50 +00:00
}
std::tuple<Element::rst_mark, Element::match_len>
Element::elementCheck(const QList<LexResult>& tokens, int offset) const
{
2022-11-06 10:15:55 +00:00
auto u = tokens[offset];
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
if (u.Token == name())
return std::make_tuple(true, 1);
return std::make_tuple(false, 0);
2022-11-06 00:37:50 +00:00
}
Expression::Expression(const QString & name)
2022-11-06 10:15:55 +00:00
: Element(name), name_store(name), chain_store(nullptr)
2022-11-06 00:37:50 +00:00
{
}
Link * Expression::parseFlow() const
{
2022-11-06 10:15:55 +00:00
return chain_store;
2022-11-06 00:37:50 +00:00
}
void Expression::resetLinks(Link * entry)
{
2022-11-06 10:15:55 +00:00
chain_store = entry;
2022-11-06 00:37:50 +00:00
}
DefType Expression::type() const
{
2022-11-06 10:15:55 +00:00
return DefType::EXPRESSION;
2022-11-06 00:37:50 +00:00
}
std::tuple<Element::rst_mark, Element::match_len>
Expression::elementCheck(const QList<LexResult>& tokens, int offset) const
{
2022-11-06 10:15:55 +00:00
if (!chain_store)
return std::make_tuple(false, 0);
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
return chain_store->linkCheck(tokens, offset);
2022-11-06 00:37:50 +00:00
}
ParseRule::ParseRule(XSyntaxBase * host, const QString & rule_name, unsigned short level,
2022-11-06 10:15:55 +00:00
std::function<ParseResult(const QList<LexResult>&, int)> exc)
: host_ins(host), level_store(level),
name_store(rule_name), exc_store(exc) {}
2022-11-06 00:37:50 +00:00
int ParseRule::level() const
{
2022-11-06 10:15:55 +00:00
return level_store;
2022-11-06 00:37:50 +00:00
}
QString ParseRule::name() const
{
2022-11-06 10:15:55 +00:00
return name_store;
2022-11-06 00:37:50 +00:00
}
void Syntax::ParseRule::addExpression(const QString &name, const QList<Elm> &defines)
{
2022-11-06 10:15:55 +00:00
// 生成表达式实例
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
{
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);
2022-11-06 00:37:50 +00:00
}
ParseResult ParseRule::syntaxTrigger(const QList<LexResult>& srcs, int count) {
2022-11-06 10:15:55 +00:00
return exc_store(srcs, count);
2022-11-06 00:37:50 +00:00
}
2022-11-06 10:15:55 +00:00
XSyntaxBase::XSyntaxBase(const QString & section, MatchType type)
: target_type(type), section_name(section), current_level(-1), current_node(nullptr) {}
2022-11-06 00:37:50 +00:00
ParseRule * XSyntaxBase::addRule(const QString & name, unsigned short level,
2022-11-06 10:15:55 +00:00
std::function<ParseResult(const QList<LexResult>&, int)> exc)
2022-11-06 00:37:50 +00:00
{
2022-11-06 10:15:55 +00:00
if (!rule_collect.contains(name)) {
auto rule = new ParseRule(this, name, level, exc);
rule_collect[name] = rule;
}
return rule_collect[name];
2022-11-06 00:37:50 +00:00
}
inline Expression * XSyntaxBase::get_expression(const QString & name) {
2022-11-06 10:15:55 +00:00
if (!expressions_store.contains(name)) {
auto u = new Expression(name);
expressions_store[name] = u;
}
return expressions_store[name];
2022-11-06 00:37:50 +00:00
}
inline Element * XSyntaxBase::get_element(const QString & name)
{
2022-11-06 10:15:55 +00:00
if (!elements_store.contains(name)) {
auto u = new Element(name);
elements_store[name] = u;
}
return elements_store[name];
2022-11-06 00:37:50 +00:00
}
void XSyntaxBase::addChild(QList<SyntaxParser*> parsers)
{
2022-11-06 10:15:55 +00:00
this->child_parsers.append(parsers);
2022-11-06 00:37:50 +00:00
}
void XSyntaxBase::docActive(DocCore * ins)
{
2022-11-06 10:15:55 +00:00
src_ref = ins;
for (auto &it : children())
it->docActive(ins);
2022-11-06 00:37:50 +00:00
}
DocCore * XSyntaxBase::docRef() const
{
2022-11-06 10:15:55 +00:00
return src_ref;
2022-11-06 00:37:50 +00:00
}
bool XSyntaxBase::applied(const QList<LexResult>& seqs)
{
2022-11-06 10:15:55 +00:00
// 求取最小等级的parse-rule
ParseRule* first_rule = *rule_collect.cbegin();
for (auto &rule : rule_collect) {
if (rule->level() <= first_rule->level())
first_rule = rule;
}
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
// 执行准入匹配,在最小等级匹配规则上进行匹配结算
for (auto &rule : rule_collect) {
if (rule->level() != first_rule->level())
continue;
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
auto result = rule->tokensMatch(seqs);
if (std::get<0>(result)) {
current_level = rule->level();
return true;
}
}
return false;
2022-11-06 00:37:50 +00:00
}
void XSyntaxBase::reset()
{
2022-11-06 10:15:55 +00:00
// 重置标记
current_level = INT_MAX;
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
for (auto &x : rule_collect)
if (current_level > x->level())
current_level = x->level();
2022-11-06 00:37:50 +00:00
2022-11-06 10:15:55 +00:00
current_node = nullptr;
2022-11-06 00:37:50 +00:00
}
ParseResult XSyntaxBase::parse(QList<LexResult>& seqs)
{
2022-11-06 10:15:55 +00:00
// 求取符合等级的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::Entirely)
return ParseResult::Failed;
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;
}
2022-11-06 00:37:50 +00:00
}
QList<SyntaxParser*> XSyntaxBase::children() const
{
2022-11-06 10:15:55 +00:00
return child_parsers;
2022-11-06 00:37:50 +00:00
}
void XSyntaxBase::refocusNode(DesNode * ins)
{
2022-11-06 10:15:55 +00:00
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;
2022-11-06 00:37:50 +00:00
}
DesNode * XSyntaxBase::currNode() const
{
2022-11-06 10:15:55 +00:00
return current_node;
2022-11-06 00:37:50 +00:00
}
Elm::Elm(const QString &alias_name, bool tail_mark)
2022-11-06 10:15:55 +00:00
: name_store(alias_name), tail_mark(tail_mark),
type_define(DefType::ELEMENT) {}
2022-11-06 00:37:50 +00:00
QString Elm::aliasName() const
{
2022-11-06 10:15:55 +00:00
return this->name_store;
2022-11-06 00:37:50 +00:00
}
QString Elm::refer() const
{
2022-11-06 10:15:55 +00:00
return Link::name(this->name_store);
2022-11-06 00:37:50 +00:00
}
bool Elm::isTail() const
{
2022-11-06 10:15:55 +00:00
return tail_mark;
2022-11-06 00:37:50 +00:00
}
DefType Elm::type() const
{
2022-11-06 10:15:55 +00:00
return type_define;
2022-11-06 00:37:50 +00:00
}
Exp::Exp(const QString& alias_name, bool tail_mark)
2022-11-06 10:15:55 +00:00
: Elm(alias_name, tail_mark)
2022-11-06 00:37:50 +00:00
{
2022-11-06 10:15:55 +00:00
type_define = DefType::EXPRESSION;
2022-11-06 00:37:50 +00:00
}
DefType Exp::type() const
{
2022-11-06 10:15:55 +00:00
return type_define;
2022-11-06 00:37:50 +00:00
}