// 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.

#include "common/analysis/syntax_tree_search.h"

#include <functional>
#include <vector>

#include "common/analysis/matcher/bound_symbol_manager.h"
#include "common/analysis/matcher/matcher.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/tree_context_visitor.h"

namespace verible {
namespace {

using matcher::BoundSymbolManager;

// SyntaxTreeSearcher collects node that match specified criteria
// from a syntax tree.  Prefer to use the SearchSyntaxTree() function
// over this class.
class SyntaxTreeSearcher : public TreeContextVisitor {
 public:
  SyntaxTreeSearcher(
      const matcher::Matcher &m,
      const std::function<bool(const SyntaxTreeContext &)> &context_predicate)
      : matcher_(m), context_predicate_(context_predicate) {}

  void Search(const Symbol &root) { root.Accept(this); }

  const std::vector<TreeSearchMatch> &Matches() const { return matches_; }

 private:
  void CheckSymbol(const Symbol &);
  void Visit(const SyntaxTreeLeaf &leaf) final;
  void Visit(const SyntaxTreeNode &node) final;

  // Main matcher that finds a particular type of tree node.
  const verible::matcher::Matcher matcher_;

  // Predicate that further qualifies the matches of interest.
  const std::function<bool(const SyntaxTreeContext &)> context_predicate_;

  // Accumulated set of matches.
  std::vector<TreeSearchMatch> matches_;
};

// Checks if leaf matches critera.
void SyntaxTreeSearcher::CheckSymbol(const Symbol &symbol) {
  BoundSymbolManager manager;
  if (matcher_.Matches(symbol, &manager)) {
    if (context_predicate_(Context())) {
      matches_.push_back(TreeSearchMatch{&symbol, Context()});
    }
  }
}
//
// Checks if leaf matches critera.
void SyntaxTreeSearcher::Visit(const SyntaxTreeLeaf &leaf) {
  CheckSymbol(leaf);
}

// Checks if node matches criteria.
// Then recursively search subtree.
void SyntaxTreeSearcher::Visit(const SyntaxTreeNode &node) {
  CheckSymbol(node);
  TreeContextVisitor::Visit(node);
}

}  // namespace

std::vector<TreeSearchMatch> SearchSyntaxTree(
    const Symbol &root, const verible::matcher::Matcher &matcher,
    const std::function<bool(const SyntaxTreeContext &)> &context_predicate) {
  SyntaxTreeSearcher searcher(matcher, context_predicate);
  searcher.Search(root);
  return searcher.Matches();
}

std::vector<TreeSearchMatch> SearchSyntaxTree(
    const Symbol &root, const verible::matcher::Matcher &matcher) {
  return SearchSyntaxTree(root, matcher,
                          [](const SyntaxTreeContext &) { return true; });
}

}  // namespace verible
