aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c38
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;