#ifndef TOML11_SCANNER_FWD_HPP #define TOML11_SCANNER_FWD_HPP #include "../region.hpp" #include "../version.hpp" #include #include #include #include #include #include #include namespace toml { inline namespace TOML11_INLINE_VERSION_NAMESPACE { namespace detail { class scanner_base { public: virtual ~scanner_base() = default; virtual region scan(location& loc) const = 0; virtual scanner_base* clone() const = 0; // returns expected character or set of characters or literal. // to show the error location, it changes loc (in `sequence`, especially). virtual std::string expected_chars(location& loc) const = 0; virtual std::string name() const = 0; }; // make `scanner*` copyable struct scanner_storage { template>::value, std::nullptr_t> = nullptr> explicit scanner_storage(Scanner&& s) : scanner_(cxx::make_unique>(std::forward(s))) {} ~scanner_storage() = default; scanner_storage(const scanner_storage& other); scanner_storage& operator=(const scanner_storage& other); scanner_storage(scanner_storage&&) = default; scanner_storage& operator=(scanner_storage&&) = default; bool is_ok() const noexcept {return static_cast(scanner_);} region scan(location& loc) const; std::string expected_chars(location& loc) const; scanner_base& get() const noexcept; std::string name() const; private: std::unique_ptr scanner_; }; // ---------------------------------------------------------------------------- class character final : public scanner_base { public: using char_type = location::char_type; public: explicit character(const char_type c) noexcept : value_(c) {} ~character() override = default; region scan(location& loc) const override; std::string expected_chars(location&) const override; scanner_base* clone() const override; std::string name() const override; private: char_type value_; }; // ---------------------------------------------------------------------------- class character_either final : public scanner_base { public: using char_type = location::char_type; public: template explicit character_either(const char (&cs)[N]) noexcept : value_(cs), size_(N-1) // remove null character at the end {} ~character_either() override = default; region scan(location& loc) const override; std::string expected_chars(location&) const override; scanner_base* clone() const override; std::string name() const override; private: const char* value_; std::size_t size_; }; // ---------------------------------------------------------------------------- class character_in_range final : public scanner_base { public: using char_type = location::char_type; public: explicit character_in_range(const char_type from, const char_type to) noexcept : from_(from), to_(to) {} ~character_in_range() override = default; region scan(location& loc) const override; std::string expected_chars(location&) const override; scanner_base* clone() const override; std::string name() const override; private: char_type from_; char_type to_; }; // ---------------------------------------------------------------------------- class literal final : public scanner_base { public: using char_type = location::char_type; public: template explicit literal(const char (&cs)[N]) noexcept : value_(cs), size_(N-1) // remove null character at the end {} ~literal() override = default; region scan(location& loc) const override; std::string expected_chars(location&) const override; scanner_base* clone() const override; std::string name() const override; private: const char* value_; std::size_t size_; }; // ---------------------------------------------------------------------------- class sequence final: public scanner_base { public: using char_type = location::char_type; public: template explicit sequence(Ts&& ... args) { push_back_all(std::forward(args)...); } sequence(const sequence&) = default; sequence(sequence&&) = default; sequence& operator=(const sequence&) = default; sequence& operator=(sequence&&) = default; ~sequence() override = default; region scan(location& loc) const override; std::string expected_chars(location& loc) const override; scanner_base* clone() const override; std::string name() const override; private: void push_back_all() { return; } template void push_back_all(T&& head, Ts&& ... args) { others_.emplace_back(std::forward(head)); push_back_all(std::forward(args)...); return; } private: std::vector others_; }; // ---------------------------------------------------------------------------- class either final: public scanner_base { public: using char_type = location::char_type; public: template explicit either(Ts&& ... args) { push_back_all(std::forward(args)...); } either(const either&) = default; either(either&&) = default; either& operator=(const either&) = default; either& operator=(either&&) = default; ~either() override = default; region scan(location& loc) const override; std::string expected_chars(location& loc) const override; scanner_base* clone() const override; std::string name() const override; private: void push_back_all() { return; } template void push_back_all(T&& head, Ts&& ... args) { others_.emplace_back(std::forward(head)); push_back_all(std::forward(args)...); return; } private: std::vector others_; }; // ---------------------------------------------------------------------------- class repeat_exact final: public scanner_base { public: using char_type = location::char_type; public: template repeat_exact(const std::size_t length, Scanner&& other) : length_(length), other_(std::forward(other)) {} repeat_exact(const repeat_exact&) = default; repeat_exact(repeat_exact&&) = default; repeat_exact& operator=(const repeat_exact&) = default; repeat_exact& operator=(repeat_exact&&) = default; ~repeat_exact() override = default; region scan(location& loc) const override; std::string expected_chars(location& loc) const override; scanner_base* clone() const override; std::string name() const override; private: std::size_t length_; scanner_storage other_; }; // ---------------------------------------------------------------------------- class repeat_at_least final: public scanner_base { public: using char_type = location::char_type; public: template repeat_at_least(const std::size_t length, Scanner&& s) : length_(length), other_(std::forward(s)) {} repeat_at_least(const repeat_at_least&) = default; repeat_at_least(repeat_at_least&&) = default; repeat_at_least& operator=(const repeat_at_least&) = default; repeat_at_least& operator=(repeat_at_least&&) = default; ~repeat_at_least() override = default; region scan(location& loc) const override; std::string expected_chars(location& loc) const override; scanner_base* clone() const override; std::string name() const override; private: std::size_t length_; scanner_storage other_; }; // ---------------------------------------------------------------------------- class maybe final: public scanner_base { public: using char_type = location::char_type; public: template explicit maybe(Scanner&& s) : other_(std::forward(s)) {} maybe(const maybe&) = default; maybe(maybe&&) = default; maybe& operator=(const maybe&) = default; maybe& operator=(maybe&&) = default; ~maybe() override = default; region scan(location& loc) const override; std::string expected_chars(location&) const override; scanner_base* clone() const override; std::string name() const override; private: scanner_storage other_; }; } // detail } // TOML11_INLINE_VERSION_NAMESPACE } // toml #endif // TOML11_SCANNER_FWD_HPP