implemented structure parsing

This commit is contained in:
Lorenzo Torres 2025-12-03 09:59:09 +01:00
parent d0d750f059
commit 664affc6d3
4 changed files with 119 additions and 4 deletions

8
lc.c
View file

@ -134,6 +134,14 @@ void print_ast(ast_node *node, int depth) {
current = current->expr.unit_node.next; current = current->expr.unit_node.next;
} }
break; 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: case NODE_IF:
printf("IfStmt (Fields missing in struct)\n"); printf("IfStmt (Fields missing in struct)\n");
break; break;

View file

@ -676,6 +676,99 @@ static ast_node *parse_while(parser *p)
return node; 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) static ast_node *parse_statement(parser *p)
{ {
if (match(p, TOKEN_BREAK)) if (match(p, TOKEN_BREAK))
@ -802,6 +895,10 @@ static ast_node *parse_statement(parser *p)
return node; return node;
} }
else if (match(p, TOKEN_STRUCT))
{
return parse_struct(p);
}
else else
{ {
ast_node *expr = parse_expression(p); ast_node *expr = parse_expression(p);

View file

@ -4,6 +4,8 @@
#include "lexer.h" #include "lexer.h"
#include "utils.h" #include "utils.h"
struct _ast_node;
typedef enum { typedef enum {
OP_PLUS, // + OP_PLUS, // +
OP_MINUS, // - OP_MINUS, // -
@ -49,11 +51,11 @@ typedef enum {
LAYOUT_EXTERN LAYOUT_EXTERN
} struct_layout; } struct_layout;
typedef struct { typedef struct _member {
char *type_name; struct _ast_node *type;
usize type_len;
char *name; char *name;
usize name_len; usize name_len;
struct _member *next;
} member; } member;
typedef struct { typedef struct {
@ -177,6 +179,11 @@ typedef struct _ast_node {
char *type; char *type;
usize type_len; usize type_len;
} var_decl; } var_decl;
struct {
member *members;
char *name;
usize name_len;
} structure;
} expr; } expr;
} ast_node; } ast_node;

5
test.c
View file

@ -1 +1,4 @@
u32 a = 3; struct {
struct { u32 x, u32 y } a,
u32 b,
}