implemented enum parsing

This commit is contained in:
Lorenzo Torres 2025-12-03 13:08:42 +01:00
parent c34bea6fff
commit 5902ec8dbc
4 changed files with 113 additions and 2 deletions

8
lc.c
View file

@ -150,6 +150,14 @@ void print_ast(ast_node *node, int depth) {
m = m->next; m = m->next;
} }
break; break;
case NODE_ENUM:
printf("Enum: %.*s\n", (int)node->expr.enm.name_len, node->expr.enm.name);
variant *v = node->expr.enm.variants;
while (v) {
printf("\t%.*s\n", (int)v->name_len, v->name);
v = v->next;
}
break;
case NODE_IF: case NODE_IF:
printf("If:\n"); printf("If:\n");
print_ast(node->expr.whle.condition, depth + 1); print_ast(node->expr.whle.condition, depth + 1);

View file

@ -727,6 +727,91 @@ static member *parse_member(parser *p)
return m; return m;
} }
static variant *parse_variant(parser *p)
{
if (!match_peek(p, TOKEN_IDENTIFIER)) {
error(p, "expected identifier.");
return NULL;
}
variant *v = arena_alloc(p->allocator, sizeof(variant));
v->name = peek(p)->lexeme;
v->name_len = peek(p)->lexeme_len;
advance(p);
if (match(p, TOKEN_EQ)) {
v->value = parse_factor(p);
if (!v->value) {
error(p, "expected integer.");
return NULL;
}
if (v->value->type != NODE_INTEGER) {
error(p, "expected integer.");
return NULL;
}
}
return v;
}
static ast_node *parse_enum(parser *p)
{
ast_node *enm = arena_alloc(p->allocator, sizeof(ast_node));
enm->type = NODE_ENUM;
if (match_peek(p, TOKEN_IDENTIFIER)) {
/* Named enum */
enm->expr.enm.name = peek(p)->lexeme;
enm->expr.enm.name_len = peek(p)->lexeme_len;
advance(p);
} else if (!match_peek(p, TOKEN_LCURLY)) {
error(p, "expected identifier or `{`.");
return NULL;
} else {
enm->expr.enm.name = NULL;
enm->expr.enm.name_len = 0;
}
if (!match(p, TOKEN_LCURLY)) {
error(p, "expected `{`.");
return NULL;
}
variant *prev = parse_variant(p);
variant *head = prev;
enm->expr.enm.variants = head;
if (!prev) {
error(p, "invalid enum definition. Enums should contain at least 1 variant.");
return NULL;
}
if (!match(p, TOKEN_COMMA)) {
if (!match(p, TOKEN_RCURLY)) {
error(p, "expected `,`.");
return NULL;
} else {
return enm;
}
}
while (!match(p, TOKEN_RCURLY)) {
variant *current = parse_variant(p);
if (!current) {
error(p, "expected variant 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 enm;
}
static ast_node *parse_struct(parser *p) static ast_node *parse_struct(parser *p)
{ {
ast_node *structure = arena_alloc(p->allocator, sizeof(ast_node)); ast_node *structure = arena_alloc(p->allocator, sizeof(ast_node));
@ -917,6 +1002,10 @@ static ast_node *parse_statement(parser *p)
{ {
return parse_struct(p); return parse_struct(p);
} }
else if (match(p, TOKEN_ENUM))
{
return parse_enum(p);
}
else if (match(p, TOKEN_UNION)) else if (match(p, TOKEN_UNION))
{ {
ast_node *u = parse_struct(p); ast_node *u = parse_struct(p);

View file

@ -64,6 +64,13 @@ typedef struct {
member *params; member *params;
} function; } function;
typedef struct _variant {
struct _ast_node *value;
char *name;
usize name_len;
struct _variant *next;
} variant;
typedef enum { typedef enum {
NODE_IDENTIFIER, NODE_IDENTIFIER,
NODE_INTEGER, NODE_INTEGER,
@ -184,6 +191,11 @@ typedef struct _ast_node {
char *name; char *name;
usize name_len; usize name_len;
} structure; } structure;
struct {
variant *variants;
char *name;
usize name_len;
} enm; // enum
} expr; } expr;
} ast_node; } ast_node;

6
test.c
View file

@ -1,3 +1,5 @@
if a == x { enum {
printf("hello"); a = 3,
b,
c
} }