#pragma once #include #include #include #include #include #include #include namespace sliger::json { enum class Type { Null, String, Number, Bool, Array, Object, }; struct Value { virtual ~Value() = default; virtual auto type() const -> Type = 0; template requires std::derived_from inline auto as() & -> T& { return static_cast(this); } }; struct Null final : public Value { auto type() const -> Type override { return Type::Null; } }; struct String final : public Value { auto type() const -> Type override { return Type::String; } std::string value; }; struct Number final : public Value { auto type() const -> Type override { return Type::Number; } double value; }; struct Bool final : public Value { auto type() const -> Type override { return Type::Bool; } bool value; }; struct Array final : public Value { auto type() const -> Type override { return Type::Array; } std::vector> values; }; struct Object final : public Value { auto type() const -> Type override { return Type::Object; } }; struct Pos { int line; int col; }; enum class TokTyp { Error, Eof, String, Float, False, True, Null, LBrace, RBrace, LBracket, RBracket, Comma, Colon, }; struct Tok { Tok(TokTyp typ) : typ(typ) , val_id(0) { } Tok(TokTyp typ, size_t val_id) : typ(typ) , val_id(val_id) { } Tok(TokTyp typ, double float_val) : typ(typ) , float_val(float_val) { } Tok(TokTyp typ, bool bool_val) : typ(typ) , bool_val(bool_val) { } TokTyp typ; union { size_t val_id; double float_val; bool bool_val; }; }; class Lexer { public: Lexer(std::string_view text) : text(text) { } auto next() -> Tok; inline auto pos() const -> Pos { return { this->line, this->col }; } private: inline void step() { this->i += 1; } inline auto test_in(std::string_view chs) const -> bool { for (auto ch : chs) if (test(ch)) return true; return false; } inline auto test(char ch) const -> bool { return !done() && cur() == ch; } inline auto done() const -> bool { return this->i >= this->text.size(); } inline auto cur() const -> char { return this->text.at(this->i); } std::string_view text; size_t i = 0; int line = 1; int col = 1; }; class Parser { public: Parser(std::string_view text) : lexer(text) , cur(lexer.next()) { } private: Lexer lexer; Tok cur; }; struct Jsonable { virtual ~Jsonable() = default; virtual auto to_json() const -> std::string = 0; }; template auto from_json() -> T { T::from_json(); } }