88 lines
2.8 KiB
C
88 lines
2.8 KiB
C
#include "internal.h"
|
|
#include "../log.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|