143 lines
5.1 KiB
C++
143 lines
5.1 KiB
C++
#include "ast_gen.h"
|
||
|
||
using namespace ast_gen;
|
||
|
||
ExprTreeParser::ExprTreeParser(std::shared_ptr<const ExprVisitor> vistor) : visitor_store(vistor) {}
|
||
|
||
typedef std::shared_ptr<const SyntaxElement> E;
|
||
typedef QList<std::shared_ptr<const SyntaxElement>> Es;
|
||
typedef std::shared_ptr<const ast_basic::ExprNode> Expr;
|
||
|
||
QList<std::shared_ptr<const SyntaxElement>> ExprTreeParser::parse(const QString& name,
|
||
const QList<std::shared_ptr<const ast_basic::ExprNode>>& forest) const {
|
||
std::function<Es(Expr, E)> visit_loop = [&](Expr n, E p) -> Es {
|
||
QList<std::shared_ptr<const SyntaxElement>> temp_list;
|
||
auto node = this->visitor_store->visit(n, p);
|
||
if (node)
|
||
temp_list.append(node);
|
||
|
||
for (auto& it : n->exprNodes()) {
|
||
temp_list.append(visit_loop(it, node));
|
||
}
|
||
|
||
return temp_list;
|
||
};
|
||
|
||
QList<std::shared_ptr<const SyntaxElement>> temp_list;
|
||
auto root = std::make_shared<GlobalElement>(name);
|
||
temp_list << root;
|
||
|
||
for (auto& tree : forest) {
|
||
temp_list.append(visit_loop(tree, root));
|
||
}
|
||
|
||
return temp_list;
|
||
}
|
||
|
||
std::shared_ptr<const ElementAccess> ExprTreeParser::tidy(const QList<std::shared_ptr<const SyntaxElement>>& nodes) const {
|
||
auto temp = nodes.first();
|
||
while (temp->parent()) {
|
||
temp = temp->parent();
|
||
}
|
||
|
||
auto core_cache = std::static_pointer_cast<GlobalElement>(std::const_pointer_cast<SyntaxElement>(temp));
|
||
core_cache->clearCache();
|
||
for (auto& it : nodes) {
|
||
if (!it->isAnonymous()) {
|
||
core_cache->appendToCache(it);
|
||
}
|
||
}
|
||
|
||
auto root = std::make_shared<ElementAccess>(temp);
|
||
for (auto& node : nodes)
|
||
tidy_branch(root, node);
|
||
|
||
return root;
|
||
}
|
||
|
||
void ExprTreeParser::tidy_branch(std::shared_ptr<ElementAccess> root, std::shared_ptr<const SyntaxElement> node) const {
|
||
QList<std::shared_ptr<const SyntaxElement>> link;
|
||
while (node) {
|
||
link.prepend(node);
|
||
node = node->parent();
|
||
}
|
||
|
||
std::function<void(std::shared_ptr<ElementAccess> pnode, QList<std::shared_ptr<const SyntaxElement>>)> merge =
|
||
[&](std::shared_ptr<ElementAccess> pnode, QList<std::shared_ptr<const SyntaxElement>> remains) {
|
||
if (!remains.size())
|
||
return;
|
||
|
||
auto current = remains.first();
|
||
for (auto& c_a : pnode->children()) {
|
||
if (c_a->element() == current) {
|
||
merge(std::const_pointer_cast<ElementAccess>(c_a), remains.mid(1));
|
||
return;
|
||
}
|
||
}
|
||
|
||
auto new_branch = std::make_shared<ElementAccess>(current);
|
||
pnode->appendChild(new_branch);
|
||
if (remains.size() > 1)
|
||
merge(new_branch, remains.mid(1));
|
||
};
|
||
|
||
merge(root, link.mid(1));
|
||
}
|
||
|
||
GlobalElement::GlobalElement(const QString& name) :names_store(name) {}
|
||
|
||
void GlobalElement::clearCache() { node_cache.clear(); }
|
||
|
||
void GlobalElement::appendToCache(std::shared_ptr<const SyntaxElement> named_node) {
|
||
auto mixed_key = QString(u8"%1<%2>").arg(named_node->signature()).arg(named_node->typeMark());
|
||
if (node_cache.contains(mixed_key))
|
||
throw new lib_syntax::SyntaxException(
|
||
QString(u8"Parse[0x0004]ϵͳ<CFB5>а<EFBFBD><D0B0><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㣺%1<type<70><65>%2>").arg(named_node->signature()).arg(named_node->typeMark()));
|
||
node_cache[mixed_key] = named_node;
|
||
}
|
||
|
||
std::shared_ptr<const SyntaxElement> GlobalElement::getNamedNodeBy(int type, const QString& signature) const {
|
||
auto mixed_key = QString(u8"%1<%2>").arg(signature).arg(type);
|
||
if (!node_cache.contains(mixed_key))
|
||
throw new lib_syntax::SyntaxException(QString(u8"Parse[0x0005]ϵͳ<CFB5>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ǩ<EFBFBD><C7A9><EFBFBD>Ľڵ㣺%1<type<70><65>%2>").arg(signature).arg(type));
|
||
return node_cache[mixed_key];
|
||
}
|
||
|
||
int GlobalElement::typeMark() const { return 0; }
|
||
|
||
bool ast_gen::GlobalElement::isAnonymous() const { return true; }
|
||
|
||
QString GlobalElement::signature() const { return u8"::global"; }
|
||
|
||
QString GlobalElement::path() const { return u8""; }
|
||
|
||
std::shared_ptr<const SyntaxElement> GlobalElement::parent() const { return nullptr; }
|
||
|
||
QList<std::shared_ptr<const TokenAccess>> GlobalElement::selfTokens() const { return QList<std::shared_ptr<const TokenAccess>>(); }
|
||
|
||
ElementAccess::ElementAccess(std::shared_ptr<const SyntaxElement> point) { peers = point; }
|
||
|
||
std::shared_ptr<const SyntaxElement> ElementAccess::element() const { return peers; }
|
||
|
||
QList<std::shared_ptr<const ElementAccess>> ElementAccess::children() const { return children_store; }
|
||
|
||
void ElementAccess::appendChild(std::shared_ptr<const ElementAccess> inst) { children_store.append(inst); }
|
||
|
||
QList<std::shared_ptr<const TokenAccess>> ElementAccess::tokens() const {
|
||
QList<std::shared_ptr<const TokenAccess>> tokens_retv;
|
||
tokens_retv.append(element()->selfTokens());
|
||
for (auto& it : children()) {
|
||
tokens_retv.append(it->tokens());
|
||
}
|
||
|
||
return tokens_retv;
|
||
}
|
||
|
||
TokenAccess::TokenAccess(std::shared_ptr<const SyntaxElement> elm_inst, std::shared_ptr<const lib_token::Token> token_inst)
|
||
: element_bind(elm_inst), token_store(token_inst) {}
|
||
|
||
std::shared_ptr<const SyntaxElement> TokenAccess::bind() const { return element_bind; }
|
||
|
||
std::shared_ptr<const lib_token::Token> TokenAccess::token() const { return token_store; }
|
||
|