diff --git a/lc.c b/lc.c index 24c098f..10abe3e 100644 --- a/lc.c +++ b/lc.c @@ -108,6 +108,14 @@ void print_ast(ast_node *node, int depth) { current = current->expr.unit_node.next; } 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: printf("IfStmt (Fields missing in struct)\n"); break; diff --git a/parser.c b/parser.c index 673e843..05ecb78 100644 --- a/parser.c +++ b/parser.c @@ -82,6 +82,74 @@ static void error(parser *p, char *msg) 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. */ static ast_node *parse_factor(parser *p) { @@ -96,7 +164,12 @@ static ast_node *parse_factor(parser *p) node->type = NODE_FLOAT; node->expr.flt = parse_float(t->lexeme, t->lexeme_len); 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)); node->type = NODE_IDENTIFIER; node->expr.string.start = t->lexeme; diff --git a/parser.h b/parser.h index a34e3bc..cecc20c 100644 --- a/parser.h +++ b/parser.h @@ -52,7 +52,6 @@ typedef struct { usize type_len; char *name; usize name_len; - usize offset; } member; typedef struct { @@ -68,12 +67,12 @@ typedef enum { NODE_STRING, NODE_CHAR, NODE_CAST, + NODE_UNARY, + NODE_BINARY, NODE_ARRAY_SUBSCRIPT, NODE_ACCESS, NODE_CALL, NODE_POSTFIX, - NODE_UNARY, - NODE_BINARY, NODE_GOTO, NODE_BREAK, NODE_CASE, @@ -84,7 +83,6 @@ typedef enum { NODE_IF, NODE_RETURN, NODE_COMPOUND, - NODE_TYPEDEF, NODE_ENUM, NODE_STRUCT, NODE_UNION, @@ -137,6 +135,13 @@ typedef struct _ast_node { struct _ast_node *expr; struct _ast_node *next; } 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; } ast_node; diff --git a/test.c b/test.c index 7bde329..116c235 100644 --- a/test.c +++ b/test.c @@ -1 +1 @@ -x.y +x(4, 5) diff --git a/utils.c b/utils.c index c8ee4ed..05b0b1b 100644 --- a/utils.c +++ b/utils.c @@ -97,9 +97,9 @@ void *arena_alloc(arena *a, usize size) { 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) diff --git a/utils.h b/utils.h index 6eac1de..7392d46 100644 --- a/utils.h +++ b/utils.h @@ -43,7 +43,7 @@ arena arena_init(usize size); * does not have enough memory to allocate the requested space */ 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(arena *a); /* This call should never fail, also, do we even care if it does? */