#include "internal.h" #include "../log.h" #include #include bool parse_module_declaration(Parser* p, Module* module) { if (!parser_expect(p, TOKEN_MODULE, "expected keyword 'module'")) { return false; } if (!parser_require(p, TOKEN_IDENTIFIER, "expected module identifier")) { return false; } module->name = parser_to_text(p); return parser_expect(p, TOKEN_SEMICOLON, "expected ';' after module name"); } Module* parser_parse(TokenStream* ts) { Parser* p = malloc(sizeof(Parser)); p->ts = ts; parser_next_token(p); Module* module = malloc(sizeof(Module)); memset(module, 0, sizeof(Module)); if (!parse_module_declaration(p, module)) { goto fail; } while (!parser_peek(p, TOKEN_EOF)) { bool is_public = false; bool is_static = false; bool is_const = false; bool terminal = false; while (!terminal) { if (parser_accept(p, TOKEN_IMPORT)) { if (is_static) { log_on_line(&p->token.location, "import declarations cannot be static or const"); goto fail; } if (is_const) { log_on_line(&p->token.location, "import declarations cannot be static or const"); goto fail; } if (!parse_import_declaration(p, module, is_public)) { goto fail; } terminal = true; } else if (parser_accept(p, TOKEN_ALIAS)) { if (is_static) { log_on_line(&p->token.location, "alias declarations cannot be static or const"); goto fail; } if (is_const) { log_on_line(&p->token.location, "alias declarations cannot be static or const"); goto fail; } if (!parse_alias_declaration(p, module, is_public)) { goto fail; } terminal = true; } else if (parser_accept(p, TOKEN_PUBLIC)) { is_public = true; } else if (parser_accept(p, TOKEN_STATIC)) { is_static = true; } else if (parser_accept(p, TOKEN_CONST)) { is_const = true; } else if (parser_accept(p, TOKEN_VAR) || parser_accept_primitive(p)) { if (!parse_variable_declaration(p, module, is_public, is_static, is_const)) { goto fail; } terminal = true; } else { log_on_line(&p->token.location, "unexpected token"); goto fail; } } } free(p); return module; fail: free(p); parser_free(module); return NULL; } void parser_free(Module* module) { if (module == NULL) { return; } if (module->imports != NULL) { for(size_t i = 0; i < module->import_count; i++) { free(module->imports[i].module_name); } free(module->imports); } if (module->aliases != NULL) { for(size_t i = 0; i < module->alias_count; i++) { free((void*)module->aliases[i].name); free_type_expression(&module->aliases[i].value); } free(module->aliases); } if (module->variables != NULL) { for(size_t i = 0; i < module->variable_count; i++) { free(module->variables[i].name); free_type_expression(&module->variables[i].type); if (module->variables[i].initializer) { if (module->variables[i].initializer->tag == EXPRESSION_STRING) { free((void*)module->variables[i].initializer->string); } free(module->variables[i].initializer); } } free(module->variables); } free(module->name); free(module); }