#include "internal.h" #include "../log.h" #include #include bool parse_module_declaration(Parser* p, ModuleTree* 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"); } ModuleTree* parser_parse(TokenStream* ts) { Parser* p = malloc(sizeof(Parser)); p->ts = ts; parser_next_token(p); ModuleTree* module = malloc(sizeof(ModuleTree)); memset(module, 0, sizeof(ModuleTree)); 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); ast_free_module(module); return NULL; }