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