243 lines
6.9 KiB
C++
243 lines
6.9 KiB
C++
#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);
|
|
}
|