From 6ab9c3732793b6fd40e6388cf1b08756194c0ea6 Mon Sep 17 00:00:00 2001 From: Quinn Stephens Date: Thu, 7 Nov 2024 16:59:19 -0500 Subject: [compiler] Parse return statements Laid groundwork for statements and AST trees. Currently return values are not supported, expression parsing must be implemented first. Also stopped dumping parsed type definitions. Signed-off-by: Quinn Stephens --- compiler/lexer/keywords.c | 1 + compiler/main.c | 97 +++++++++++------------------------------------ compiler/parser/proc.c | 22 ++++++----- compiler/parser/stmt.c | 62 ++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 83 deletions(-) create mode 100644 compiler/parser/stmt.c (limited to 'compiler') diff --git a/compiler/lexer/keywords.c b/compiler/lexer/keywords.c index 88c2e67..dbae881 100644 --- a/compiler/lexer/keywords.c +++ b/compiler/lexer/keywords.c @@ -69,6 +69,7 @@ keywords_init(void) add_keyword("type", TK_TYPE); add_keyword("enum", TK_ENUM); add_keyword("struct", TK_STRUCT); + add_keyword("ret", TK_RET); initialized = true; } diff --git a/compiler/main.c b/compiler/main.c index e614be6..aa3bcdc 100644 --- a/compiler/main.c +++ b/compiler/main.c @@ -183,69 +183,31 @@ print_ptrs(int n_ptrs) } static void -print_alias(struct type *typ) +print_ret(struct ast_node *node) { - printf("alias (%lu bytes, %d pointer(s));\n", typ->size, typ->n_ptrs); -} - -static void -print_enum(struct type *typ) -{ - struct enum_member *mem; + (void)node; - printf("enum {\n"); - - for (size_t r = 0; r < typ->members.n_rows; r++) { - mem = (struct enum_member*)typ->members.rows[r].head; - while (mem != (struct enum_member*)&typ->members.rows[r]) { - printf(" %.*s,\n", (int)mem->name_len, mem->name); - - mem = (struct enum_member*)mem->hashmap_entry.list_entry.next; - } - } - - printf("}\n"); + /* TODO: Print return value */ + printf(" ret;\n"); } static void -print_struct(struct type *typ) +print_stmt_block(struct ast_node *parent) { - struct struct_member *mem; - - printf("struct (%lu bytes) {\n", typ->size); - - for (size_t r = 0; r < typ->members.n_rows; r++) { - mem = (struct struct_member*)typ->members.rows[r].head; - while (mem != (struct struct_member*)&typ->members.rows[r]) { - printf(" %.*s ", (int)mem->typ->name_len, mem->typ->name); - print_ptrs(mem->n_ptrs); - printf("%.*s;\n", (int)mem->name_len, mem->name); - - mem = (struct struct_member*)mem->hashmap_entry.list_entry.next; + struct ast_node *node; + + node = (struct ast_node*)parent->children.head; + while (node != (struct ast_node*)&parent->children) { + switch (node->kind) { + case NK_RETURN: + print_ret(node); + break; + default: + printf(" /* Unknown */\n"); + break; } - } - - printf("}\n"); -} -static void -print_type(struct type *typ) -{ - printf("type %.*s: ", (int)typ->name_len, typ->name); - - switch (typ->kind) { - case TYK_ALIAS: - print_alias(typ); - break; - case TYK_ENUM: - print_enum(typ); - break; - case TYK_STRUCT: - print_struct(typ); - break; - default: - printf("unknown;\n"); - break; + node = (struct ast_node*)node->list_entry.next; } } @@ -281,26 +243,14 @@ print_proc(struct procedure *proc) print_ptrs(proc->ret_n_ptrs); } - printf(";\n"); -} - -static void -dump_types(struct hashmap *map) -{ - struct type *typ, *next; - - for (size_t r = 0; r < map->n_rows; r++) { - typ = (struct type*)map->rows[r].head; - while (typ != (struct type*)&map->rows[r]) { - print_type(typ); - - next = (struct type*)typ->hashmap_entry.list_entry.next; - free(typ); - typ = next; - } + if (list_is_empty(&proc->node->children)) { + printf(";\n"); + return; } - free(map->rows); + printf(" {\n"); + print_stmt_block(proc->node); + printf("}\n"); } static void @@ -362,7 +312,6 @@ main(int argc, char **argv) parser_init(&parser, input); parser_parse(&parser); - dump_types(parser.types); dump_procs(parser.procs); free(input); diff --git a/compiler/parser/proc.c b/compiler/parser/proc.c index bbbdad1..b32f5e9 100644 --- a/compiler/parser/proc.c +++ b/compiler/parser/proc.c @@ -7,6 +7,7 @@ #include #include "debug.h" #include "parser/proc.h" +#include "parser/stmt.h" #include "parser/type.h" #include "parser.h" @@ -119,26 +120,29 @@ parse_proc(struct parser *ctx) } } - /* Add procedure to parser's registry */ - hashmap_add(ctx->procs, &proc->hashmap_entry); - /* We are finished now if this is just a declaration */ if (ctx->tok.kind == TK_SEMICOLON) { + proc->node = NULL; + + /* Add procedure to parser's registry */ + hashmap_add(ctx->procs, &proc->hashmap_entry); + next_token(ctx); return; } if (ctx->tok.kind != TK_LBRACE) { + proc->node = NULL; tok_error(&ctx->tok, "Expected \";\" or \"{\"\n"); return; } - /* TODO: Parse body/code */ + /* Allocate AST root node for body */ + proc->node = ast_new_node(NK_PROCEDURE); - if (next_token(ctx)->kind != TK_RBRACE) { - tok_error(&ctx->tok, "Expected \"}\" after procedure body\n"); - return; - } + /* Parse procedure body (code) */ + parse_stmt_block(ctx, proc->node, proc); - next_token(ctx); + /* Add procedure to parser's registry */ + hashmap_add(ctx->procs, &proc->hashmap_entry); } diff --git a/compiler/parser/stmt.c b/compiler/parser/stmt.c new file mode 100644 index 0000000..6fe3d6d --- /dev/null +++ b/compiler/parser/stmt.c @@ -0,0 +1,62 @@ +/* + * Statement parser. + * Copyright (c) 2023-2024, Quinn Stephens and the OSMORA team. + * Provided under the BSD 3-Clause license. + */ + +#include +#include "debug.h" +#include "parser/ast.h" +#include "parser/stmt.h" +#include "parser/proc.h" +#include "parser.h" + +static bool +parse_ret(struct parser *ctx, struct ast_node *parent, struct procedure *proc) +{ + struct ast_node *node; + + (void)proc; + + debug("Parsing return statement...\n"); + + /* TODO: Parse return value */ + next_token(ctx); + + if (ctx->tok.kind != TK_SEMICOLON) { + tok_error(&ctx->tok, "Expected \";\"\n"); + return false; + } + next_token(ctx); + + node = ast_new_node(NK_RETURN); + ast_append_child(parent, node); + + return true; +} + +void +parse_stmt_block(struct parser *ctx, struct ast_node *parent, struct procedure *proc) +{ + bool success; + + debug("Parsing statement block...\n"); + + next_token(ctx); + while (ctx->tok.kind != TK_RBRACE) { + switch (ctx->tok.kind) { + case TK_RET: + success = parse_ret(ctx, parent, proc); + break; + default: + tok_error(&ctx->tok, "Expected statement\n"); + success = false; + break; + } + + if (!success) { + return; + } + } + next_token(ctx); +} -- cgit v1.2.3