#include "ast_gen.h" using namespace ast_gen; ExprTreeParser::ExprTreeParser(std::shared_ptr vistor) : visitor_store(vistor) {} typedef std::shared_ptr E; typedef QList> Es; typedef std::shared_ptr Expr; QList> ExprTreeParser::parse(const QString& name, const QList>& forest) const { std::function visit_loop = [&](Expr n, E p) -> Es { QList> 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> temp_list; auto root = std::make_shared(name); temp_list << root; for (auto& tree : forest) { temp_list.append(visit_loop(tree, root)); } return temp_list; } std::shared_ptr ExprTreeParser::tidy(const QList>& nodes) const { auto temp = nodes.first(); while (temp->parent()) { temp = temp->parent(); } auto core_cache = std::static_pointer_cast(std::const_pointer_cast(temp)); core_cache->clearCache(); for (auto& it : nodes) { if (!it->isAnonymous()) { core_cache->appendToCache(it); } } auto root = std::make_shared(temp); for (auto& node : nodes) tidy_branch(root, node); return root; } void ExprTreeParser::tidy_branch(std::shared_ptr root, std::shared_ptr node) const { QList> link; while (node) { link.prepend(node); node = node->parent(); } std::function pnode, QList>)> merge = [&](std::shared_ptr pnode, QList> 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(c_a), remains.mid(1)); return; } } auto new_branch = std::make_shared(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 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]系统中包含同类型重名命名节点:%1").arg(named_node->signature()).arg(named_node->typeMark())); node_cache[mixed_key] = named_node; } std::shared_ptr 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]系统中不包含指定签名的节点:%1").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 GlobalElement::parent() const { return nullptr; } QList> GlobalElement::selfTokens() const { return QList>(); } ElementAccess::ElementAccess(std::shared_ptr point) { peers = point; } std::shared_ptr ElementAccess::element() const { return peers; } QList> ElementAccess::children() const { return children_store; } void ElementAccess::appendChild(std::shared_ptr inst) { children_store.append(inst); } QList> ElementAccess::tokens() const { QList> tokens_retv; tokens_retv.append(element()->selfTokens()); for (auto& it : children()) { tokens_retv.append(it->tokens()); } return tokens_retv; } TokenAccess::TokenAccess(std::shared_ptr elm_inst, std::shared_ptr token_inst) : element_bind(elm_inst), token_store(token_inst) {} std::shared_ptr TokenAccess::bind() const { return element_bind; } std::shared_ptr TokenAccess::token() const { return token_store; }