// 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/matcher/descent_path.h"

#include <iterator>
#include <memory>
#include <vector>

#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"

namespace verible {
namespace matcher {

// AggregateAllDescendantsFromPath is a local helper for
// GetAllDescendantsFromPath. It minimizes copying by using iterators
// and pushing all discovered symbols onto a single vector.
//
// Adds all descendants of symbol that are precisely along path to target
// children must have matching SymbolTag to the last element of path.
//
// Position should point to the start position of your path and
// end should point to the end position.
//
// Discovered children are pushed back onto target
static void AggregateAllDescendantsFromPath(
    const Symbol &symbol, const DescentPath::const_iterator &position,
    const DescentPath::const_iterator &end,
    std::vector<const Symbol *> *target);

std::vector<const Symbol *> GetAllDescendantsFromPath(const Symbol &symbol,
                                                      const DescentPath &path) {
  std::vector<const Symbol *> target;

  if (symbol.Kind() == SymbolKind::kNode) {
    const auto *node = down_cast<const SyntaxTreeNode *>(&symbol);
    for (const auto &child : node->children()) {
      if (child) {
        AggregateAllDescendantsFromPath(*child, path.begin(), path.end(),
                                        &target);
      }
    }
  }

  return target;
}

static void AggregateAllDescendantsFromPath(
    const Symbol &symbol, const DescentPath::const_iterator &position,
    const DescentPath::const_iterator &end,
    std::vector<const Symbol *> *target) {
  // If we are somehow operating on empty vector, stop recursion.
  if (position == end) {
    return;
  }

  // If we're at the last SymbolTag, stop recursion and check if we need to add
  // symbol to target.
  if (position + 1 == end) {
    if (symbol.Tag() == (*position)) {
      target->push_back(&symbol);
    }
    return;
  }

  // In order to recursively check descendants, symbol needs to be a node
  if (symbol.Kind() != SymbolKind::kNode) {
    return;
  }

  const auto *node = down_cast<const SyntaxTreeNode *>(&symbol);

  // If the cast fails or the node does not have the required tag or kind,
  // then stop recursion
  const auto tag_kind = node->Tag();
  if (tag_kind != *position) {
    return;
  }

  // Recurse on children
  for (const auto &child : node->children()) {
    if (child) {
      AggregateAllDescendantsFromPath(*child, position + 1, end, target);
    }
  }
}

}  // namespace matcher
}  // namespace verible
