diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/src/parser.c b/src/parser.c index 6ee273b..fcc29be 100644 --- a/src/parser.c +++ b/src/parser.c @@ -69,7 +69,8 @@ int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocato /* BODY_LOOP = BODY* @end_token */ -static THROWABLE parser_parse_body_loop(Parser *self, Buffer *body_list, Token end_token) { +static THROWABLE parser_parse_body_loop(Parser *self, Scope *scope, Token end_token) { + int result; for(;;) { Ast body_obj; bool is_end_token; @@ -78,7 +79,21 @@ static THROWABLE parser_parse_body_loop(Parser *self, Buffer *body_list, Token e break; try(parser_parse_body(self, &body_obj)); - throw_if_error(buffer_append(body_list, &body_obj, sizeof(body_obj))); + result = scope_add_child(scope, &body_obj); + if(result == 0) { + continue; + } else if(result == AST_ERR_DEF_DUP) { + /* TODO: Convert ast type to string for error message */ + BufferView obj_name; + obj_name = ast_get_name(&body_obj); + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_code_reference_index(&self->tokenizer, obj_name.data), + "A variable with the name %.*s was declared twice in the same scope", obj_name.size, obj_name.data); + self->error_context = ERROR_CONTEXT_NONE; + throw(result); + } else { + throw(result); + } } return PARSER_OK; } @@ -130,11 +145,15 @@ static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignme *assignment = bool_false; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); if(match && is_const) { - self->error = tokenizer_create_error(&self->tokenizer, "const variable declaration requires assignment (expected '=', got ';')"); + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "const variable declaration requires assignment (expected '=', got ';')"); throw(PARSER_UNEXPECTED_TOKEN); } if(!match) { - self->error = tokenizer_create_error(&self->tokenizer, "Expected '=' or ';'"); + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "Expected '=' or ';'"); throw(PARSER_UNEXPECTED_TOKEN); } return PARSER_OK; @@ -282,7 +301,9 @@ static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { if(rhs_expr->type != AST_NONE) return PARSER_OK; - self->error = tokenizer_create_error(&self->tokenizer, "Expected string, variable or function call"); + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "Expected string, variable or function call"); throw(PARSER_UNEXPECTED_TOKEN); } @@ -374,6 +395,7 @@ int parser_parse_rhs_start(Parser *self, Ast *rhs_expr) { self->error_context = ERROR_CONTEXT_RHS_START; try(parser_parse_rhs(self, rhs_expr)); + self->error_context = ERROR_CONTEXT_NONE; return PARSER_OK; } @@ -388,7 +410,9 @@ static THROWABLE parser_parse_body_semicolon(Parser *self, Ast *expr) { 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"); + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "Expected ';' or binop"); throw(PARSER_UNEXPECTED_TOKEN); } return PARSER_OK; @@ -437,10 +461,10 @@ ROOT = BODY_LOOP */ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name) { int result; - throw_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name)); + throw_if_error(tokenizer_init(&self->tokenizer, self->allocator, code_buffer, buffer_name)); result = setjmp(self->parse_env); if(result == 0) - try(parser_parse_body_loop(self, &self->scope.ast_objects, TOK_END_OF_FILE)); + try(parser_parse_body_loop(self, &self->scope, TOK_END_OF_FILE)); else if(self->error.str != NULL) { switch(self->error_context) { case ERROR_CONTEXT_NONE: |