| // Copyright 2017-2021 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // This header provides iterators to traverse VectorTrees in various ways. |
| |
| #ifndef VERIBLE_COMMON_UTIL_VECTOR_TREE_ITERATORS_H_ |
| #define VERIBLE_COMMON_UTIL_VECTOR_TREE_ITERATORS_H_ |
| |
| #include <cstddef> |
| #include <iterator> |
| |
| #include "common/util/iterator_range.h" |
| #include "common/util/logging.h" |
| #include "common/util/tree_operations.h" |
| |
| namespace verible { |
| |
| namespace internal { |
| |
| // Class implementing common VectorTree*Iterator members using CRTP polymorphic |
| // chaining. Derived class must implement following methods: |
| // - `static VectorTreeType* GetNextNode(VectorTreeType* node)` - returns |
| // pointer |
| // to a next node |
| template <typename ImplType, typename VectorTreeType> |
| class VectorTreeIteratorBase { |
| public: |
| using iterator_category = std::forward_iterator_tag; |
| using difference_type = std::ptrdiff_t; |
| using value_type = VectorTreeType; |
| using pointer = VectorTreeType *; |
| using reference = VectorTreeType &; |
| |
| VectorTreeIteratorBase() : node_(nullptr) {} |
| explicit VectorTreeIteratorBase(pointer node) : node_(node) {} |
| |
| reference operator*() const { |
| CHECK_NOTNULL(node_); |
| return *node_; |
| } |
| pointer operator->() const { |
| CHECK_NOTNULL(node_); |
| return node_; |
| } |
| ImplType &operator++() { |
| node_ = ImplType::GetNextNode(node_); |
| return static_cast<ImplType &>(*this); |
| } |
| ImplType operator++(int) { |
| ImplType tmp = static_cast<ImplType &>(*this); |
| node_ = ImplType::GetNextNode(node_); |
| return tmp; |
| } |
| friend ImplType operator+(ImplType lhs, std::size_t rhs) { |
| while (rhs--) ++lhs; |
| return lhs; |
| } |
| friend bool operator==(const ImplType &a, const ImplType &b) { |
| return a.node_ == b.node_; |
| }; |
| friend bool operator!=(const ImplType &a, const ImplType &b) { |
| return a.node_ != b.node_; |
| }; |
| |
| protected: |
| pointer node_; |
| }; |
| |
| } // namespace internal |
| |
| template <typename VectorTreeType> |
| class VectorTreeLeavesIterator |
| : public internal::VectorTreeIteratorBase< |
| VectorTreeLeavesIterator<VectorTreeType>, VectorTreeType> { |
| using this_type = VectorTreeLeavesIterator<VectorTreeType>; |
| using base_type = internal::VectorTreeIteratorBase<this_type, VectorTreeType>; |
| |
| public: |
| VectorTreeLeavesIterator() : base_type() {} |
| explicit VectorTreeLeavesIterator(VectorTreeType *node) |
| : base_type(node ? &LeftmostDescendant(*node) : nullptr) {} |
| |
| static VectorTreeType *GetNextNode(VectorTreeType *node) { |
| if (!node) return nullptr; |
| return NextLeaf(*node); |
| } |
| }; |
| |
| template <typename VectorTreeType> |
| VectorTreeLeavesIterator(VectorTreeType *) |
| -> VectorTreeLeavesIterator<VectorTreeType>; |
| |
| // Returns VectorTreeLeavesIterator range that spans all leaves of a tree. |
| // Note that when the node passed as a tree is a leaf, the returned range spans |
| // this node. |
| template <typename VectorTreeType> |
| iterator_range<VectorTreeLeavesIterator<VectorTreeType>> |
| VectorTreeLeavesTraversal(VectorTreeType &tree) { |
| VectorTreeLeavesIterator<VectorTreeType> begin(&LeftmostDescendant(tree)); |
| VectorTreeLeavesIterator<VectorTreeType> end(&RightmostDescendant(tree)); |
| ++end; |
| return {begin, end}; |
| } |
| |
| template <typename VectorTreeType> |
| class VectorTreePreOrderIterator |
| : public internal::VectorTreeIteratorBase< |
| VectorTreePreOrderIterator<VectorTreeType>, VectorTreeType> { |
| using this_type = VectorTreePreOrderIterator<VectorTreeType>; |
| using base_type = internal::VectorTreeIteratorBase<this_type, VectorTreeType>; |
| |
| public: |
| VectorTreePreOrderIterator() : base_type() {} |
| explicit VectorTreePreOrderIterator(VectorTreeType *node) : base_type(node) {} |
| |
| static VectorTreeType *GetNextNode(VectorTreeType *node) { |
| if (!node) return nullptr; |
| if (!node->Children().empty()) return &node->Children().front(); |
| while (node && verible::IsLastChild(*node)) { |
| node = node->Parent(); |
| } |
| if (node) node = NextSibling(*node); |
| return node; |
| } |
| |
| this_type begin() const { return *this; } |
| this_type end() const { |
| if (!this->node_) return this_type(nullptr); |
| return this_type(GetNextNode(&RightmostDescendant(*this->node_))); |
| } |
| }; |
| |
| template <typename VectorTreeType> |
| VectorTreePreOrderIterator(VectorTreeType *) |
| -> VectorTreePreOrderIterator<VectorTreeType>; |
| |
| // Returns VectorTreePreOrderIterator range that spans all nodes of a tree |
| // (including the tree's root). |
| template <typename VectorTreeType> |
| iterator_range<VectorTreePreOrderIterator<VectorTreeType>> |
| VectorTreePreOrderTraversal(VectorTreeType &tree) { |
| VectorTreePreOrderIterator<VectorTreeType> it(&tree); |
| return {it.begin(), it.end()}; |
| } |
| |
| template <typename VectorTreeType> |
| class VectorTreePostOrderIterator |
| : public internal::VectorTreeIteratorBase< |
| VectorTreePostOrderIterator<VectorTreeType>, VectorTreeType> { |
| using this_type = VectorTreePostOrderIterator<VectorTreeType>; |
| using base_type = internal::VectorTreeIteratorBase<this_type, VectorTreeType>; |
| |
| public: |
| VectorTreePostOrderIterator() : base_type() {} |
| explicit VectorTreePostOrderIterator(VectorTreeType *node) |
| : base_type(node) {} |
| |
| static VectorTreeType *GetNextNode(VectorTreeType *node) { |
| if (!node) return nullptr; |
| if (verible::IsLastChild(*node)) return node->Parent(); |
| node = NextSibling(*node); |
| if (!node->Children().empty()) node = &LeftmostDescendant(*node); |
| return node; |
| } |
| |
| this_type begin() const { |
| if (!this->node_) return this_type(nullptr); |
| return this_type(&LeftmostDescendant(*this->node_)); |
| } |
| this_type end() const { return this_type(GetNextNode(this->node_)); } |
| }; |
| |
| template <typename VectorTreeType> |
| VectorTreePostOrderIterator(VectorTreeType *) |
| -> VectorTreePostOrderIterator<VectorTreeType>; |
| |
| // Returns VectorTreePostOrderIterator range that spans all nodes of a tree |
| // (including the tree's root). |
| template <typename VectorTreeType> |
| iterator_range<VectorTreePostOrderIterator<VectorTreeType>> |
| VectorTreePostOrderTraversal(VectorTreeType &tree) { |
| VectorTreePostOrderIterator<VectorTreeType> it(&tree); |
| return {it.begin(), it.end()}; |
| } |
| |
| } // namespace verible |
| |
| #endif // VERIBLE_COMMON_UTIL_VECTOR_TREE_ITERATORS_H_ |