// Copyright 2022 Google LLC
//
// 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 FUZZTEST_GRAMMAR_CODEGEN_BACKEND_H_
#define FUZZTEST_GRAMMAR_CODEGEN_BACKEND_H_

#include <string>
#include <string_view>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_set.h"
#include "./grammar_codegen/grammar_info.h"

namespace fuzztest::internal::grammar {

class CodeGenerator {
 public:
  // The constructor accepts the information collected by the parser.
  CodeGenerator(Grammar grammar) : grammar_(std::move(grammar)) {}
  // Return the generated code as a string. The generated code works as a header
  // and contains the definition of the ast nodes for a language.
  std::string Generate();

 private:
  // Simplify the grammar so that the elements of Vector/Tuple/Variant are
  // either terminals or non-terminals.
  // For example, A: (C D)* will be converted to: A: N*, N: C D. So that we can
  // say A is a vector of N, and N is a tuple of C, D.
  void Preprocess(Grammar& grammar);

  std::string BuildClassDefinitionForSymbol(GrammarRule& rule);
  std::string BuilldClassDefinitionForCharSet(std::string_view class_name);
  std::string BuildClassDefinitionForLiteral(std::string_view class_name);
  std::string BuildBaseTypeForGrammarRule(const GrammarRule& rule);

  // Caculate the fallback indexes for all the symbols (including
  // sub-productions). During generation, if every grammar rule chooses the
  // fallback index during generation, generation will guarantee to end.
  void CalculateFallBackIndex(std::vector<GrammarRule>& rules);

  bool IsSymbolSafe(std::string_view symbol);
  void MarkSymbolAsSafe(std::string_view symbol);

  bool HasSafeRange(const Block& block);

  bool TryMarkProductionRuleVecAsSafe(ProductionWithFallbackIndex& productions);
  bool TryMarkBlockAsSafe(Block& block);
  bool TryMarkProductionRuleAsSafe(ProductionRule& prod_rule);
  bool TryMarkGrammarRuleAsSafe(GrammarRule& rule);

  // Get the name of the generated class for the block.
  std::string GetClassName(const Block& block);
  std::string GetClassNameForSymbol(const std::string id);
  std::string GetClassNameForLiteral(std::string_view s);
  std::string GetClassNameForCharSet(std::string_view s);

  Grammar grammar_;
  absl::flat_hash_set<std::string> safe_rules_;

  // Use ordered map so that the generated code has a stable order.
  absl::btree_map<std::string, std::string> literal_node_ids_;
  absl::btree_map<std::string, std::string> charset_node_ids_;
};
}  // namespace fuzztest::internal::grammar

#endif  // FUZZTEST_GRAMMAR_CODEGEN_BACKEND_H_
