#ifndef GRAMMAR_HH #define GRAMMAR_HH #include "errors.hh" #include "io.hh" #include #include #include #include namespace grammar { struct Element; struct Symbol { enum class Type : uint8_t { // value == terminal, as UTF-8 kTerminal, // element != nullptr kNonTerminal, // char_class != 0 kCharacterClass, }; Type type; enum class Optional : uint8_t { // Symbol is NOT optional. kRequired, // Symbol is optional. kZeroOrOne, // Symbol is optional and can repeat. kZeroOrMore, // Symbol should be excluded from previous symbol. // Example: InputCharacter but not * or / kExcluded, }; Optional optional{Optional::kRequired}; uint8_t char_class{0}; Element const* element{nullptr}; std::string value; }; struct Definition { std::vector symbols; }; struct Element { std::string name; std::vector definitions; }; class Grammar { public: virtual ~Grammar() = default; [[nodiscard]] virtual Element const& root() const = 0; protected: Grammar() = default; Grammar(Grammar const&) = delete; Grammar& operator=(Grammar const&) = delete; }; std::unique_ptr load(std::unique_ptr reader, std::vector const& character_classes, src::Errors& errors); } // namespace grammar #endif // GRAMMAR_HH