#include "parser.h" #include "log.h" #include #include #include Module* parser_parse(TokenStream* ts) { Token t = tokenstream_next(ts); if (t.token != TOKEN_MODULE) { log_on_line(&t.location, t.location.column_end, "expected 'module' keyword"); return NULL; } t = tokenstream_next(ts); if (t.token != TOKEN_IDENTIFIER) { log_on_line(&t.location, t.location.column_end, "expected module name"); return NULL; } Module* module = (Module*)malloc(sizeof(Module)); if (module == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } module->name = NULL; module->imports = NULL; module->import_count = 0; module->name = (char*)malloc(t.text.length + 1); if (module->name == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } memcpy(module->name, t.text.data, t.text.length); module->name[t.text.length] = '\0'; t = tokenstream_next(ts); if (t.token != TOKEN_SEMICOLON) { log_on_line(&t.location, t.location.column_end, "expected ';' after module name"); parser_free(module); return NULL; } module->imports = NULL; module->import_count = 0; while (1) { t = tokenstream_next(ts); if (t.token != TOKEN_IMPORT) { break; } 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_IDENTIFIER && strncmp(t.text.data, "public", t.text.length) == 0) { 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; } module->imports[module->import_count].module_name = (char*)malloc(t.text.length + 1); if (!module->imports[module->import_count].module_name) { fprintf(stderr, "Out of memory\n"); exit(1); } memcpy(module->imports[module->import_count].module_name, t.text.data, t.text.length); module->imports[module->import_count].module_name[t.text.length] = '\0'; module->imports[module->import_count].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"); parser_free(module); return NULL; } } return module; } 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); } free(module->name); free(module); }