#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::nextElements() const { return next_inss; } std::tuple Link::linkCheck(const QList& 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::elementCheck(const QList& 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 Expression::elementCheck(const QList& 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&, 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 &defines) { // 生成表达式实例 auto exp = host_ins->get_expression(Link::name(name)); // 逐个构建表达式或者元素 QList 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 ParseRule::tokensMatch(const QList& 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& 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&, 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 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& 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& seqs) { if(!seqs.size()) return ParseResult::Failed; // 求取符合等级的parse-rule QList rules_set; for (auto &rule : rule_collect) { if (rule->level() >= current_level) rules_set << rule; } std::tuple 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 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) { if (expressions_store.contains(Link::name(name))) return nullptr; auto ins = get_expression(Link::name(name)); // 逐个构建表达式或者元素 QList 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; }