aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-03-03 14:54:07 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit465c544d4a593a135c86390d61385cfbd2f93dd5 (patch)
treedf51caef09740a3e3e6eb1b79b61cf0d2913b680
parentb3b0c807a75c4f854495b547d8e00a598979cbf6 (diff)
Use setjmp, longjmp instead of return_if_error to improve performance
-rw-r--r--include/ast.h2
-rw-r--r--include/parser.h15
-rw-r--r--src/ast.c1
-rw-r--r--src/parser.c211
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 <setjmp.h>
+
#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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
-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;
}