aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c134
1 files changed, 107 insertions, 27 deletions
diff --git a/src/parser.c b/src/parser.c
index 78b0018..da85292 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,19 +1,51 @@
#include "../include/parser.h"
#include "../include/ast.h"
-#include "../include/misc.h"
-#include "../include/alloc.h"
+#include "../include/compiler.h"
+#include "../include/std/misc.h"
+#include "../include/std/file.h"
+#include "../include/std/mem.h"
+#include "../include/std/log.h"
#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+static CHECK_RESULT int parser_queue_file(Parser *self, BufferView path);
static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast);
-int parser_init(Parser *self) {
- return_if_error(scoped_allocator_init(&self->allocator));
- return_if_error(buffer_init(&self->ast_objects, &self->allocator));
- return PARSER_OK;
+int parser_thread_data_init(ParserThreadData *self) {
+ am_memset(&self->allocator, 0, sizeof(self->allocator));
+ am_memset(&self->thread, 0, sizeof(self->thread));
+ self->status = PARSER_THREAD_STATUS_NEW;
+ return scoped_allocator_init(&self->allocator);
}
-void parser_deinit(Parser *self) {
+int parser_thread_data_deinit(ParserThreadData *self) {
scoped_allocator_deinit(&self->allocator);
+ return amal_thread_deinit(&self->thread);
+}
+
+int parser_thread_data_start(ParserThreadData *self, AmalThreadCallbackFunc callback_func, void *userdata) {
+ return_if_error(amal_thread_deinit(&self->thread));
+ return_if_error(amal_thread_create(&self->thread, AMAL_THREAD_JOINABLE, "Parser", callback_func, userdata));
+ self->status = PARSER_THREAD_STATUS_RUNNING;
+ return 0;
+}
+
+int parser_thread_data_join(ParserThreadData *self, void **result) {
+ int retval;
+ if(self->status == PARSER_THREAD_STATUS_NEW)
+ return 0;
+ retval = amal_thread_join(&self->thread, result);
+ if(retval == 0 || retval == AMAL_THREAD_NOT_JOINABLE)
+ self->status = PARSER_THREAD_STATUS_IDLE;
+ return retval;
+}
+
+int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocator) {
+ self->allocator = allocator;
+ self->compiler = compiler;
+ self->started = bool_false;
+ return buffer_init(&self->ast_objects, self->allocator);
}
/*
@@ -34,8 +66,8 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result) {
return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER));
var_name = self->tokenizer.value.identifier;
- fprintf(stderr, "var name: %.*s\n", (int)var_name.size, var_name.data);
- return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(LhsExpr), (void**)result));
+ amal_log_debug("var name: %.*s", (int)var_name.size, var_name.data);
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result));
lhsexpr_init(*result, isConst, var_name);
return PARSER_OK;
}
@@ -56,23 +88,19 @@ static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl **
/* TODO: Parse return types */
return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE));
- return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(FunctionDecl), (void**)func_decl));
- cleanup_if_error(funcdecl_init(*func_decl, &self->allocator));
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl));
+ return_if_error(funcdecl_init(*func_decl, self->allocator));
for(;;) {
Ast body_obj;
- cleanup_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result));
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result));
if(result)
break;
- cleanup_if_error(parser_parse_body(self, &body_obj));
- cleanup_if_error(funcdecl_add_to_body(*func_decl, body_obj));
+ return_if_error(parser_parse_body(self, &body_obj));
+ return_if_error(funcdecl_add_to_body(*func_decl, body_obj));
}
return PARSER_OK;
-
- cleanup:
- *func_decl = NULL;
- return PARSER_ERR;
}
/*
@@ -92,20 +120,33 @@ static CHECK_RESULT int parser_parse_function_call(Parser *self, FunctionCall **
/* TODO: Parse arguments */
return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN));
- return_if_error(scoped_allocator_alloc(&self->allocator, sizeof(FunctionCall), (void**)func_call));
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)func_call));
funccall_init(*func_call, func_name);
return PARSER_OK;
}
/*
-RHS = FUNC_DECL | FUNC_CALL
+IMPORT = IMPORT_SYMBOL
+*/
+static CHECK_RESULT int parser_parse_import(Parser *self, Import **import) {
+ bool result;
+
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &result));
+ if(!result)
+ return PARSER_OK;
+
+ return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import));
+ import_init(*import, self->tokenizer.value.string);
+ return PARSER_OK;
+}
+
+/*
+RHS = FUNC_DECL | FUNC_CALL | IMPORT
*/
static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
FunctionDecl *func_decl;
FunctionCall *func_call;
- Token token;
- func_decl = NULL;
- func_call = NULL;
+ Import *import;
return_if_error(parser_parse_function_decl(self, &func_decl));
if(func_decl) {
@@ -121,9 +162,16 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
return PARSER_OK;
}
- return_if_error(tokenizer_next(&self->tokenizer, &token));
+ return_if_error(parser_parse_import(self, &import));
+ if(import) {
+ rhs_expr->type = AST_IMPORT;
+ rhs_expr->value.import = import;
+ return_if_error(parser_queue_file(self, import->path));
+ return PARSER_OK;
+ }
+
/* TODO: Convert token to string */
- tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call, got token: %d");
+ tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call");
return PARSER_UNEXPECTED_TOKEN;
}
@@ -153,9 +201,9 @@ int parser_parse_body(Parser *self, Ast *ast) {
/*
ROOT = BODY*
*/
-int parser_parse_buffer(Parser *self, BufferView code_buffer) {
+int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name) {
Ast ast;
- return_if_error(tokenizer_init(&self->tokenizer, code_buffer));
+ return_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name));
for(;;) {
bool isEof;
@@ -169,3 +217,35 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer) {
return PARSER_OK;
}
+
+int parser_parse_file(Parser *self, BufferView filepath) {
+ int result;
+ int mapped_file_deinit_result;
+ MappedFile mapped_file;
+ char *filepath_tmp;
+
+ amal_log_debug("Parsing %.*s", (int)filepath.size, filepath.data);
+ assert(!self->started && "Parser can't be reused. Create a new parser.");
+ self->started = bool_true;
+ /* TODO: Somehow free this... */
+ /*return_if_error(scoped_allocator_alloc(self->allocator, filepath.size + 1, (void**)&filepath_tmp));*/
+ filepath_tmp = malloc(filepath.size + 1);
+ am_memcpy(filepath_tmp, filepath.data, filepath.size);
+ filepath_tmp[filepath.size] = '\0';
+ result = mapped_file_init(&mapped_file, filepath_tmp, MAPPED_FILE_READ);
+ if(result != 0) return result;
+ result = parser_parse_buffer(self, create_buffer_view(mapped_file.file_data, mapped_file.file_size), filepath);
+ mapped_file_deinit_result = mapped_file_deinit(&mapped_file);
+ return result != 0 ? result : mapped_file_deinit_result;
+}
+
+/*
+Path can be path to included library path (or system library path) in which case
+the path separator is a dot, otherwise the path separator is forward slash '/'
+*/
+int parser_queue_file(Parser *self, BufferView path) {
+ /* TODO: Do not load same path twice or the compile will fail (and it can have recursive import) also for performance reasons */
+ /* TODO: Parse special path (to include library path with dots) */
+ return_if_error(amal_compiler_load_file(self->compiler, path));
+ return PARSER_OK;
+} \ No newline at end of file