diff --git a/.gitignore b/.gitignore index 41e5a9d..4a5f0fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/*.o **/*~ lc +*.swp diff --git a/lc.c b/lc.c index 529abad..7125d91 100644 --- a/lc.c +++ b/lc.c @@ -168,7 +168,13 @@ void print_ast(ast_node *node, int depth) { print_ast(node->expr.var_decl.value, depth + 1); break; case NODE_FUNCTION: - printf("FunctionDef (Fields missing in struct)\n"); + printf("Function: %.*s\n", (int)node->expr.function.name_len, node->expr.function.name); + m = node->expr.function.parameters; + while (m) { + print_ast(m->type, depth + 1); + m = m->next; + } + print_ast(node->expr.function.body, depth + 1); break; case NODE_RETURN: printf("Return:\n"); @@ -203,7 +209,7 @@ void print_ast(ast_node *node, int depth) { int main(void) { - FILE *fp = fopen("test.c", "r"); + FILE *fp = fopen("test.l", "r"); usize size = 0; fseek(fp, 0, SEEK_END); size = ftell(fp); diff --git a/parser.c b/parser.c index 8aba74f..e501ab7 100644 --- a/parser.c +++ b/parser.c @@ -869,6 +869,60 @@ static ast_node *parse_struct(parser *p) return structure; } +static ast_node *parse_function(parser *p) +{ + ast_node *fn = arena_alloc(p->allocator, sizeof(ast_node)); + fn->type = NODE_FUNCTION; + fn->expr.function.type = peek(p)->lexeme; + fn->expr.function.type_len = peek(p)->lexeme_len; + advance(p); + fn->expr.function.name = peek(p)->lexeme; + fn->expr.function.name_len = peek(p)->lexeme_len; + advance(p); + /* Consume `(` */ + advance(p); + + if (match(p, TOKEN_RPAREN)) { + fn->expr.function.body = parse_compound(p); + fn->expr.function.parameters = NULL; + fn->expr.function.parameters_len = 0; + return fn; + } + member *prev = parse_member(p); + member *head = prev; + fn->expr.function.parameters = head; + fn->expr.function.parameters_len = 1; + if (!match(p, TOKEN_COMMA)) { + if (!match(p, TOKEN_RPAREN)) { + error(p, "expected `,`."); + return NULL; + } else { + fn->expr.function.body = parse_compound(p); + return fn; + } + } + while (!match(p, TOKEN_RPAREN)) { + member *current = parse_member(p); + if (!current) { + error(p, "expected parameter."); + return NULL; + } + prev->next = current; + if (!match(p, TOKEN_COMMA)) { + if (!match_peek(p, TOKEN_RPAREN)) { + error(p, "expected `,`."); + return NULL; + } + } + fn->expr.function.parameters_len += 1; + + prev = current; + } + fn->expr.function.body = parse_compound(p); + + return fn; +} + static ast_node *parse_statement(parser *p) { if (match(p, TOKEN_BREAK)) @@ -993,6 +1047,10 @@ static ast_node *parse_statement(parser *p) } else if (match_peek(p, TOKEN_IDENTIFIER) && p->tokens->next && p->tokens->next->type == TOKEN_IDENTIFIER) { + if (p->tokens->next->next && p->tokens->next->next->type == TOKEN_LPAREN) { + /* Function definition. */ + return parse_function(p); + } /* Variable declaration. */ ast_node *node = arena_alloc(p->allocator, sizeof(ast_node)); node->type = NODE_VAR_DECL; diff --git a/parser.h b/parser.h index 837bf70..2b201e0 100644 --- a/parser.h +++ b/parser.h @@ -191,6 +191,15 @@ typedef struct _ast_node { char *name; usize name_len; } structure; + struct { + member *parameters; + usize parameters_len; + char *name; + usize name_len; + char *type; + usize type_len; + struct _ast_node *body; + } function; struct { variant *variants; char *name; diff --git a/test.c b/test.c deleted file mode 100644 index 99ec2a1..0000000 --- a/test.c +++ /dev/null @@ -1,7 +0,0 @@ -enum { - a = 4, - b, - c -} - -a = 3; diff --git a/test.l b/test.l new file mode 100644 index 0000000..6f87c31 --- /dev/null +++ b/test.l @@ -0,0 +1,4 @@ +u32 a(u32 a) +{ + u32 x = 3; +}