From d3d71bb044e0ae9af75bd74d4030e1d95f18a68e Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Fri, 14 Feb 2025 08:08:57 +0100 Subject: feat(json): Nested parsing --- json.c | 67 +++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 27 deletions(-) (limited to 'json.c') diff --git a/json.c b/json.c index cf40634..197dca3 100644 --- a/json.c +++ b/json.c @@ -9,7 +9,13 @@ #include "string.h" typedef struct { - int value; + JSON *value; + uintptr_t pos; +} parse_any_result; +parse_any_result parse_any(Arena *a, char *src, uintptr_t pos); + +typedef struct { + int *value; uintptr_t pos; } parse_integer_result; @@ -21,11 +27,11 @@ parse_integer_result parse_integer(Arena *a, char *src, uintptr_t pos) { ints[i] = val; i++; } - int result = 0; + int *result = new (a, int, 1); for (int j = 0; j < i; j++) { - result += ints[j] * pow(10, (i - j - 1)); + *result += ints[j] * pow(10, (i - j - 1)); } - printf("json.parse_integer: parsed int=%d at pos=%lu\n", result, pos); + printf("json.parse_integer: parsed int=%d at pos=%lu\n", *result, pos); return (parse_integer_result){result, pos + i}; } @@ -42,16 +48,15 @@ typedef struct { uintptr_t pos; } parse_array_result; -parse_array_result parse_array(Arena *a, char *src, uintptr_t start_pos) { - printf("json.parse_array: parsing array %s\n", src + start_pos); - assert(src[start_pos] == '['); - uintptr_t pos = start_pos + 1; - Vec *items = Vec_new(a, JSON, 0); +parse_array_result parse_array(Arena *a, char *src, uintptr_t pos) { + printf("json.parse_array: parsing array %s\n", src + pos); + assert(src[pos] == '['); + pos++; + Vec items = Vec_new(a, JSON, 2); for (;;) { pos = absorb_whitespaces(src, pos); - parse_integer_result result = parse_integer(a, src, pos); - assert(result.pos > pos); - items = Vec_push(a, items, &result.value); + parse_any_result result = parse_any(a, src, pos); + Vec_push(a, &items, result.value); pos = result.pos; pos = absorb_whitespaces(src, pos); if (src[pos] == ',') { @@ -62,7 +67,7 @@ parse_array_result parse_array(Arena *a, char *src, uintptr_t start_pos) { }; assert(src[pos] == ']'); - return (parse_array_result){items, pos + 1}; + return (parse_array_result){&items, pos + 1}; } typedef struct { @@ -78,31 +83,39 @@ parse_string_result parse_string(Arena *a, char *src, uintptr_t pos) { while (src[pos + i] != '"' && src[pos + i - 1] != '\\') { i++; } - assert(src[pos + i]); + assert(src[pos + i] == '"'); Str s = Str_copy(a, &src[pos + 1], i - 1); - return (parse_string_result){s, pos + i}; + return (parse_string_result){s, pos + i + 1}; } -JSON JSON_parse(Arena *a, char *src) { - JSON json = {0}; - int pos = 0; - printf("json.parse: src=%s\n", src); +parse_any_result parse_any(Arena *a, char *src, uintptr_t pos) { + JSON *value = new (a, JSON, 1); if (isdigit(src[pos])) { - parse_integer_result result = parse_integer(a, src, 0); - json.integer = &result.value; + parse_integer_result result = parse_integer(a, src, pos); + value->integer = result.value; pos = result.pos; - } - if (src[pos] == '[') { + } else if (src[pos] == '[') { parse_array_result result = parse_array(a, src, pos); - json.array = result.items; + value->array = result.items; pos = result.pos; - } - if (src[pos] == '"') { + } else if (src[pos] == '"') { parse_string_result result = parse_string(a, src, pos); - json.string = &result.string; + value->string = &result.string; pos = result.pos; } + return (parse_any_result){value, pos}; +} + +JSON JSON_parse(Arena *a, char *src) { + parse_any_result result = parse_any(a, src, 0); + return *result.value; +} + +JSON JSON_Int(Arena *a, int val) { + JSON json = {0}; + json.integer = new (a, int, 1); + *json.integer = val; return json; } -- cgit v1.3