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; }
|
|||
|
|