From 664affc6d36506cc1ad0d2af53f918e8a0d79525 Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Wed, 3 Dec 2025 09:59:09 +0100 Subject: [PATCH] implemented structure parsing --- lc.c | 8 +++++ parser.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.h | 13 ++++++-- test.c | 5 ++- 4 files changed, 119 insertions(+), 4 deletions(-) diff --git a/lc.c b/lc.c index 5557c7a..b643372 100644 --- a/lc.c +++ b/lc.c @@ -134,6 +134,14 @@ void print_ast(ast_node *node, int depth) { current = current->expr.unit_node.next; } break; + case NODE_STRUCT: + printf("Struct: %.*s\n", (int)node->expr.structure.name_len, node->expr.structure.name); + member *m = node->expr.structure.members; + while (m) { + print_ast(m->type, depth + 1); + m = m->next; + } + break; case NODE_IF: printf("IfStmt (Fields missing in struct)\n"); break; diff --git a/parser.c b/parser.c index 3d4b247..660c86e 100644 --- a/parser.c +++ b/parser.c @@ -676,6 +676,99 @@ static ast_node *parse_while(parser *p) return node; } +static ast_node *parse_struct(parser *p); +static member *parse_member(parser *p) +{ + ast_node *type = NULL; + + if (match(p, TOKEN_STRUCT)) { + type = parse_struct(p); + } + if (!type) { + type = parse_factor(p); + if (!type) { + error(p, "expected struct definition or identifier."); + return NULL; + } + if (type->type != NODE_IDENTIFIER) { + error(p, "expected struct definition or identifier."); + return NULL; + } + } + + + if (!match_peek(p, TOKEN_IDENTIFIER)) { + error(p, "expected identifier."); + return NULL; + } + + member *m = arena_alloc(p->allocator, sizeof(member)); + m->type = type; + m->name = peek(p)->lexeme; + m->name_len = peek(p)->lexeme_len; + advance(p); + + + return m; +} + +static ast_node *parse_struct(parser *p) +{ + ast_node *structure = arena_alloc(p->allocator, sizeof(ast_node)); + structure->type = NODE_STRUCT; + if (match_peek(p, TOKEN_IDENTIFIER)) { + /* Named structure */ + structure->expr.structure.name = peek(p)->lexeme; + structure->expr.structure.name_len = peek(p)->lexeme_len; + advance(p); + } else if (!match_peek(p, TOKEN_LCURLY)) { + error(p, "expected identifier or `{`."); + return NULL; + } else { + structure->expr.structure.name = NULL; + structure->expr.structure.name_len = 0; + } + + if (!match(p, TOKEN_LCURLY)) { + error(p, "expected `{`."); + return NULL; + } + + member *prev = parse_member(p); + member *head = prev; + structure->expr.structure.members = head; + if (!prev) { + error(p, "invalid struct definition. Structs should contain at least 1 member."); + return NULL; + } + if (!match(p, TOKEN_COMMA)) { + if (!match(p, TOKEN_RCURLY)) { + error(p, "expected `,`."); + return NULL; + } else { + return structure; + } + } + while (!match(p, TOKEN_RCURLY)) { + member *current = parse_member(p); + if (!current) { + error(p, "expected member definition."); + return NULL; + } + prev->next = current; + if (!match(p, TOKEN_COMMA)) { + if (!match_peek(p, TOKEN_RCURLY)) { + error(p, "expected `,`."); + return NULL; + } + } + + prev = current; + } + + return structure; +} + static ast_node *parse_statement(parser *p) { if (match(p, TOKEN_BREAK)) @@ -802,6 +895,10 @@ static ast_node *parse_statement(parser *p) return node; } + else if (match(p, TOKEN_STRUCT)) + { + return parse_struct(p); + } else { ast_node *expr = parse_expression(p); diff --git a/parser.h b/parser.h index 57068e7..2fa02b8 100644 --- a/parser.h +++ b/parser.h @@ -4,6 +4,8 @@ #include "lexer.h" #include "utils.h" +struct _ast_node; + typedef enum { OP_PLUS, // + OP_MINUS, // - @@ -49,11 +51,11 @@ typedef enum { LAYOUT_EXTERN } struct_layout; -typedef struct { - char *type_name; - usize type_len; +typedef struct _member { + struct _ast_node *type; char *name; usize name_len; + struct _member *next; } member; typedef struct { @@ -177,6 +179,11 @@ typedef struct _ast_node { char *type; usize type_len; } var_decl; + struct { + member *members; + char *name; + usize name_len; + } structure; } expr; } ast_node; diff --git a/test.c b/test.c index 0064f08..544384a 100644 --- a/test.c +++ b/test.c @@ -1 +1,4 @@ -u32 a = 3; +struct { + struct { u32 x, u32 y } a, + u32 b, +}