mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 22:46:30 +00:00
json done
This commit is contained in:
parent
77483438d8
commit
b96dc867ab
@ -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)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user