summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/parser/parser.c19
-rw-r--r--compiler/parser/type.c95
2 files changed, 77 insertions, 37 deletions
diff --git a/compiler/parser/parser.c b/compiler/parser/parser.c
index 261385b..a630e37 100644
--- a/compiler/parser/parser.c
+++ b/compiler/parser/parser.c
@@ -15,7 +15,7 @@
#include "parser.h"
static void
-add_builtin(struct hashmap *map, char *name, size_t size, int n_ptrs)
+add_builtin(struct hashmap *map, char *name, size_t size)
{
struct type *type;
size_t name_len;
@@ -27,7 +27,7 @@ add_builtin(struct hashmap *map, char *name, size_t size, int n_ptrs)
type->name = name;
type->name_len = name_len;
type->size = size;
- type->n_ptrs = n_ptrs;
+ type->n_ptrs = 0;
hashmap_add(map, &type->hashmap_entry);
}
@@ -67,8 +67,7 @@ parser_parse(struct parser *ctx)
break;
default:
tok_error(&ctx->tok, "unexpected \"%.*s\"\n", (int)ctx->tok.len, ctx->tok.pos);
- next_token(ctx);
- break;
+ return;
}
}
}
@@ -79,10 +78,10 @@ parser_init(struct parser *ctx, char *source)
debug("Initializing parser...\n");
lexer_init(&ctx->lexer, source);
- add_builtin(ctx->types, "any", 0, 0);
- add_builtin(ctx->types, "uint", sizeof(void*), 0);
- add_builtin(ctx->types, "uint64", 8, 0);
- add_builtin(ctx->types, "uint32", 4, 0);
- add_builtin(ctx->types, "uint16", 2, 0);
- add_builtin(ctx->types, "uint8", 1, 0);
+ add_builtin(ctx->types, "any", 0);
+ add_builtin(ctx->types, "uint", sizeof(void*));
+ add_builtin(ctx->types, "uint64", 8);
+ add_builtin(ctx->types, "uint32", 4);
+ add_builtin(ctx->types, "uint16", 2);
+ add_builtin(ctx->types, "uint8", 1);
}
diff --git a/compiler/parser/type.c b/compiler/parser/type.c
index e0990c3..5e161b4 100644
--- a/compiler/parser/type.c
+++ b/compiler/parser/type.c
@@ -27,6 +27,21 @@ type_new(struct token *tok)
return typ;
}
+static void
+free_all(struct hashmap *map)
+{
+ struct hashmap_entry *ent, *next;
+
+ for (size_t r = 0; r < map->n_rows; r++) {
+ ent = (struct hashmap_entry*)map->rows[r].head;
+ while (ent != (struct hashmap_entry*)&map->rows[r]) {
+ next = (struct hashmap_entry*)ent->list_entry.next;
+ free(ent);
+ ent = next;
+ }
+ }
+}
+
static bool
parse_type_ref(struct parser *ctx, struct type **typ_out, int *n_ptrs_out)
{
@@ -72,6 +87,12 @@ parse_alias(struct parser *ctx, struct type *typ)
return false;
}
+ if (ctx->tok.kind != TK_SEMICOLON) {
+ tok_error(&ctx->tok, "expected \";\" after type definition\n");
+ return false;
+ }
+ next_token(ctx);
+
if (typ->n_ptrs >= 1) {
typ->size = sizeof(void*);
} else {
@@ -86,26 +107,29 @@ parse_enum(struct parser *ctx, struct type *typ)
{
struct enum_member *mem;
uint64_t value;
+ bool error;
debug("Parsing enum definition...\n");
- typ->kind = TYK_ENUM;
-
if (next_token(ctx)->kind != TK_LBRACE) {
tok_error(&ctx->tok, "expected \"{\" after \"enum\"\n");
return false;
}
+ /* Set up type and members hashmap */
+ typ->kind = TYK_ENUM;
typ->members.rows = malloc(HASHMAP_ROWS * sizeof(struct list));
typ->members.n_rows = HASHMAP_ROWS;
hashmap_init(&typ->members);
value = 0;
+ error = false;
next_token(ctx);
while (ctx->tok.kind != TK_RBRACE) {
if (ctx->tok.kind != TK_IDENTIFIER) {
tok_error(&ctx->tok, "expected enum member name\n");
- return true;
+ error = true;
+ break;
}
mem = malloc(sizeof(struct enum_member));
@@ -122,10 +146,18 @@ parse_enum(struct parser *ctx, struct type *typ)
if (ctx->tok.kind != TK_RBRACE) {
tok_error(&ctx->tok, "expected \",\" or \"}\" after enum member name\n");
- return true;
+ error = true;
+ break;
}
}
+ /* Free hashmap data if error occurred */
+ if (error) {
+ free_all(&typ->members);
+ free(typ->members.rows);
+ return false;
+ }
+
next_token(ctx);
return true;
}
@@ -134,64 +166,80 @@ static bool
parse_struct(struct parser *ctx, struct type *typ)
{
struct struct_member *mem;
- uint64_t off;
+ struct type *mem_typ;
+ int mem_n_ptrs;
+ size_t off;
+ bool error;
debug("Parsing struct definition...\n");
- typ->kind = TYK_STRUCT;
-
if (next_token(ctx)->kind != TK_LBRACE) {
tok_error(&ctx->tok, "expected \"{\" after \"struct\"\n");
return false;
}
+ /* Set up type and members hashmap */
+ typ->kind = TYK_STRUCT;
typ->members.rows = malloc(HASHMAP_ROWS * sizeof(struct list));
typ->members.n_rows = HASHMAP_ROWS;
hashmap_init(&typ->members);
off = 0;
+ error = false;
next_token(ctx);
while (ctx->tok.kind != TK_RBRACE) {
if (ctx->tok.kind != TK_IDENTIFIER) {
tok_error(&ctx->tok, "expected type name\n");
- return true;
+ error = true;
+ break;
}
- mem = malloc(sizeof(struct struct_member));
- mem->hashmap_entry.hash = ctx->tok.hash;
- mem->name = ctx->tok.pos;
- mem->name_len = ctx->tok.len;
- mem->off = off;
-
- if (!parse_type_ref(ctx, &mem->typ, &mem->n_ptrs)) {
- return true;
+ if (!parse_type_ref(ctx, &mem_typ, &mem_n_ptrs)) {
+ error = true;
+ break;
}
if (ctx->tok.kind != TK_IDENTIFIER) {
tok_error(&ctx->tok, "expected struct member name\n");
- return true;
+ error = true;
+ break;
}
+
+ mem = malloc(sizeof(struct struct_member));
+ mem->hashmap_entry.hash = ctx->tok.hash;
mem->name = ctx->tok.pos;
mem->name_len = ctx->tok.len;
+ mem->off = off;
+ mem->typ = mem_typ;
+ mem->n_ptrs = mem_n_ptrs;
if (mem->n_ptrs >= 1) {
mem->size = sizeof(void*);
} else {
mem->size = mem->typ->size;
}
- off += mem->size;
hashmap_add(&typ->members, &mem->hashmap_entry);
+ off += mem->size;
+
if (next_token(ctx)->kind != TK_SEMICOLON) {
tok_error(&ctx->tok, "expected \";\" after struct member name\n");
- return true;
+ error = true;
+ break;
}
next_token(ctx);
}
- typ->size = off;
+
+ /* Free hashmap data if error occurred */
+ if (error) {
+ free_all(&typ->members);
+ free(typ->members.rows);
+ return false;
+ }
next_token(ctx);
+ typ->size = off;
return true;
}
@@ -243,13 +291,6 @@ parse_type(struct parser *ctx)
return;
}
- if (ctx->tok.kind != TK_SEMICOLON) {
- tok_error(&ctx->tok, "expected \";\" after type definition\n");
- free(typ);
- return;
- }
- next_token(ctx);
-
/* Add type to parser's registry */
hashmap_add(ctx->types, &typ->hashmap_entry);
}