#include "ccl/rslang/SyntaxTree.h" #include "ASTNormalizer.h" #include #include namespace ccl::rslang { SyntaxTree::Node::Node(const Node& node2) { *this = node2; } SyntaxTree::Node& SyntaxTree::Node::operator=(const Node& node2) { if (this != &node2) { token = node2.token; const auto oldCount = size(children); for (const auto& child : node2.children) { children.emplace_back(std::make_unique(*child))->parent = this; } if (oldCount > 0) { children.erase(begin(children), begin(children) + static_cast(oldCount)); children.shrink_to_fit(); } } return *this; } Index SyntaxTree::Node::ChildrenCount() const noexcept { return static_cast(ssize(children)); } SyntaxTree::Node& SyntaxTree::Node::operator()(const Index index) { return At(index); } SyntaxTree::Node& SyntaxTree::Node::At(const Index index) { assert(index < ChildrenCount() && index >= 0); return *children.at(static_cast(index)); } const SyntaxTree::Node& SyntaxTree::Node::operator()(const Index index) const { return At(index); } const SyntaxTree::Node& SyntaxTree::Node::At(const Index index) const { assert(index < ChildrenCount() && index >= 0); return *children.at(static_cast(index)); } void SyntaxTree::Node::AdoptChild(RawNode son) { assert(son != nullptr); children.emplace_back(std::move(son))->parent = this; } void SyntaxTree::Node::AddChildCopy(const Node& son) { children.emplace_back(std::make_unique(son))->parent = this; } void SyntaxTree::Node::AddNewChild(const TokenID tid) { children.emplace_back(std::make_unique(Token{ tid, token.pos }))->parent = this; } void SyntaxTree::Node::RemoveAll() noexcept { children.clear(); } void SyntaxTree::Node::ExtendChild(const Index index, const TokenID tid) { assert(index < ChildrenCount() && index >= 0); auto newNode = std::make_unique(Token{ tid, At(index).token.pos }); newNode->AdoptChild(std::move(children.at(static_cast(index)))); newNode->parent = this; children.at(static_cast(index)) = std::move(newNode); } void SyntaxTree::Node::RemoveChild(const Index index) noexcept { assert(index < ChildrenCount() && index >= 0); children.erase(children.begin() + static_cast(index)); } SyntaxTree::RawNode SyntaxTree::Node::ExtractChild(const Index index) { assert(index < ChildrenCount() && index >= 0); RawNode result = std::move(children.at(static_cast(index))); children.erase(begin(children) + static_cast(index)); return result; } bool SyntaxTree::Node::operator==(const Node& node2) const { if (size(children) != size(node2.children) || token.id != node2.token.id || token.data != node2.token.data) { return false; } else { for (auto i = 0U; i < size(children); ++i) { if (*children.at(i) != *node2.children.at(i)) { return false; } } return true; } } bool SyntaxTree::Cursor::MoveToParent() noexcept { if (node->parent != nullptr) { node = node->parent; return true; } else { return false; } } void SyntaxTree::Cursor::MoveToChild(Index son) { assert(son < ChildrenCount() && son >= 0); node = node->children.at(static_cast(son)).get(); } SyntaxTree::Cursor SyntaxTree::Cursor::Child(Index son) const { auto result = *this; result.MoveToChild(son); return result; } bool SyntaxTree::Cursor::MoveToNextSibling() { if (node->parent == nullptr) { return false; } for (auto child = next(rbegin(node->parent->children)); child != rend(node->parent->children); ++child) { if (child->get() == node) { --child; node = child->get(); return true; } } return false; } bool SyntaxTree::Cursor::MoveToPrevSibling() { if (node->parent == nullptr) { return false; } for (auto child = next(begin(node->parent->children)); child != end(node->parent->children); ++child) { if (child->get() == node) { --child; node = child->get(); return true; } } return false; } const Token* SyntaxTree::Cursor::operator->() const noexcept { return &node->token; } const Token& SyntaxTree::Cursor::operator*() const noexcept { return node->token; } bool SyntaxTree::Cursor::IsRoot() const noexcept { return node->parent == nullptr; } Index SyntaxTree::Cursor::ChildrenCount() const noexcept { return node->ChildrenCount(); } const Token& SyntaxTree::Cursor::operator()(Index index) const { return node->children.at(static_cast(index))->token; } const Token& SyntaxTree::Cursor::Parent() const noexcept { return node->parent->token; } SyntaxTree::SyntaxTree(const SyntaxTree& tree) { *this = tree; } SyntaxTree& SyntaxTree::operator=(const SyntaxTree& tree) { if (&tree != this) { root = std::make_unique(*tree.root); } return *this; } SyntaxTree::Cursor SyntaxTree::Root() const noexcept { return Cursor{ *root }; } bool SyntaxTree::operator==(const SyntaxTree& t2) const { return *root == *t2.root; } void SyntaxTree::Normalize(SyntaxTreeContext termFuncs) { if (root != nullptr) { Normalizer{ termFuncs }.Normalize(*root); } } std::string AST2String::Apply(const SyntaxTree& ast) { static AST2String generator{}; generator.text.clear(); ast.Root().DispatchVisit(generator); return generator.text; } bool AST2String::VisitDefault(Cursor iter) { text += '['; text += iter->ToString(); for (Index child = 0; child < iter.ChildrenCount(); ++child) { VisitChild(iter, child); } text += ']'; return true; } std::optional FindMinimalNode(SyntaxTree::Cursor root, StrRange range) { if (!root->pos.Contains(range)) { return std::nullopt; } else if (root.ChildrenCount() == 0) { return root; } else { root.MoveToChild(0); do { if (const auto result = FindMinimalNode(root, range); result.has_value()) { return result; } } while (root.MoveToNextSibling()); root.MoveToParent(); return root; } } } // namespace ccl::rslang