From b96dc867ab59736e6a3a81e80b4f8dc177225f2f Mon Sep 17 00:00:00 2001
From: SimonFJ20 <simonfromjakobsen@gmail.com>
Date: Mon, 18 Nov 2024 10:11:58 +0100
Subject: [PATCH] json done

---
 runtime/json.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++------
 runtime/json.hpp | 25 +++++++++++++---
 2 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/runtime/json.cpp b/runtime/json.cpp
index c72cc49..c677beb 100644
--- a/runtime/json.cpp
+++ b/runtime/json.cpp
@@ -1,7 +1,6 @@
 #include "json.hpp"
 #include <cstdlib>
 #include <format>
-#include <iostream>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -153,18 +152,74 @@ auto Parser::parse_val() -> Res<std::unique_ptr<Value>>
         case TokTyp::LBrace: {
             step();
             ObjectFields fields;
-            while (curtyp() != TokTyp::RBrace) { }
             if (curtyp() != TokTyp::RBrace) {
-                return Err {
-                    .pos = this->cur.val().pos,
-                    .msg
-                    = std::format("malformed object, expected '}', got '{}'",
-                        tok_typ_to_string(this->cur.val().typ)),
-                };
+                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()));
+                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::LBracket:
         case TokTyp::RBracket:
         case TokTyp::Comma:
         case TokTyp::Colon:
@@ -175,4 +230,9 @@ auto Parser::parse_val() -> Res<std::unique_ptr<Value>>
             };
             break;
     }
+    return Err {
+        .pos = cur.pos,
+        .msg = std::format(
+            "internal error, could not parse '{}'", tok_typ_to_string(cur.typ)),
+    };
 }
diff --git a/runtime/json.hpp b/runtime/json.hpp
index 0d39e52..1d543cb 100644
--- a/runtime/json.hpp
+++ b/runtime/json.hpp
@@ -2,11 +2,12 @@
 
 #include <concepts>
 #include <cstddef>
+#include <format>
 #include <memory>
 #include <optional>
 #include <string>
+#include <string_view>
 #include <unordered_map>
-#include <unordered_set>
 #include <vector>
 
 namespace sliger::json {
@@ -292,6 +293,17 @@ public:
     auto parse_val() -> Res<std::unique_ptr<Value>>;
 
 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>
     {
         auto tok = this->lexer.next();
@@ -305,12 +317,17 @@ private:
     Res<Tok> cur;
 };
 
-struct Jsonable {
-    virtual ~Jsonable() = default;
+struct Serializable {
+    virtual ~Serializable() = default;
 
     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);
+}
 
 }