json done

This commit is contained in:
SimonFJ20 2024-11-18 10:11:58 +01:00
parent 77483438d8
commit b96dc867ab
2 changed files with 90 additions and 13 deletions

View File

@ -1,7 +1,6 @@
#include "json.hpp" #include "json.hpp"
#include <cstdlib> #include <cstdlib>
#include <format> #include <format>
#include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -153,18 +152,74 @@ auto Parser::parse_val() -> Res<std::unique_ptr<Value>>
case TokTyp::LBrace: { case TokTyp::LBrace: {
step(); step();
ObjectFields fields; ObjectFields fields;
while (curtyp() != TokTyp::RBrace) { }
if (curtyp() != TokTyp::RBrace) { if (curtyp() != TokTyp::RBrace) {
return Err { if (curtyp() != TokTyp::String) {
.pos = this->cur.val().pos, return unexpected_tok_err(
.msg TokTyp::String, "malformed object");
= std::format("malformed object, expected '}', got '{}'", }
tok_typ_to_string(this->cur.val().typ)), auto key = this->lexer.val(this->cur.val().val_id);
}; step();
if (curtyp() != TokTyp::Comma) {
return unexpected_tok_err(
TokTyp::Comma, "malformed object");
}
step();
auto value = parse_val();
if (value.ok()) {
return value.err();
}
fields.insert_or_assign(key, std::move(value.val()));
while (curtyp() == TokTyp::Comma) {
step();
if (curtyp() != TokTyp::String) {
return unexpected_tok_err(
TokTyp::String, "malformed object");
}
auto key = this->lexer.val(this->cur.val().val_id);
step();
if (curtyp() != TokTyp::Comma) {
return unexpected_tok_err(
TokTyp::Comma, "malformed object");
}
step();
auto value = parse_val();
if (value.ok()) {
return value.err();
}
fields.insert_or_assign(key, std::move(value.val()));
}
} }
if (curtyp() != TokTyp::RBrace) {
return unexpected_tok_err(TokTyp::RBrace, "malformed object");
}
return Res<std::unique_ptr<Value>>(
std::make_unique<Object>(std::move(fields)));
}
case TokTyp::LBracket: {
step();
ArrayValues values;
if (curtyp() != TokTyp::RBrace) {
auto value = parse_val();
if (value.ok()) {
return value.err();
}
values.push_back(std::move(value.val()));
while (curtyp() == TokTyp::Comma) {
step();
auto value = parse_val();
if (value.ok()) {
return value.err();
}
values.push_back(std::move(value.val()));
}
}
if (curtyp() != TokTyp::RBrace) {
return unexpected_tok_err(TokTyp::RBrace, "malformed object");
}
return Res<std::unique_ptr<Value>>(
std::make_unique<Array>(std::move(values)));
} }
case TokTyp::RBrace: case TokTyp::RBrace:
case TokTyp::LBracket:
case TokTyp::RBracket: case TokTyp::RBracket:
case TokTyp::Comma: case TokTyp::Comma:
case TokTyp::Colon: case TokTyp::Colon:
@ -175,4 +230,9 @@ auto Parser::parse_val() -> Res<std::unique_ptr<Value>>
}; };
break; break;
} }
return Err {
.pos = cur.pos,
.msg = std::format(
"internal error, could not parse '{}'", tok_typ_to_string(cur.typ)),
};
} }

View File

@ -2,11 +2,12 @@
#include <concepts> #include <concepts>
#include <cstddef> #include <cstddef>
#include <format>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
#include <string_view>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
namespace sliger::json { namespace sliger::json {
@ -292,6 +293,17 @@ public:
auto parse_val() -> Res<std::unique_ptr<Value>>; auto parse_val() -> Res<std::unique_ptr<Value>>;
private: private:
inline auto unexpected_tok_err(TokTyp expected, std::string_view msg)
-> Res<std::unique_ptr<Value>>
{
return Err {
.pos = this->cur.val().pos,
.msg = std::format("{}, expected '{}', got '{}'", msg,
tok_typ_to_string(expected),
tok_typ_to_string(this->cur.val().typ)),
};
}
inline auto step() -> Res<void> inline auto step() -> Res<void>
{ {
auto tok = this->lexer.next(); auto tok = this->lexer.next();
@ -305,12 +317,17 @@ private:
Res<Tok> cur; Res<Tok> cur;
}; };
struct Jsonable { struct Serializable {
virtual ~Jsonable() = default; virtual ~Serializable() = default;
virtual auto to_json() const -> std::string = 0; virtual auto to_json() const -> std::string = 0;
}; };
template <typename T> auto from_json() -> T { T::from_json(); } template <typename T>
requires std::derived_from<T, Serializable>
auto from_json(std::string_view json_string) -> T
{
return T::from_json(json_string);
}
} }