QtNovelUI/libParse/XSyntaxBase.cpp

442 lines
11 KiB
C++

#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)
{
if(!seqs.size())
return false;
// 求取最小等级的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)
{
if(!seqs.size())
return ParseResult::Failed;
// 求取符合等级的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;
}