From f0621a8076ac6e23516a0d21e60cd3b805f85c6f Mon Sep 17 00:00:00 2001 From: Sebastiaan de Schaetzen Date: Wed, 29 Apr 2026 11:53:26 +0200 Subject: [PATCH] Refactor parser --- v0/parser.c | 197 +++++++++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 87 deletions(-) diff --git a/v0/parser.c b/v0/parser.c index ca97689..1f564e9 100644 --- a/v0/parser.c +++ b/v0/parser.c @@ -4,6 +4,114 @@ #include #include +/** + * Parses an import declaration. + * + * @param ts The token stream to parse from. + * @param module The module being parsed. + * @returns true on success, false on failure. + */ +static bool parse_import(TokenStream* ts, Module* module) { + ImportDeclaration* new_imports = realloc(module->imports, (module->import_count + 1) * sizeof(ImportDeclaration)); + if (!new_imports) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + module->imports = new_imports; + + Token t = tokenstream_next(ts); + bool is_public = false; + if (t.token == TOKEN_PUBLIC) { + is_public = true; + t = tokenstream_next(ts); + } + + if (t.token != TOKEN_IDENTIFIER) { + log_on_line(&t.location, t.location.column_end, "expected module name to import"); + return false; + } + + char* name = (char*)malloc(t.text.length + 1); + memcpy(name, t.text.data, t.text.length); + name[t.text.length] = '\0'; + + module->imports[module->import_count] = (ImportDeclaration){ .module_name = name, .is_public = is_public }; + module->import_count++; + + t = tokenstream_next(ts); + if (t.token != TOKEN_SEMICOLON) { + log_on_line(&t.location, t.location.column_end, "expected ';' after import"); + return false; + } + return true; +} + +/** + * Parses an alias declaration. + * + * @param ts The token stream to parse from. + * @param module The module being parsed. + * @returns true on success, false on failure. + */ +static bool parse_alias(TokenStream* ts, Module* module) { + AliasDeclaration* new_aliases = realloc(module->aliases, (module->alias_count + 1) * sizeof(AliasDeclaration)); + if (!new_aliases) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + module->aliases = new_aliases; + + Token t = tokenstream_next(ts); + if (t.token != TOKEN_IDENTIFIER) { + log_on_line(&t.location, t.location.column_end, "expected alias name"); + return false; + } + char* name = (char*)malloc(t.text.length + 1); + memcpy(name, t.text.data, t.text.length); + name[t.text.length] = '\0'; + AliasDeclaration alias; + alias.name = name; + + t = tokenstream_next(ts); + if (t.token != TOKEN_ASSIGN) { + log_on_line(&t.location, t.location.column_end, "expected '='"); + return false; + } + + t = tokenstream_next(ts); + + TypeExpression type; + if (t.token == TOKEN_IDENTIFIER && strncmp(t.text.data, "int32", t.text.length) == 0) { + type = (TypeExpression){ .tag = TYPE_EXPRESSION_BUILTIN, .builtin = { .bitSize = 32, .isSigned = true } }; + t = tokenstream_next(ts); + if (t.token == TOKEN_BRACKET_OPEN) { + t = tokenstream_next(ts); + if (t.token != TOKEN_BRACKET_CLOSE) { + log_on_line(&t.location, t.location.column_end, "expected ']'"); + return false; + } + TypeExpression* inner = malloc(sizeof(TypeExpression)); + *inner = type; + type = (TypeExpression){ .tag = TYPE_EXPRESSION_ARRAY, .array = { .array = inner } }; + t = tokenstream_next(ts); + } + } else { + log_on_line(&t.location, t.location.column_end, "expected type"); + return false; + } + + alias.value = type; + + module->aliases[module->alias_count] = alias; + module->alias_count++; + + if (t.token != TOKEN_SEMICOLON) { + log_on_line(&t.location, t.location.column_end, "expected ';'"); + return false; + } + return true; +} + Module* parser_parse(TokenStream* ts) { Token t = tokenstream_next(ts); if (t.token != TOKEN_MODULE) { @@ -40,97 +148,12 @@ Module* parser_parse(TokenStream* ts) { while (1) { t = tokenstream_next(ts); if (t.token == TOKEN_IMPORT) { - ImportDeclaration* new_imports = realloc(module->imports, (module->import_count + 1) * sizeof(ImportDeclaration)); - if (!new_imports) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - module->imports = new_imports; - - t = tokenstream_next(ts); - bool is_public = false; - if (t.token == TOKEN_PUBLIC) { - is_public = true; - t = tokenstream_next(ts); - } - - if (t.token != TOKEN_IDENTIFIER) { - log_on_line(&t.location, t.location.column_end, "expected module name to import"); - parser_free(module); - return NULL; - } - - char* name = (char*)malloc(t.text.length + 1); - memcpy(name, t.text.data, t.text.length); - name[t.text.length] = '\0'; - - module->imports[module->import_count] = (ImportDeclaration){ .module_name = name, .is_public = is_public }; - module->import_count++; - - t = tokenstream_next(ts); - if (t.token != TOKEN_SEMICOLON) { - log_on_line(&t.location, t.location.column_end, "expected ';' after import"); + if (!parse_import(ts, module)) { parser_free(module); return NULL; } } else if (t.token == TOKEN_ALIAS) { - AliasDeclaration* new_aliases = realloc(module->aliases, (module->alias_count + 1) * sizeof(AliasDeclaration)); - if (!new_aliases) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - module->aliases = new_aliases; - - t = tokenstream_next(ts); - if (t.token != TOKEN_IDENTIFIER) { - log_on_line(&t.location, t.location.column_end, "expected alias name"); - parser_free(module); - return NULL; - } - char* name = (char*)malloc(t.text.length + 1); - memcpy(name, t.text.data, t.text.length); - name[t.text.length] = '\0'; - AliasDeclaration alias; - alias.name = name; - - t = tokenstream_next(ts); - if (t.token != TOKEN_ASSIGN) { - log_on_line(&t.location, t.location.column_end, "expected '='"); - parser_free(module); - return NULL; - } - - t = tokenstream_next(ts); - - TypeExpression type; - if (t.token == TOKEN_IDENTIFIER && strncmp(t.text.data, "int32", t.text.length) == 0) { - type = (TypeExpression){ .tag = TYPE_EXPRESSION_BUILTIN, .builtin = { .bitSize = 32, .isSigned = true } }; - t = tokenstream_next(ts); - if (t.token == TOKEN_BRACKET_OPEN) { - t = tokenstream_next(ts); - if (t.token != TOKEN_BRACKET_CLOSE) { - log_on_line(&t.location, t.location.column_end, "expected ']'"); - parser_free(module); - return NULL; - } - TypeExpression* inner = malloc(sizeof(TypeExpression)); - *inner = type; - type = (TypeExpression){ .tag = TYPE_EXPRESSION_ARRAY, .array = { .array = inner } }; - t = tokenstream_next(ts); - } - } else { - log_on_line(&t.location, t.location.column_end, "expected type"); - parser_free(module); - return NULL; - } - - alias.value = type; - - module->aliases[module->alias_count] = alias; - module->alias_count++; - - if (t.token != TOKEN_SEMICOLON) { - log_on_line(&t.location, t.location.column_end, "expected ';'"); + if (!parse_alias(ts, module)) { parser_free(module); return NULL; }