implemented call expression parsing

This commit is contained in:
Lorenzo Torres 2025-12-01 13:00:07 +01:00
parent d1b89939ae
commit 37356facc2
6 changed files with 95 additions and 9 deletions

8
lc.c
View file

@ -108,6 +108,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_CALL:
printf("Call: %.*s\n", (int)node->expr.call.name_len, node->expr.call.name);
current = node->expr.call.parameters;
while (current && current->type == NODE_UNIT) {
print_ast(current->expr.unit_node.expr, depth + 1);
current = current->expr.unit_node.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

@ -82,6 +82,74 @@ static void error(parser *p, char *msg)
parser_sync(p); parser_sync(p);
} }
static ast_node *parse_call(parser *p)
{
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
node->type = NODE_CALL;
node->expr.call.name = peek(p)->lexeme;
node->expr.call.name_len = peek(p)->lexeme_len;
advance(p);
/* Skip also the opening `(` */
advance(p);
/* Call without parameters */
if (match(p, TOKEN_RPAREN)) {
node->expr.call.parameters = NULL;
return node;
}
snapshot arena_start = arena_snapshot(p->allocator);
node->expr.call.parameters = arena_alloc(p->allocator, sizeof(ast_node));
node->expr.call.parameters->type = NODE_UNIT;
node->expr.call.parameters->expr.unit_node.expr = parse_expression(p);
ast_node *tail = node->expr.call.parameters;
node->expr.call.param_len = 1;
/* In this case, there is only one parameter */
if (match(p, TOKEN_RPAREN)) {
return node;
}
if (match(p, TOKEN_COMMA)) {
ast_node *expr = parse_expression(p);
if (expr) {
while (!match(p, TOKEN_RPAREN)) {
if (!match(p, TOKEN_COMMA)) {
error(p, "expected `)`.");
arena_reset_to_snapshot(p->allocator, arena_start);
return NULL;
}
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
tail->expr.unit_node.next->expr.unit_node.expr = expr;
tail = tail->expr.unit_node.next;
tail->type = NODE_UNIT;
expr = parse_expression(p);
if (!expr) {
error(p, "expected `)`.");
arena_reset_to_snapshot(p->allocator, arena_start);
return NULL;
}
node->expr.call.param_len += 1;
}
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
tail->expr.unit_node.next->expr.unit_node.expr = expr;
tail = tail->expr.unit_node.next;
tail->type = NODE_UNIT;
} else {
error(p, "expected expression.");
arena_reset_to_snapshot(p->allocator, arena_start);
return NULL;
}
} else {
error(p, "expected `)`.");
arena_reset_to_snapshot(p->allocator, arena_start);
return NULL;
}
return node;
}
/* Parse expressions with the highest precedence. */ /* Parse expressions with the highest precedence. */
static ast_node *parse_factor(parser *p) static ast_node *parse_factor(parser *p)
{ {
@ -96,7 +164,12 @@ static ast_node *parse_factor(parser *p)
node->type = NODE_FLOAT; node->type = NODE_FLOAT;
node->expr.flt = parse_float(t->lexeme, t->lexeme_len); node->expr.flt = parse_float(t->lexeme, t->lexeme_len);
return node; return node;
} else if (match(p, TOKEN_IDENTIFIER)) { } else if (match_peek(p, TOKEN_IDENTIFIER)) {
/* If a `(` is found after an identifier, it should be a call. */
if (p->tokens->next && p->tokens->next->type == TOKEN_LPAREN) {
return parse_call(p);
}
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node)); ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
node->type = NODE_IDENTIFIER; node->type = NODE_IDENTIFIER;
node->expr.string.start = t->lexeme; node->expr.string.start = t->lexeme;

View file

@ -52,7 +52,6 @@ typedef struct {
usize type_len; usize type_len;
char *name; char *name;
usize name_len; usize name_len;
usize offset;
} member; } member;
typedef struct { typedef struct {
@ -68,12 +67,12 @@ typedef enum {
NODE_STRING, NODE_STRING,
NODE_CHAR, NODE_CHAR,
NODE_CAST, NODE_CAST,
NODE_UNARY,
NODE_BINARY,
NODE_ARRAY_SUBSCRIPT, NODE_ARRAY_SUBSCRIPT,
NODE_ACCESS, NODE_ACCESS,
NODE_CALL, NODE_CALL,
NODE_POSTFIX, NODE_POSTFIX,
NODE_UNARY,
NODE_BINARY,
NODE_GOTO, NODE_GOTO,
NODE_BREAK, NODE_BREAK,
NODE_CASE, NODE_CASE,
@ -84,7 +83,6 @@ typedef enum {
NODE_IF, NODE_IF,
NODE_RETURN, NODE_RETURN,
NODE_COMPOUND, NODE_COMPOUND,
NODE_TYPEDEF,
NODE_ENUM, NODE_ENUM,
NODE_STRUCT, NODE_STRUCT,
NODE_UNION, NODE_UNION,
@ -137,6 +135,13 @@ typedef struct _ast_node {
struct _ast_node *expr; struct _ast_node *expr;
struct _ast_node *next; struct _ast_node *next;
} unit_node; } unit_node;
struct {
/* This should be a list of unit_node */
struct _ast_node *parameters;
usize param_len;
char *name;
usize name_len;
} call;
} expr; } expr;
} ast_node; } ast_node;

2
test.c
View file

@ -1 +1 @@
x.y x(4, 5)

View file

@ -97,9 +97,9 @@ void *arena_alloc(arena *a, usize size) {
return ret; return ret;
} }
snapshot arena_snapshot(arena a) snapshot arena_snapshot(arena *a)
{ {
return a.position; return a->position;
} }
void arena_reset_to_snapshot(arena *a, snapshot s) void arena_reset_to_snapshot(arena *a, snapshot s)

View file

@ -43,7 +43,7 @@ arena arena_init(usize size);
* does not have enough memory to allocate the requested space * does not have enough memory to allocate the requested space
*/ */
void *arena_alloc(arena *a, usize size); void *arena_alloc(arena *a, usize size);
snapshot arena_snapshot(arena a); snapshot arena_snapshot(arena *a);
void arena_reset_to_snapshot(arena *a, snapshot s); void arena_reset_to_snapshot(arena *a, snapshot s);
void arena_reset(arena *a); void arena_reset(arena *a);
/* This call should never fail, also, do we even care if it does? */ /* This call should never fail, also, do we even care if it does? */