diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/src/parser.c b/src/parser.c index 33e9146..cdf7c5b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -20,6 +20,8 @@ do { \ throw(return_if_result); \ } while(0) +#define VAR_MAX_LEN UINT8_MAX + static CHECK_RESULT Ast* parser_parse_rhs(Parser *self); static CHECK_RESULT Ast* parser_parse_body(Parser *self); static CHECK_RESULT Ast* parser_parse_struct_body(Parser *self); @@ -193,21 +195,27 @@ static void parser_parse_function_parameters(Parser *self, FunctionSignature *fu FUNC_RETURN_TYPES = VAR_TYPE (',' VAR_TYPE)* */ static void parser_parse_function_return_types(Parser *self, FunctionSignature *func_sig) { + int return_type_index; + return_type_index = 0; for(;;) { VariableType var_type; bool match; parser_parse_var_type(self, &var_type); if(var_type.type == VARIABLE_TYPE_NONE) { + /* If function has no return types */ + if(return_type_index == 0) + return; self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), - "Expected closure return type"); + "Expected type or closure signature"); throw(PARSER_UNEXPECTED_TOKEN); } throw_if_error(function_signature_add_return_type(func_sig, &var_type)); throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COMMA, &match)); if(!match) return; + ++return_type_index; } } @@ -256,14 +264,9 @@ void parser_parse_var_type(Parser *self, VariableType *result) { return; } - result->type = VARIABLE_TYPE_SIGNATURE; result->value.signature = parser_parse_function_signature(self); - if(!result->value.signature) { - self->error = tokenizer_create_error(&self->tokenizer, - tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data), - "Expected type or closure signature"); - throw(PARSER_UNEXPECTED_TOKEN); - } + if(result->value.signature) + result->type = VARIABLE_TYPE_SIGNATURE; } /* @@ -280,6 +283,12 @@ void parser_parse_var_type_def(Parser *self, VariableType *result) { } parser_parse_var_type(self, result); + if(result->type == VARIABLE_TYPE_NONE) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "Expected type or closure signature"); + throw(PARSER_UNEXPECTED_TOKEN); + } } /* @@ -339,6 +348,13 @@ static CHECK_RESULT LhsExpr* parser_parse_declaration_lhs(Parser *self) { throw_if_error(arena_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)&result)); lhsexpr_init(result, decl_flag, var_name); + if(var_name.size > VAR_MAX_LEN) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_code_reference_index(&self->tokenizer, var_name.data), + "Variable name can't be longer than %d", VAR_MAX_LEN); + throw(PARSER_ERR); + } + parser_parse_var_type_def(self, &result->type); return result; } @@ -741,6 +757,12 @@ static Ast* parser_parse_lhs_rhs(Parser *self, LhsExpr *lhs_expr) { func_decl = parser_parse_closure(self); if(func_decl) { + if(buffer_get_size(&func_decl->signature->return_types, FunctionReturnType) > 1 && LHS_EXPR_IS_EXTERN(lhs_expr)) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_code_reference_index(&self->tokenizer, lhs_expr->var_name.data), + "Extern closure can only have one return value"); + throw(PARSER_ERR); + } throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &result)); func_decl->lhs_expr = lhs_expr; return result; |