Refactor AST and Parser into modular subdirectories
- Split ast.h into granular headers in v0/ast/ - Split parser.c into modular implementation files in v0/parser/ - Move and rename parser tests to v0/parser/test_*.c - Update build system (include.mk) with modular sub-makefiles - Maintain v0/ast.h and v0/parser.h as umbrella headers
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#include "internal.h"
|
||||
#include "../log.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user