QtNovelUI/libParse/syntax_foundation.cpp

243 lines
6.9 KiB
C++
Raw Normal View History

#include "syntax_foundation.h"
#include "lex_foundation.h"
using namespace SyntaxX;
using namespace Ast;
void *TokenRule::operator new(size_t s) {
auto ins = ::operator new(s);
static_cast<TokenRule *>(ins)->build_within_heap = true;
return ins;
}
TokenRule::TokenRule(const Lex::TokenDef &def) : token_type(def) {}
BaseRule *TokenRule::toHeap() && {
auto ins = new TokenRule(this->token_type);
return ins;
}
bool TokenRule::heapMark() const { return build_within_heap; }
QPair<uint, Result> TokenRule::match(Lex::TokenReader *port, uint start, uint count) const noexcept {
auto target = port->tokenPeak(start);
if (target->def()->typeName() == this->token_type.typeName())
return qMakePair(1, Result::All);
return qMakePair(0, Result::Fail);
}
void TokenRule::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
auto token = port->read();
auto leaf = new ASTLeaf(parent, token);
parent->insert(parent->count(), leaf);
}
Repeat::Repeat(BaseRule *item, uint min, uint max) : item_store(*item), match_max(max), match_min(min) {
if (match_min < 1 || match_min >= match_max)
throw new Lex::WsBaseException("匹配参数错误:匹配次数参数设置错误");
}
Repeat::Repeat(BaseRule &&item, uint min, uint max) : Repeat(&item, min, max) {}
void *Repeat::operator new(size_t s) {
auto ins = ::operator new(s);
static_cast<Repeat *>(ins)->build_within_heap = true;
return ins;
}
BaseRule *Repeat::toHeap() && { return new Repeat(&this->item_store, match_max); }
bool Repeat::heapMark() const { return this->build_within_heap; }
QPair<uint, Result> Repeat::match(Lex::TokenReader *port, uint start, uint count) const noexcept { return item_store.match(port, start, count); }
void Repeat::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
auto repeat_times = 0;
while (item_store.match(port, 0, UINT_MAX).second == Result::All) {
item_store.parse(port, parent);
repeat_times++;
if (repeat_times == match_max)
break;
}
if (repeat_times < match_min)
throw new SyntaxException(*port->tokenPeak(0), "指定Token不符合Repeat语法定义");
}
using namespace Lex;
ElmRule::ElmRule() : item_store(nullptr) {}
ElmRule::~ElmRule() { delete item_store; }
void ElmRule::resetProcess(std::function<ASTList *(Lex::TokenReader *, Ast::ASTList *)> exec) { this->exec_store = exec; }
void ElmRule::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
auto result = this->exec_store(port, parent);
parent->insert(parent->count(), result);
this->item_store->parse(port, result);
}
BaseRule *ElmRule::toHeap() && { throw new WsBaseException("不允许ElmRule构建堆实例"); }
bool ElmRule::heapMark() const { return false; }
void ElmRule::setRule(BaseRule &&item) { this->item_store = std::move(item).toHeap(); }
QPair<uint, Result> ElmRule::match(Lex::TokenReader *port, uint start, uint count) const noexcept { return item_store->match(port, start, count); }
Seqs::Seqs() {}
Seqs::Seqs(Seqs &&other) {
this->items_rule.append(other.items_rule);
other.items_rule.clear();
}
Seqs::~Seqs() {
for (auto &it : items_rule)
if (it->heapMark())
delete it;
items_rule.clear();
}
void *Seqs::operator new(size_t s) {
auto ins = ::operator new(s);
static_cast<Seqs *>(ins)->build_within_heap = true;
return ins;
}
BaseRule *Seqs::toHeap() && {
auto ins = new Seqs();
ins->items_rule.append(this->items_rule);
this->items_rule.clear();
return ins;
}
bool Seqs::heapMark() const { return this->build_within_heap; }
QPair<uint, Result> Seqs::match(Lex::TokenReader *port, uint start, uint count) const noexcept {
auto m_len = 0;
for (auto &it : items_rule) {
auto next_count = count - m_len;
if (next_count <= 0)
return qMakePair(count, Result::Part);
auto m_rst = it->match(port, start + m_len, next_count);
if (m_rst.second == Result::All) {
m_len += m_rst.first;
} else {
if (m_len + m_rst.first == 0)
return qMakePair(0, Result::Fail);
else
return qMakePair(m_len + m_rst.first, Result::Part);
}
}
return qMakePair(m_len, Result::All);
}
void Seqs::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
for (auto &it : items_rule) {
if (it->match(port, 0, UINT32_MAX).second == Result::All) {
it->parse(port, parent);
} else {
}
}
}
Any::Any() {}
Any::Any(Any &&other) {
items_rule.append(other.items_rule);
other.items_rule.clear();
}
Any::~Any() {
for (auto &it : items_rule)
if (it->heapMark())
delete it;
items_rule.clear();
}
void *Any::operator new(size_t s) {
auto ins = ::operator new(s);
static_cast<Any *>(ins)->build_within_heap = true;
return ins;
}
BaseRule *Any::toHeap() && {
auto ins = new Any();
ins->items_rule.append(this->items_rule);
this->items_rule.clear();
return ins;
}
bool Any::heapMark() const { return this->build_within_heap; }
QPair<uint, Result> Any::match(Lex::TokenReader *port, uint start, uint count) const noexcept {
auto match_rst = qMakePair(0, Result::Fail);
for (auto &it : items_rule) {
auto rst = it->match(port, start, count);
if (rst.second == Result::All)
return rst;
if (rst.first > match_rst.first) {
match_rst = rst;
}
}
return match_rst;
}
void Any::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
auto match_rst = qMakePair<uint, BaseRule *>(-1, items_rule.first());
for (auto &it : items_rule) {
auto rst = it->match(port, 0, UINT32_MAX);
if (rst.second == Result::All) {
match_rst = qMakePair(rst.first, it);
break;
}
if (rst.first > match_rst.first) {
match_rst = qMakePair(rst.first, it);
}
}
match_rst.second->parse(port, parent);
}
SyntaxException::SyntaxException(const Lex::Token &tins, const QString &simple) : Lex::WsBaseException(simple), target(tins) {}
const Token &SyntaxException::targetToken() const { return this->target; }
void *Optional::operator new(size_t s) {
auto ins = ::operator new(s);
static_cast<Optional *>(ins)->build_within_heap = true;
return ins;
}
Optional::Optional(BaseRule *item) : item_store(*item) {}
Optional::Optional(BaseRule &&item) : item_store(item) {}
BaseRule *Optional::toHeap() && { return new Optional(&item_store); }
bool Optional::heapMark() const { return build_within_heap; }
QPair<uint, Result> Optional::match(Lex::TokenReader *port, uint start, uint count) const noexcept {
auto rst = item_store.match(port, start, count);
if (rst.second != Result::All)
return qMakePair(0, Result::All);
return rst;
}
void Optional::parse(Lex::TokenReader *port, Ast::ASTList *parent) {
if (this->match(port, 0, UINT32_MAX).second == Result::All)
item_store.parse(port, parent);
}