From 465c544d4a593a135c86390d61385cfbd2f93dd5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 3 Mar 2019 14:54:07 +0100 Subject: Use setjmp, longjmp instead of return_if_error to improve performance --- include/ast.h | 2 + include/parser.h | 15 +++- src/ast.c | 1 + src/parser.c | 211 +++++++++++++++++++++++++++++++------------------------ 4 files changed, 138 insertions(+), 91 deletions(-) diff --git a/include/ast.h b/include/ast.h index 05bb6ee..29a0b64 100644 --- a/include/ast.h +++ b/include/ast.h @@ -85,6 +85,8 @@ struct Binop { Ast lhs; Ast rhs; BinopType type; + /* Is the binop already ordered - no need to reorder it */ + bool grouped; }; Ast ast_none(); diff --git a/include/parser.h b/include/parser.h index 531d67d..b9fb3b7 100644 --- a/include/parser.h +++ b/include/parser.h @@ -8,6 +8,8 @@ #include "tokenizer.h" #include "defs.h" +#include + #define PARSER_OK 0 /* General error */ #define PARSER_ERR -1 @@ -25,6 +27,11 @@ struct ParserThreadData { ScopedAllocator allocator; }; +typedef enum { + ERROR_CONTEXT_NONE, + ERROR_CONTEXT_RHS_START +} ErrorContext; + typedef struct { Tokenizer tokenizer; Buffer ast_objects; @@ -32,6 +39,8 @@ typedef struct { amal_compiler *compiler; bool started; TokenizerError error; + ErrorContext error_context; + jmp_buf parse_env; } Parser; CHECK_RESULT int parser_thread_data_init(ParserThreadData *self); @@ -44,9 +53,13 @@ CHECK_RESULT int parser_init(Parser *self, amal_compiler *compiler, ScopedAlloca /* @buffer_name will be the path to the file when using parser_parse_file and when parsing a buffer you can name the buffer anything you want to identify it. +Should only be called once for a parser object. */ CHECK_RESULT int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name); -/* Parses a file and the dependencies that are included using @import */ +/* +Parses a file and the dependencies that are included using @import. +Should only be called once for a parser object. +*/ CHECK_RESULT int parser_parse_file(Parser *self, BufferView filepath); #endif diff --git a/src/ast.c b/src/ast.c index 4b72f43..993cf95 100644 --- a/src/ast.c +++ b/src/ast.c @@ -48,4 +48,5 @@ void binop_init(Binop *self) { self->lhs = ast_none(); self->rhs = ast_none(); self->type = BINOP_ADD; + self->grouped = bool_false; } \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 52c5bfe..52c2916 100644 --- a/src/parser.c +++ b/src/parser.c @@ -6,13 +6,30 @@ #include "../include/std/mem.h" #include "../include/std/log.h" #include "../include/std/alloc.h" + #include #include #include -static CHECK_RESULT int parser_parse_rhs_start(Parser *self, Ast *rhs_expr); -static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast); -static CHECK_RESULT int parser_queue_file(Parser *self, BufferView path); +#define THROWABLE CHECK_RESULT int +#define try(result) \ +do { \ + int return_if_result; \ + return_if_result = (result); \ + (void)return_if_result; \ +} while(0) +#define throw(result) do { longjmp(self->parse_env, (result)); } while(0) +#define throw_if_error(result) \ +do { \ + int return_if_result; \ + return_if_result = (result); \ + if((return_if_result) != 0) \ + throw(return_if_result); \ +} while(0) + +static THROWABLE parser_parse_rhs_start(Parser *self, Ast *rhs_expr); +static THROWABLE parser_parse_body(Parser *self, Ast *ast); +static THROWABLE parser_queue_file(Parser *self, BufferView path); int parser_thread_data_init(ParserThreadData *self) { am_memset(&self->allocator, 0, sizeof(self->allocator)); @@ -45,26 +62,23 @@ int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocato self->started = bool_false; self->error.index = 0; self->error.str = NULL; + self->error_context = ERROR_CONTEXT_NONE; return buffer_init(&self->ast_objects, self->allocator); } -static bool parser_got_overwritable_error(Parser *self) { - return self->error.str != NULL; -} - /* BODY_LOOP = BODY* @end_token */ -static CHECK_RESULT int parser_parse_body_loop(Parser *self, Buffer *body_list, Token end_token) { +static THROWABLE parser_parse_body_loop(Parser *self, Buffer *body_list, Token end_token) { for(;;) { Ast body_obj; bool is_end_token; - return_if_error(tokenizer_consume_if(&self->tokenizer, end_token, &is_end_token)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, end_token, &is_end_token)); if(is_end_token) break; - return_if_error(parser_parse_body(self, &body_obj)); - return_if_error(buffer_append(body_list, &body_obj, sizeof(body_obj))); + try(parser_parse_body(self, &body_obj)); + throw_if_error(buffer_append(body_list, &body_obj, sizeof(body_obj))); } return PARSER_OK; } @@ -72,47 +86,47 @@ static CHECK_RESULT int parser_parse_body_loop(Parser *self, Buffer *body_list, /* LHS = 'const'|'var' TOK_IDENTIFIER */ -static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment) { +static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment) { bool isConst; bool match; BufferView var_name; *result = NULL; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CONST, &isConst)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CONST, &isConst)); if(!isConst) { bool isVar; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_VAR, &isVar)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_VAR, &isVar)); if(!isVar) return PARSER_OK; } - return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); var_name = self->tokenizer.value.identifier; 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)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result)); lhsexpr_init(*result, isConst, var_name); - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match)); if(match) { - return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); (*result)->type_name = self->tokenizer.value.identifier; } - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match)); if(match) { *assignment = bool_true; return PARSER_OK; } *assignment = bool_false; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); if(match && isConst) { self->error = tokenizer_create_error(&self->tokenizer, "const variable declaration requires assignment (expected '=', got ';')"); - return PARSER_UNEXPECTED_TOKEN; + throw(PARSER_UNEXPECTED_TOKEN); } if(!match) { self->error = tokenizer_create_error(&self->tokenizer, "Expected '=' or ';'"); - return PARSER_UNEXPECTED_TOKEN; + throw(PARSER_UNEXPECTED_TOKEN); } return PARSER_OK; } @@ -120,33 +134,34 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *a /* CLOSURE = 'fn' ('(' PARAM* ')')? '{' BODY_LOOP '}' */ -static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) { +static THROWABLE parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) { bool match; *func_decl = NULL; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match)); if(!match) return PARSER_OK; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_BRACE, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_BRACE, &match)); if(!match) { - return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_PAREN)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_PAREN)); /* TODO: Parse parameters */ - return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); /* TODO: Parse return types */ - return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); } - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl)); - return_if_error(funcdecl_init(*func_decl, self->allocator)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl)); + throw_if_error(funcdecl_init(*func_decl, self->allocator)); - return parser_parse_body_loop(self, &(*func_decl)->body, TOK_CLOSING_BRACE); + try(parser_parse_body_loop(self, &(*func_decl)->body, TOK_CLOSING_BRACE)); + return PARSER_OK; } /* FUNC_ARGS = (RHS_START)? (',' RHS_START)* ')' */ -static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *func_call) { +static THROWABLE parser_parse_function_args(Parser *self, FunctionCall *func_call) { bool first_arg; first_arg = bool_true; @@ -155,16 +170,16 @@ static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *f bool is_end_token; arg_expr = ast_none(); - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_PAREN, &is_end_token)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_PAREN, &is_end_token)); if(is_end_token) break; if(!first_arg) - return_if_error(tokenizer_accept(&self->tokenizer, TOK_COMMA)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_COMMA)); first_arg = bool_false; - return_if_error(parser_parse_rhs_start(self, &arg_expr)); - return_if_error(buffer_append(&func_call->args, &arg_expr, sizeof(arg_expr))); + try(parser_parse_rhs_start(self, &arg_expr)); + throw_if_error(buffer_append(&func_call->args, &arg_expr, sizeof(arg_expr))); } return PARSER_OK; @@ -174,58 +189,59 @@ static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *f VARIABLE = TOK_IDENTIFIER FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')' */ -static CHECK_RESULT int parser_parse_function_call_or_variable(Parser *self, Ast *expr) { +static THROWABLE parser_parse_function_call_or_variable(Parser *self, Ast *expr) { bool match; BufferView identifier; FunctionCall *func_call; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); if(!match) return PARSER_OK; identifier = self->tokenizer.value.identifier; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match)); if(!match) { Variable *variable; - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Variable), (void**)&variable)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Variable), (void**)&variable)); variable->name = identifier; expr->type = AST_VARIABLE; expr->value.variable = variable; return PARSER_OK; } - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)&func_call)); - return_if_error(funccall_init(func_call, self->tokenizer.value.identifier, self->allocator)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)&func_call)); + throw_if_error(funccall_init(func_call, self->tokenizer.value.identifier, self->allocator)); expr->type = AST_FUNCTION_CALL; expr->value.func_call = func_call; - return parser_parse_function_args(self, func_call); + try(parser_parse_function_args(self, func_call)); + return PARSER_OK; } /* IMPORT = IMPORT_SYMBOL */ -static CHECK_RESULT int parser_parse_import(Parser *self, Import **import) { +static THROWABLE parser_parse_import(Parser *self, Import **import) { bool match; *import = NULL; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &match)); if(!match) return PARSER_OK; - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import)); import_init(*import, self->tokenizer.value.string); return PARSER_OK; } -static CHECK_RESULT int parser_parse_number(Parser *self, Ast *rhs_expr) { +static THROWABLE parser_parse_number(Parser *self, Ast *rhs_expr) { bool match; Number *number; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_NUMBER, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_NUMBER, &match)); if(!match) return PARSER_OK; - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Number), (void**)&number)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Number), (void**)&number)); number_init(number, self->tokenizer.value.integer, self->tokenizer.number_is_integer); rhs_expr->type = AST_NUMBER; rhs_expr->value.number = number; @@ -235,61 +251,64 @@ static CHECK_RESULT int parser_parse_number(Parser *self, Ast *rhs_expr) { /* RHS_S = STRING | NUMBER | FUNC_CALL_OR_VARIABLE */ -static CHECK_RESULT int parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { +static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { bool match; *rhs_expr = ast_none(); - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match)); if(match) { String *string; - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(String), (void**)&string)); - return_if_error(string_init(string, self->tokenizer.value.string)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(String), (void**)&string)); + throw_if_error(string_init(string, self->tokenizer.value.string)); rhs_expr->type = AST_STRING; rhs_expr->value.string = string; return PARSER_OK; } - return_if_error(parser_parse_number(self, rhs_expr)); + try(parser_parse_number(self, rhs_expr)); if(rhs_expr->type != AST_NONE) return PARSER_OK; - return_if_error(parser_parse_function_call_or_variable(self, rhs_expr)); + try(parser_parse_function_call_or_variable(self, rhs_expr)); if(rhs_expr->type != AST_NONE) return PARSER_OK; self->error = tokenizer_create_error(&self->tokenizer, "Expected string, variable or function call"); - return PARSER_UNEXPECTED_TOKEN; + throw(PARSER_UNEXPECTED_TOKEN); } -static CHECK_RESULT int parser_parse_rhs_binop(Parser *self, Ast *expr); +static THROWABLE parser_parse_rhs_binop(Parser *self, Ast *expr); /* RHS_BINOP_PAREN = '(' RHS_BINOP ')' (TOK_BINOP RHS_BINOP) */ -static CHECK_RESULT int parser_parse_rhs_binop_paren(Parser *self, bool *match, Ast *expr) { +static THROWABLE parser_parse_rhs_binop_paren(Parser *self, bool *match, Ast *expr) { bool binop_match; Ast lhs; Ast rhs; BinopType binop_type; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, match)); if(!*match) return PARSER_OK; - return_if_error(parser_parse_rhs_binop(self, &lhs)); - return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); + try(parser_parse_rhs_binop(self, &lhs)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &binop_match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &binop_match)); if(!binop_match) { + if(lhs.type == AST_BINOP) + lhs.value.binop->grouped = bool_true; *expr = lhs; return PARSER_OK; } binop_type = self->tokenizer.value.binop_type; - return_if_error(parser_parse_rhs_binop(self, &rhs)); - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); + try(parser_parse_rhs_binop(self, &rhs)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); binop_init(expr->value.binop); expr->value.binop->type = binop_type; + expr->value.binop->grouped = bool_true; expr->value.binop->lhs = lhs; expr->value.binop->rhs = rhs; expr->type = AST_BINOP; @@ -299,22 +318,22 @@ static CHECK_RESULT int parser_parse_rhs_binop_paren(Parser *self, bool *match, /* RHS_BINOP_WO_PAREN = RHS_S | (RHS_S TOK_BINOP RHS_BINOP) */ -static CHECK_RESULT int parser_parse_rhs_binop_without_paren(Parser *self, Ast *expr) { +static THROWABLE parser_parse_rhs_binop_without_paren(Parser *self, Ast *expr) { bool match; Ast lhs; Ast rhs; BinopType binop_type; - return_if_error(parser_parse_rhs_single_expr(self, &lhs)); - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); + try(parser_parse_rhs_single_expr(self, &lhs)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); if(!match) { *expr = lhs; return PARSER_OK; } binop_type = self->tokenizer.value.binop_type; - return_if_error(parser_parse_rhs_binop(self, &rhs)); - return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); + try(parser_parse_rhs_binop(self, &rhs)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); binop_init(expr->value.binop); expr->value.binop->type = binop_type; expr->value.binop->lhs = lhs; @@ -330,10 +349,11 @@ Note: Parantheses count has to match for the beginning paranthesis and the endin */ int parser_parse_rhs_binop(Parser *self, Ast *expr) { bool match; - return_if_error(parser_parse_rhs_binop_paren(self, &match, expr)); + try(parser_parse_rhs_binop_paren(self, &match, expr)); if(match) return PARSER_OK; - return parser_parse_rhs_binop_without_paren(self, expr); + try(parser_parse_rhs_binop_without_paren(self, expr)); + return PARSER_OK; } /* @@ -341,9 +361,9 @@ RHS = RHS_BINOP ';' Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis. */ -static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { +static THROWABLE parser_parse_rhs(Parser *self, Ast *rhs_expr) { /* TODO: If binop only contains one expression, then use that directly for @rhs_expr */ - return_if_error(parser_parse_rhs_binop(self, rhs_expr)); + try(parser_parse_rhs_binop(self, rhs_expr)); /* TODO: Implement this */ /*binop_reorder_by_precedence(binop);*/ @@ -356,27 +376,25 @@ RHS_START = CLOSURE | IMPORT | RHS int parser_parse_rhs_start(Parser *self, Ast *rhs_expr) { FunctionDecl *func_decl; Import *import; - int result; - return_if_error(parser_parse_function_decl(self, &func_decl)); + try(parser_parse_function_decl(self, &func_decl)); if(func_decl) { rhs_expr->type = AST_FUNCTION_DECL; rhs_expr->value.func_decl = func_decl; return PARSER_OK; } - return_if_error(parser_parse_import(self, &import)); + try(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)); + try(parser_queue_file(self, import->path)); return PARSER_OK; } - result = parser_parse_rhs(self, rhs_expr); - if(result == PARSER_UNEXPECTED_TOKEN && parser_got_overwritable_error(self)) - self->error = tokenizer_create_error(&self->tokenizer, "Expected string, variable, closure, function call or import"); - return result; + self->error_context = ERROR_CONTEXT_RHS_START; + try(parser_parse_rhs(self, rhs_expr)); + return PARSER_OK; } /* @@ -392,14 +410,14 @@ int parser_parse_body(Parser *self, Ast *ast) { Ast rhs_expr; rhs_expr = ast_none(); - return_if_error(parser_parse_lhs(self, &lhs_expr, &assignment)); + try(parser_parse_lhs(self, &lhs_expr, &assignment)); if(!assignment) { ast->type = AST_LHS; ast->value.lhs_expr = lhs_expr; return PARSER_OK; } - return_if_error(parser_parse_rhs_start(self, &rhs_expr)); + try(parser_parse_rhs_start(self, &rhs_expr)); if(lhs_expr) { lhs_expr->rhs_expr = rhs_expr; ast->type = AST_LHS; @@ -410,7 +428,7 @@ int parser_parse_body(Parser *self, Ast *ast) { if(rhs_expr.type == AST_BINOP) { bool match; - return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); if(!match) { /* TODO: Specify all the binop characters instead of "binop" which doesn't make sense for the user */ self->error = tokenizer_create_error(&self->tokenizer, "Expected ';' or binop"); @@ -421,7 +439,7 @@ int parser_parse_body(Parser *self, Ast *ast) { /* TODO: Check for struct and tables */ if(rhs_expr.type != AST_FUNCTION_DECL) - return_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON)); + throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON)); return PARSER_OK; } @@ -431,10 +449,23 @@ ROOT = BODY_LOOP */ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name) { int result; - return_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name)); - result = parser_parse_body_loop(self, &self->ast_objects, TOK_END_OF_FILE); - if(self->error.str != NULL) - tokenizer_print_error_object(&self->tokenizer, &self->error); + throw_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name)); + result = setjmp(self->parse_env); + if(result == 0) + try(parser_parse_body_loop(self, &self->ast_objects, TOK_END_OF_FILE)); + else if(self->error.str != NULL) { + switch(self->error_context) { + case ERROR_CONTEXT_NONE: + tokenizer_print_error_object(&self->tokenizer, &self->error); + break; + case ERROR_CONTEXT_RHS_START: + tokenizer_print_error(&self->tokenizer, "Expected string, variable, closure, function call or import"); + break; + default: + assert(bool_false && "Error context handling not implemented"); + break; + } + } return result; } @@ -467,6 +498,6 @@ 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)); + throw_if_error(amal_compiler_load_file(self->compiler, path)); return PARSER_OK; } -- cgit v1.2.3