diff --git a/include/parser/parser.h b/include/parser/parser.h index 0a27d01..da66a89 100644 --- a/include/parser/parser.h +++ b/include/parser/parser.h @@ -4,6 +4,8 @@ #include "json_entities.h" #include "lexer.h" -void parse_token(token_t token); +typedef struct parser_s parser_t; + +jentity_t *load_json(const char *filepath); #endif // !PARSER_H diff --git a/src/main.c b/src/main.c index 12cde95..8539a09 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include "aliases.h" +#include "json_entities.h" #include "lexer.h" #include "parser.h" #include @@ -14,48 +15,13 @@ int main(int argc, char *argv[]) { const char *filename = argv[1]; - FILE *fp = fopen(filename, "r"); + jentity_t *root = load_json(filename); - fseek(fp, 0, SEEK_END); - - u64 length = ftell(fp); - - fseek(fp, 0, SEEK_SET); - - char json[length + 1]; - memset(json, 0, length + 1); - - fread(json, sizeof(char), length, fp); - - fclose(fp); - - lexer_t *lexer = NULL; - - lexer_init(&lexer); - if (!lexer) { + if (!root) { return EXIT_FAILURE; } - lex_result_t result = get_next_token(lexer, json); - - if (result.error.errno) { - printf("%s\n", result.error.msg); - } else { - while (result.token.type != TK_NO_TOKEN) { - print_token(result.token); - - parse_token(result.token); - - result = get_next_token(lexer, NULL); - - if (result.error.errno) { - printf("%s\n", result.error.msg); - break; - } - } - } - - lexer_free(&lexer); + print_json(root, 2); return EXIT_SUCCESS; } diff --git a/src/parser/parser.c b/src/parser/parser.c index b05e414..b4fb345 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -5,91 +5,182 @@ #include "lexer.h" #include #include +#include -INTERNAL jentity_t *current = NULL; +struct parser_s { + jentity_t *root; + jentity_t *current; + jval_t value; +}; -INTERNAL jcoll_t *get_collection_from_entity(const jentity_t *entity); -INTERNAL jentity_t *create_new_single_entity(const jval_t value, - jentity_t *parent); -INTERNAL jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value, - jentity_t *parent); -INTERNAL void add_key(jentity_t **entity, dstr_t *key, const jval_t *value); -INTERNAL jentity_t *add_value(jentity_t **entity, const jval_t *value); -INTERNAL void add_collection(jentity_t **entity, const jval_t *value); +INTERNAL void parser_free(parser_t **parser); +INTERNAL void parser_init(parser_t **parser); +INTERNAL void parse_token(parser_t *parser, token_t token); +INTERNAL void add_key(parser_t *parser, dstr_t *key); +INTERNAL jentity_t *add_value(parser_t *parser); +INTERNAL void add_collection(parser_t *parser); -void parse_token(token_t token) { +jentity_t *load_json(const char *filepath) { + FILE *fp = fopen(filepath, "r"); + + if (!fp) { + return NULL; + } + + fseek(fp, 0, SEEK_END); + + u64 length = ftell(fp); + + fseek(fp, 0, SEEK_SET); + + char json[length + 1]; + memset(json, 0, length + 1); + + fread(json, sizeof(char), length, fp); + + fclose(fp); + + lexer_t *lexer = NULL; + parser_t *parser = NULL; + + lexer_init(&lexer); + if (!lexer) { + return NULL; + } + + parser_init(&parser); + if (!parser) { + lexer_free(&lexer); + + return NULL; + } + + lex_result_t result = get_next_token(lexer, json); + + if (result.error.errno) { + printf("%s\n", result.error.msg); + } else { + while (result.token.type != TK_NO_TOKEN) { + parse_token(parser, result.token); + + result = get_next_token(lexer, NULL); + + if (result.error.errno) { + printf("%s\n", result.error.msg); + break; + } + } + } + + jentity_t *root = parser->root; + + parser_free(&parser); + lexer_free(&lexer); + + return root; +} + +void parser_init(parser_t **parser) { + if (*parser) { + parser_free(parser); + } + + *parser = (parser_t *)malloc(sizeof(parser_t)); + + if (!(*parser)) { + return; + } + + (*parser)->root = NULL; + (*parser)->current = NULL; + (*parser)->value = (jval_t){0}; +} + +void parser_free(parser_t **parser) { + if (!(*parser)) { + return; + } + + (*parser)->root = NULL; + (*parser)->current = NULL; + + free(*parser); + *parser = NULL; +} + +void parse_token(parser_t *parser, token_t token) { switch (token.type) { case TK_L_BRACE: case TK_L_BRACKET: { - jval_t value = (jval_t){ + parser->value = (jval_t){ .type = JVAL_COLLECTION, .collection = (jcoll_t *)malloc(sizeof(jcoll_t)), }; if (token.type == TK_L_BRACE) { - value.collection->type = JCOLL_OBJECT; + parser->value.collection->type = JCOLL_OBJECT; } else { - value.collection->type = JCOLL_ARRAY; + parser->value.collection->type = JCOLL_ARRAY; } - value.collection->size = 0; - value.collection->begin = NULL; - value.collection->end = NULL; + parser->value.collection->size = 0; + parser->value.collection->begin = NULL; + parser->value.collection->end = NULL; - add_collection(¤t, &value); + add_collection(parser); break; } case TK_R_BRACE: case TK_R_BRACKET: - if (current->parent) { - current = current->parent; + if (parser->current->parent) { + parser->current = parser->current->parent; } break; case TK_STR_KEY: { - jval_t value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL}; + parser->value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL}; - add_key(¤t, dstr_from_string(token.value.string), &value); + add_key(parser, dstr_from_string(token.value.string)); break; } case TK_NULL: { - jval_t value = (jval_t){.type = JVAL_NULL, .null_val = NULL}; + parser->value = (jval_t){.type = JVAL_NULL, .null_val = NULL}; - add_value(¤t, &value); + add_value(parser); break; } case TK_BOOL: { - jval_t value = + parser->value = (jval_t){.type = JVAL_BOOLEAN, .boolean = token.value.boolean}; - add_value(¤t, &value); + add_value(parser); break; } case TK_STR_VAL: { - jval_t value = (jval_t){.type = JVAL_STRING, - .string = dstr_from_string(token.value.string)}; + parser->value = (jval_t){.type = JVAL_STRING, + .string = dstr_from_string(token.value.string)}; - add_value(¤t, &value); + add_value(parser); break; } case TK_INTEGER: { - jval_t value = + parser->value = (jval_t){.type = JVAL_INTEGER, .num_int = token.value.num_int}; - add_value(¤t, &value); + add_value(parser); break; } case TK_DOUBLE: { - jval_t value = + parser->value = (jval_t){.type = JVAL_DOUBLE, .num_dbl = token.value.num_frac}; - add_value(¤t, &value); + add_value(parser); break; } @@ -98,45 +189,8 @@ void parse_token(token_t token) { } } -jcoll_t *get_collection_from_entity(const jentity_t *entity) { - return entity->type == JENTITY_SINGLE ? entity->value.collection - : entity->pair.value.collection; -} - -jentity_t *create_new_single_entity(const jval_t value, jentity_t *parent) { - jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); - - if (!entity) { - return NULL; - } - - entity->type = JENTITY_SINGLE; - entity->value = value; - entity->parent = parent; - entity->next = NULL; - - return entity; -} - -jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value, - jentity_t *parent) { - jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); - - if (!entity) { - return NULL; - } - - entity->type = JENTITY_PAIR; - entity->pair.key = key; - entity->pair.value = value; - entity->parent = parent; - entity->next = NULL; - - return entity; -} - -void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { - jcoll_t *collection = get_collection_from_entity(*entity); +void add_key(parser_t *parser, dstr_t *key) { + jcoll_t *collection = get_collection_from_entity(parser->current); if (!collection) { return; @@ -144,11 +198,12 @@ void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { if (!(collection->end)) { collection->begin = collection->end = - create_new_pair_entity(key, *value, *entity); + create_new_pair_entity(key, parser->value, parser->current); collection->size = 1; } else { - jentity_t *new_entity = create_new_pair_entity(key, *value, *entity); + jentity_t *new_entity = + create_new_pair_entity(key, parser->value, parser->current); collection->end->next = new_entity; @@ -158,8 +213,8 @@ void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { } } -jentity_t *add_value(jentity_t **entity, const jval_t *value) { - jcoll_t *collection = get_collection_from_entity(*entity); +jentity_t *add_value(parser_t *parser) { + jcoll_t *collection = get_collection_from_entity(parser->current); if (!collection) { return NULL; @@ -167,15 +222,16 @@ jentity_t *add_value(jentity_t **entity, const jval_t *value) { if (!(collection->end)) { collection->begin = collection->end = - create_new_single_entity(*value, *entity); + create_new_single_entity(parser->value, parser->current); collection->size = 1; } else { if (collection->end->type == JENTITY_PAIR && collection->end->pair.value.type == JVAL_EMPTY) { - collection->end->pair.value = *value; + collection->end->pair.value = parser->value; } else { - jentity_t *new_entity = create_new_single_entity(*value, *entity); + jentity_t *new_entity = + create_new_single_entity(parser->value, parser->current); collection->end->next = new_entity; @@ -188,12 +244,13 @@ jentity_t *add_value(jentity_t **entity, const jval_t *value) { return collection->end; } -void add_collection(jentity_t **entity, const jval_t *value) { - if (!(*entity)) { - *entity = create_new_single_entity(*value, NULL); +void add_collection(parser_t *parser) { + if (!(parser->root)) { + parser->root = parser->current = + create_new_single_entity(parser->value, NULL); return; } - *entity = add_value(entity, value); + parser->current = add_value(parser); }