From fabc309a0a0a6f210a8a7ed8f0d1f8498971f409 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sun, 8 Sep 2019 00:28:49 +0800 Subject: completing moonscript compiler with c++. --- MoonParser/ast.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 13 deletions(-) (limited to 'MoonParser/ast.cpp') diff --git a/MoonParser/ast.cpp b/MoonParser/ast.cpp index 739e02c..6217f3e 100644 --- a/MoonParser/ast.cpp +++ b/MoonParser/ast.cpp @@ -10,13 +10,19 @@ static ast_container *_current = 0; int ast_type_id = 0; +traversal ast_node::traverse(const std::function& func) { + return func(this); +} -bool ast_node::visit(const std::function& begin, - const std::function& end) -{ - return begin(this) || end(this); +ast_node* ast_node::getByPath(std::initializer_list) { + return nullptr; } +void ast_node::eachChild(const std::function&) { } + +bool ast_node::visitChild(const std::function&) { + return false; +} /** sets the container under construction to be this. */ @@ -48,28 +54,123 @@ void ast_container::construct(ast_stack &st) { } } -bool ast_container::visit(const std::function& begin, - const std::function& end) -{ - bool result = begin(this); - if (result) return true; +traversal ast_container::traverse(const std::function& func) { + traversal action = func(this); + switch (action) { + case traversal::Stop: return traversal::Stop; + case traversal::Return: return traversal::Continue; + default: break; + } const auto& members = this->members(); for (auto member : members) { if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { - if (ptr->get() && ptr->get()->visit(begin, end)) { + if (ptr->get() && ptr->get()->traverse(func) == traversal::Stop) { + return traversal::Stop; + } + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj->traverse(func) == traversal::Stop) { + return traversal::Stop; + } + } + } + } + return traversal::Continue; +} + +ast_node* ast_container::getByPath(std::initializer_list paths) { + ast_node* current = this; + auto it = paths.begin(); + while (it != paths.end()) { + ast_node* findNode = nullptr; + current->visitChild([&](ast_node* node) { + if (node->getId() == *it) { + findNode = node; return true; } + return false; + }); + if (findNode) { + current = findNode; + } else { + current = nullptr; + break; + } + ++it; + } + return current; +} + +void ast_container::eachChild(const std::function& func) { + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) { + func(ptr->get()); + } + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) { + func(obj); + } + } + } + } +} + +bool ast_container::visitChild(const std::function& func) { + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) { + if (func(ptr->get())) return true; + } } else if (_ast_list* list = ast_cast<_ast_list>(member)) { for (auto obj : list->objects()) { - if (obj->visit(begin, end)) { - return true; + if (obj) { + if (func(obj)) return true; } } } } - return end(this); + return false; } +ast_node* ast_container::getChild(int index) const { + int i = 0; + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) { + if (i == index) return ptr->get(); + i++; + } + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) { + if (i == index) return obj; + i++; + } + } + } + } + return nullptr; +} + +int ast_container::getChildCount() const { + int count = 0; + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) count++; + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) count++; + } + } + } + return count; +} //register the AST member to the current container. void ast_member::_init() { -- cgit v1.2.3-55-g6feb