// Copyright 2017-2020 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.

#ifndef VERIBLE_COMMON_TEXT_SYNTAX_TREE_CONTEXT_H_
#define VERIBLE_COMMON_TEXT_SYNTAX_TREE_CONTEXT_H_

#include <algorithm>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <vector>

#include "common/text/concrete_syntax_tree.h"
#include "common/util/auto_pop_stack.h"
#include "common/util/iterator_adaptors.h"
#include "common/util/logging.h"

namespace verible {

// Container with a stack of SyntaxTreeNodes and methods to verify the context
// of a SyntaxTreeNode during traversal of a ConcreteSyntaxTree.
// Note: Public methods are named to follow STL convention for std::stack.
// TODO(fangism): implement a general ForwardMatcher and ReverseMatcher
// interface that can express AND/OR/NOT.
// Despite of implementation based on pointers. This class requires
// that managed elements are non-nullptrs.
class SyntaxTreeContext : public AutoPopStack<const SyntaxTreeNode*> {
 public:
  typedef AutoPopStack<const SyntaxTreeNode*> base_type;

  // member class to handle push and pop of stack safely
  using AutoPop = base_type::AutoPop;

 protected:
  // restrict access to AutoPopStack<>::top method only to this class
  using base_type::top;

 public:
  // returns the top SyntaxTreeNode of the stack
  const SyntaxTreeNode& top() const {
    return *ABSL_DIE_IF_NULL(base_type::top());
  }

  // IsInside returns true if there is a node of the specified
  // tag on the TreeContext stack.  Search traverses from the top of the
  // stack starting with offset and returns on the first match found.
  // Type parameter E can be a language-specific enum or plain integer type.
  template <typename E>
  bool IsInsideStartingFrom(E tag_enum, size_t reverse_offset) const {
    if (size() <= reverse_offset) return false;
    return std::any_of(
        rbegin() + reverse_offset, rend(),
        [=](const SyntaxTreeNode* node) { return node->MatchesTag(tag_enum); });
  }

  // IsInside returns true if there is a node of the specified
  // tag on the TreeContext stack.  Search occurs from the top of the
  // stack and returns on the first match found.
  // Type parameter E can be a language-specific enum or plain integer type.
  template <typename E>
  bool IsInside(E tag_enum) const {
    return IsInsideStartingFrom(tag_enum, 0);
  }

  // Returns true if current context is directly inside one of the includes
  // node types before any of the excludes node types.  Search starts
  // from the top of the stack.
  template <typename E>
  bool IsInsideFirst(std::initializer_list<E> includes,
                     std::initializer_list<E> excludes) const {
    for (const auto& type : reversed_view(*this)) {
      if (type->MatchesTagAnyOf(includes)) return true;
      if (type->MatchesTagAnyOf(excludes)) return false;
    }
    return false;
  }

  // Returns true if stack is not empty and top of stack matches tag_enum.
  template <typename E>
  bool DirectParentIs(E tag_enum) const {
    if (empty()) {
      return false;
    }
    return E(top().Tag().tag) == tag_enum;
  }

  // Returns true if stack is not empty and top of stack matches
  // one of the tag_enums.
  template <typename E>
  bool DirectParentIsOneOf(std::initializer_list<E> tag_enums) const {
    if (empty()) {
      return false;
    }
    return std::find(tag_enums.begin(), tag_enums.end(), E(top().Tag().tag)) !=
           tag_enums.end();
  }

  // Returns true if the immediate parents are the given sequence (top-down).
  // Sequence should be specified as: direct-parent, direct-grandparent, ...
  // In the degenerate empty-list case, this will return true.
  template <typename E>
  bool DirectParentsAre(std::initializer_list<E> tag_enums) const {
    if (tag_enums.size() > size()) return false;
    // top of stack is back of vector (direct parent)
    return std::equal(tag_enums.begin(), tag_enums.end(), rbegin(),
                      [](E tag, const SyntaxTreeNode* node) {
                        return E(node->Tag().tag) == tag;
                      });
  }

  // Returns the closest ancestor (starting from top of context stack) that
  // matches the given 'predicate' function, or nullptr if no match is found.
  const SyntaxTreeNode* NearestParentMatching(
      const std::function<bool(const SyntaxTreeNode&)>& predicate) const {
    const auto ancestors(reversed_view(*this));
    const auto found = std::find_if(ancestors.begin(), ancestors.end(),
                                    [&predicate](const SyntaxTreeNode* parent) {
                                      return predicate(*parent);
                                    });
    return found != ancestors.end() ? *found : nullptr;
  }

  // Returns the closest ancestor (starting from top of context stack) with the
  // specified node tag (enum).
  template <typename E>
  const SyntaxTreeNode* NearestParentWithTag(E tag) const {
    return NearestParentMatching(
        [tag](const SyntaxTreeNode& node) { return E(node.Tag().tag) == tag; });
  }
};

}  // namespace verible

#endif  // VERIBLE_COMMON_TEXT_SYNTAX_TREE_CONTEXT_H_
