Author SHA1 Message Date
roodletoof d87b92e40a some progress
some progress

some progress
2026-10-03 21:47:00 +02:00
roodletoof b553af59c2 add criterion headers to ctags generation for linux 2026-10-01 22:19:38 +02:00
roodletoof 6c8ffd7d63 starting some work on implementation 2026-10-01 22:19:38 +02:00
roodletoof 93a452c041 add initial json parser definitions 2026-10-01 22:19:38 +02:00
5 changed files with 166 additions and 7 deletions
+51 -1
View File
@@ -317,7 +317,7 @@ scan_result_t scan_value_func(scan_value_t value);
scan_result_t scan_error_and_recover(scanner_t *s, char const *message);
bool scan_eof(scanner_t *s);
bool scan_literal(scanner_t *s, char const *lit);
scan_result_t scan_literal(scanner_t *s, char const *lit);
int scan_repeat_literal(scanner_t *s, char const *lit);
bool scan_whitespace(scanner_t *s);
scan_result_t scan_digit(scanner_t *s);
@@ -342,6 +342,55 @@ bool scanner_print_errors_func(FILE *fp, scan_result_t const *results, int resul
bool looks_like_float(scanner_t *s);
bool looks_like_int(scanner_t *s);
// json parser /////////////////////////////////////////////////////////////////
typedef enum json_type {
json_type_array,
json_type_boolean,
json_type_null,
json_type_number,
json_type_object,
json_type_string,
count_json_type_t
} json_type_t;
typedef struct json_string {
const char *buffer;
size_t length;
} json_string_t;
struct json_pair;
typedef struct json_object {
struct json_pair *pairs;
size_t length;
} json_object_t;
struct json_value;
typedef struct json_array {
struct json_value *values;
size_t length;
} json_array_t;
typedef struct json_value {
json_type_t type;
union {
bool boolean;
double number;
json_object_t object;
json_array_t array;
json_string_t string;
};
} json_value_t;
typedef struct json_pair {
json_string_t key;
json_value_t value;
} json_pair_t;
bool json_parse(scanner_t *scanner, allocator_t allocator, json_value_t *out);
// string builder //////////////////////////////////////////////////////////////
typedef struct string_builder_node {
struct string_builder_node *next;
@@ -403,6 +452,7 @@ void allocator_reset(allocator_t this) {
#include "dyn_array.c"
#include "cli.c"
#include "scanner.c"
#include "json.c"
#include "string_builder.c"
#include "file_io.c"
+107
View File
@@ -0,0 +1,107 @@
#include "cig.h"
#include <string.h>
bool json_parse(scanner_t *scanner, allocator_t allocator, json_value_t *out) {
scan_whitespace(scanner);
scan_result_t str_result = scan_string_literal(scanner);
if (str_result.ok) {
const char *buffer = str_result.value.string_literal;
size_t length = strlen(buffer);
char *buff_copy = allocator_alloc(allocator, length+1);
strncpy(buff_copy, buffer, length+1);
buff_copy[length] = '\0';
*out = (json_value_t) {
.type=json_type_string,
.string=(json_string_t) { .length=length, .buffer=buff_copy }
};
return true;
}
scan_result_t f64_result = scan_f64(scanner);
if (f64_result.ok) {
*out = (json_value_t) {
.type=json_type_number,
.number=f64_result.value.f64
};
return true;
}
scan_result_t i64_result = scan_i64(scanner);
if (i64_result.ok) {
*out = (json_value_t) {
.type=json_type_number,
.number=(double)i64_result.value.i64
};
return true;
}
scan_result_t true_result = scan_literal(scanner, "true");
if (true_result.ok) {
*out = (json_value_t) {
.type=json_type_boolean,
.boolean=true
};
return true;
}
scan_result_t false_result = scan_literal(scanner, "false");
if (false_result.ok) {
*out = (json_value_t) {
.type=json_type_boolean,
.boolean=false
};
return true;
}
scan_result_t null_result = scan_literal(scanner, "null");
if (null_result.ok) {
*out = (json_value_t) { .type=json_type_null, };
return true;
}
scan_result_t arr_open_result = scan_literal(scanner, "[");
if (arr_open_result.ok) {
json_value_t *values = make_arr(json_value_t, allocator);
do {
scan_whitespace(scanner);
scan_result_t arr_close_result = scan_literal(scanner, "]");
if (arr_close_result.ok) {
break;
}
json_value_t val;
bool ok = json_parse(scanner, allocator, &val);
if (!ok) {
return false;
}
arr_append(values, val);
} while(scan_literal(scanner, ",").ok); // Not quite correct, but oh well...
*out = (json_value_t) {
.type=json_type_array,
.array=(json_array_t){
.values=values,
.length=arr_len(values),
},
};
return arr_close_result.ok;
}
// TODO: arrays and objects are allowed to contain nothing...
scan_result_t obj_open_result = scan_literal(scanner, "{");
if (obj_open_result.ok) {
json_pair_t *pairs = make_arr(json_pair_t, allocator);
do {
scan_whitespace(scanner);
scan_result_t key_result = scan_string_literal(scanner);
} while(scan_literal(scanner, ",").ok);
}
typedef struct json_pair {
json_string_t key;
json_value_t value;
} json_pair_t;
}
+2
View File
@@ -32,6 +32,8 @@ LDFLAGS := if os() == "macos" {
}
DEPENDENCY_HEADERS := if os() == "macos" {
"$(pkg-config --cflags-only-I criterion | sed 's/-I//g')"
} else if os() == "linux" {
"/usr/include/criterion/"
} else {
"TODO: windows"
}
+4 -4
View File
@@ -60,22 +60,22 @@ bool scan_eof(scanner_t *s) {
return *s->cur == '\0';
}
bool scan_literal(scanner_t *s, char const *lit) {
scan_result_t scan_literal(scanner_t *s, char const *lit) {
char const *save = s->cur;
while (*lit && *lit == *s->cur) {
lit++;
s->cur++;
}
if (*lit == '\0') {
return true;
return (scan_result_t) { .ok = true };
}
s->cur = save;
return false;
return scan_error(s, "literal not present");
}
int scan_repeat_literal(scanner_t *s, char const *lit) {
int n_repeats = 0;
while (scan_literal(s, lit)) {
while (scan_literal(s, lit).ok) {
n_repeats++;
}
return n_repeats;
+2 -2
View File
@@ -26,9 +26,9 @@ Test(scanner, looks_like_float) {
bool does_look_like_int = looks_like_int(&scanner);
while (*scanner.cur++ != ' ');
bool expect;
if (scan_literal(&scanner, "true")) {
if (scan_literal(&scanner, "true").ok) {
expect = true;
} else if (scan_literal(&scanner, "false")) {
} else if (scan_literal(&scanner, "false").ok) {
expect = false;
} else {
assert(false && "invalid expectation");