blob: 916e3f0a3ee73e89f6fe4f6388d6ef9b3a395fa8 [file] [log] [blame]
// 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_