// 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_GRAMMAR_INFO_H_ #define FUZZTEST_GRAMMAR_CODEGEN_GRAMMAR_INFO_H_ #include #include #include #include namespace fuzztest::internal::grammar { // A symbol can be quantified by a range (?, +, *). `?` means the symbol is // optional, `+` means at least one, and `*` means arbitrary number. enum class Range { kNoRange, kOptional, // [0, 1] kNonEmpty, // [1, +infinity] kUnlimited, // [0, +infinity] }; // A terminal is either a string literal or a charset (regex). A lexer symbol // (Token) doesn't have to be a terminal. For example, we treat the lexer symbol // `LoopStatement: "break" | "continue"` as non-terminal because it expands to // other symbols. enum class TerminalType { kStringLiteral, kCharSet, }; struct Terminal { TerminalType type; std::string content; }; // A non-terminal is a symbol in the grammar file. struct NonTerminal { std::string name; }; struct ProductionRule; // A list of production rules. It can be the expansion rules for a symbol or a // block in one production rule. The fallback index is for finite string // generation: if we choose the production of fallback index to expand every // symbol, then the result string must be finite. struct ProductionWithFallbackIndex { std::optional fallback_index; std::vector production_rules; }; // A block is the basic unit that constructs a production rule. It can be a // terminal, non-terminal or production rules. For example, for the grammar rule // `A : "a" | B | (C | D)*`, each production rule of `A` consists of one block. // "a" is a terminal, `B` is a non-terminal, `(C | D)*` is a set of // sub-production rules. enum BlockType { kTerminal = 0, kNonTerminal = 1, kSubProductions = 2, }; struct Block { Range range = Range::kNoRange; std::variant element; }; // A production is a tuple of blocks that a symbol can expand to. struct ProductionRule { std::vector blocks; }; // Decribes the rule of productions for a symbol. struct GrammarRule { std::string symbol_name; ProductionWithFallbackIndex productions; }; // All the information about the grammar of a language. struct Grammar { std::string grammar_name; std::vector rules; }; } // namespace fuzztest::internal::grammar #endif // FUZZTEST_GRAMMAR_CODEGEN_GRAMMAR_INFO_H_