aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-31 19:58:56 +0200
committerhachem <im@hachem.wtf>2026-08-31 19:58:56 +0200
commit5b06b0e4b8effaacd23308d6a6b26c525e7d3af4 (patch)
tree351155777028e604845d3dfec27d3caf3b22257f /src/parser
parentcbdb9073480c3e4d8a088b306c23406cf42e25c0 (diff)
feat: add enums and structs
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c90
-rw-r--r--src/parser/ast.h54
-rw-r--r--src/parser/parser.c96
3 files changed, 232 insertions, 8 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
index 704e9a4..f8bd9cc 100644
--- a/src/parser/ast.c
+++ b/src/parser/ast.c
@@ -70,6 +70,12 @@ struct Program create_program(void)
program.data_decls = NULL;
program.data_count = 0;
program.data_capacity = 0;
+ program.enums = NULL;
+ program.enum_count = 0;
+ program.enum_capacity = 0;
+ program.structs = NULL;
+ program.struct_count = 0;
+ program.struct_capacity = 0;
program.procs = NULL;
program.proc_count = 0;
program.proc_capacity = 0;
@@ -83,6 +89,14 @@ void free_program(struct Program* program)
free(program->consts);
free(program->data_decls);
+ for (size_t i = 0; i < program->enum_count; i += 1)
+ free(program->enums[i].members);
+ free(program->enums);
+
+ for (size_t i = 0; i < program->struct_count; i += 1)
+ free(program->structs[i].fields);
+ free(program->structs);
+
for (size_t i = 0; i < program->proc_count; i += 1)
free_proc(&program->procs[i]);
free(program->procs);
@@ -93,6 +107,12 @@ void free_program(struct Program* program)
program->data_decls = NULL;
program->data_count = 0;
program->data_capacity = 0;
+ program->enums = NULL;
+ program->enum_count = 0;
+ program->enum_capacity = 0;
+ program->structs = NULL;
+ program->struct_count = 0;
+ program->struct_capacity = 0;
program->procs = NULL;
program->proc_count = 0;
program->proc_capacity = 0;
@@ -125,6 +145,76 @@ void add_data(struct Program* program, struct DataDecl decl)
program->data_count += 1;
}
+struct EnumDecl create_enum(void)
+{
+ struct EnumDecl decl;
+ decl.members = NULL;
+ decl.member_count = 0;
+ decl.member_capacity = 0;
+ return decl;
+}
+
+void add_enum_member(struct EnumDecl* decl, struct Token member)
+{
+ if (decl->member_count == decl->member_capacity)
+ {
+ size_t capacity = decl->member_capacity < 8 ? 8 : decl->member_capacity * 2;
+ decl->members = realloc(decl->members, capacity * sizeof(struct Token));
+ decl->member_capacity = capacity;
+ }
+
+ decl->members[decl->member_count] = member;
+ decl->member_count += 1;
+}
+
+void add_enum(struct Program* program, struct EnumDecl decl)
+{
+ if (program->enum_count == program->enum_capacity)
+ {
+ size_t capacity = program->enum_capacity < 8 ? 8 : program->enum_capacity * 2;
+ program->enums = realloc(program->enums, capacity * sizeof(struct EnumDecl));
+ program->enum_capacity = capacity;
+ }
+
+ program->enums[program->enum_count] = decl;
+ program->enum_count += 1;
+}
+
+struct StructDecl create_struct(void)
+{
+ struct StructDecl decl;
+ decl.fields = NULL;
+ decl.field_count = 0;
+ decl.field_capacity = 0;
+ return decl;
+}
+
+void add_struct_field(struct StructDecl* decl, struct StructField field)
+{
+ if (decl->field_count == decl->field_capacity)
+ {
+ size_t capacity = decl->field_capacity < 8 ? 8 : decl->field_capacity * 2;
+ decl->fields = realloc(decl->fields, capacity * sizeof(struct StructField));
+ decl->field_capacity = capacity;
+ }
+
+ decl->fields[decl->field_count] = field;
+ decl->field_count += 1;
+}
+
+void add_struct(struct Program* program, struct StructDecl decl)
+{
+ if (program->struct_count == program->struct_capacity)
+ {
+ size_t capacity = program->struct_capacity < 8 ? 8 : program->struct_capacity * 2;
+ program->structs = realloc(program->structs, capacity * sizeof(struct StructDecl));
+ program->struct_capacity = capacity;
+ }
+
+ program->structs[program->struct_count] = decl;
+ program->struct_count += 1;
+}
+
struct ProcDecl create_proc(void)
{
struct ProcDecl proc;
diff --git a/src/parser/ast.h b/src/parser/ast.h
index 98e8dea..b114fb1 100644
--- a/src/parser/ast.h
+++ b/src/parser/ast.h
@@ -6,6 +6,15 @@
#include "lexer/lexer.h"
+enum StoreSize
+{
+ STORE_SIZE_NONE,
+ STORE_SIZE_BYTE,
+ STORE_SIZE_WORD,
+ STORE_SIZE_DWORD,
+ STORE_SIZE_QWORD,
+};
+
struct ConstDecl
{
struct Token name;
@@ -18,19 +27,32 @@ struct DataDecl
struct Token value;
};
-struct Param
+struct EnumDecl
{
struct Token name;
- struct Token reg;
+ struct Token* members;
+ size_t member_count;
+ size_t member_capacity;
};
-enum StoreSize
+struct StructField
{
- STORE_SIZE_NONE,
- STORE_SIZE_BYTE,
- STORE_SIZE_WORD,
- STORE_SIZE_DWORD,
- STORE_SIZE_QWORD,
+ struct Token name;
+ enum StoreSize size;
+};
+
+struct StructDecl
+{
+ struct Token name;
+ struct StructField* fields;
+ size_t field_count;
+ size_t field_capacity;
+};
+
+struct Param
+{
+ struct Token name;
+ struct Token reg;
};
enum ExprKind
@@ -175,6 +197,14 @@ struct Program
size_t data_count;
size_t data_capacity;
+ struct EnumDecl* enums;
+ size_t enum_count;
+ size_t enum_capacity;
+
+ struct StructDecl* structs;
+ size_t struct_count;
+ size_t struct_capacity;
+
struct ProcDecl* procs;
size_t proc_count;
size_t proc_capacity;
@@ -185,6 +215,14 @@ void free_program(struct Program* program);
void add_const(struct Program* program, struct ConstDecl decl);
void add_data(struct Program* program, struct DataDecl decl);
+struct EnumDecl create_enum(void);
+void add_enum_member(struct EnumDecl* decl, struct Token member);
+void add_enum(struct Program* program, struct EnumDecl decl);
+
+struct StructDecl create_struct(void);
+void add_struct_field(struct StructDecl* decl, struct StructField field);
+void add_struct(struct Program* program, struct StructDecl decl);
+
struct ProcDecl create_proc(void);
void free_proc(struct ProcDecl* proc);
void add_param(struct ProcDecl* proc, struct Param param);
diff --git a/src/parser/parser.c b/src/parser/parser.c
index 87dedbd..682e193 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -53,6 +53,7 @@ static bool consume(struct Parser* parser, enum TokenType type, const char* mess
}
static struct Expr* parse_expression(struct Parser* parser);
+static enum StoreSize parse_store_size(struct Parser* parser);
static bool parse_const(struct Parser* parser, struct Program* program)
{
@@ -92,6 +93,89 @@ static bool parse_data(struct Parser* parser, struct Program* program)
return true;
}
+static bool parse_enum(struct Parser* parser, struct Program* program)
+{
+ struct EnumDecl decl = create_enum();
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected enum name after 'enum'"))
+ goto error;
+ decl.name = parser->previous;
+
+ if (!consume(parser, TOKEN_LEFT_BRACE, "expected '{' after enum name"))
+ goto error;
+
+ while (!check(parser, TOKEN_RIGHT_BRACE))
+ {
+ if (check(parser, TOKEN_EOF))
+ {
+ error_at(parser, parser->current, "unterminated enum");
+ goto error;
+ }
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected an enum member name"))
+ goto error;
+ add_enum_member(&decl, parser->previous);
+
+ match_token(parser, TOKEN_COMMA);
+ }
+ advance_parser(parser);
+
+ add_enum(program, decl);
+ return true;
+
+error:
+ free(decl.members);
+ return false;
+}
+
+static bool parse_struct(struct Parser* parser, struct Program* program)
+{
+ struct StructDecl decl = create_struct();
+
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected struct name after 'struct'"))
+ goto error;
+ decl.name = parser->previous;
+
+ if (!consume(parser, TOKEN_LEFT_BRACE, "expected '{' after struct name"))
+ goto error;
+
+ while (!check(parser, TOKEN_RIGHT_BRACE))
+ {
+ if (check(parser, TOKEN_EOF))
+ {
+ error_at(parser, parser->current, "unterminated struct");
+ goto error;
+ }
+
+ struct StructField field;
+ if (!consume(parser, TOKEN_IDENTIFIER, "expected a field name"))
+ goto error;
+ field.name = parser->previous;
+
+ field.size = STORE_SIZE_QWORD;
+ if (match_token(parser, TOKEN_COLON))
+ {
+ field.size = parse_store_size(parser);
+ if (field.size == STORE_SIZE_NONE)
+ {
+ error_at(parser, parser->current, "expected a size (byte, word, dword, qword) after ':'");
+ goto error;
+ }
+ }
+
+ add_struct_field(&decl, field);
+ match_token(parser, TOKEN_COMMA);
+ }
+ advance_parser(parser);
+
+ add_struct(program, decl);
+ return true;
+
+error:
+ free(decl.fields);
+ return false;
+}
+
static bool parse_params(struct Parser* parser, struct ProcDecl* proc)
{
if (check(parser, TOKEN_RIGHT_PAREN))
@@ -555,6 +639,18 @@ bool parse_program(struct Lexer* lexer, struct Program* out)
if (!parse_data(&parser, out))
return false;
}
+ else if (check(&parser, TOKEN_ENUM))
+ {
+ advance_parser(&parser);
+ if (!parse_enum(&parser, out))
+ return false;
+ }
+ else if (check(&parser, TOKEN_STRUCT))
+ {
+ advance_parser(&parser);
+ if (!parse_struct(&parser, out))
+ return false;
+ }
else if (check(&parser, TOKEN_PROC))
{
advance_parser(&parser);