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, 27 insertions, 11 deletions
diff --git a/src/parser.c b/src/parser.c
index 85165d7..ff34663 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -267,12 +267,13 @@ void parser_parse_var_type_def(Parser *self, VariableType *result) {
}
/*
-LHS_DECLARATION = 'extern'? 'pub'? 'const'|'var' TOK_IDENTIFIER VAR_TYPE_DEF?
+LHS_DECLARATION = ('extern'|'export')? 'pub'? 'const'|'var' TOK_IDENTIFIER VAR_TYPE_DEF?
*/
static CHECK_RESULT LhsExpr* parser_parse_declaration_lhs(Parser *self) {
LhsExpr *result;
DeclFlag decl_flag;
bool is_extern;
+ bool is_export;
bool is_pub;
bool is_const;
BufferView var_name;
@@ -283,10 +284,21 @@ static CHECK_RESULT LhsExpr* parser_parse_declaration_lhs(Parser *self) {
decl_flag |= DECL_FLAG_EXTERN;
if(self->has_func_parent) {
self->error = tokenizer_create_error(&self->tokenizer,
- tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data),
+ tokenizer_get_error_index(&self->tokenizer),
"Only declarations in global structs can be extern");
throw(PARSER_UNEXPECTED_TOKEN);
}
+ } else {
+ throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EXPORT, &is_export));
+ if(is_export) {
+ decl_flag |= DECL_FLAG_EXPORT;
+ if(self->has_func_parent) {
+ self->error = tokenizer_create_error(&self->tokenizer,
+ tokenizer_get_error_index(&self->tokenizer),
+ "Only declarations in global structs can be exported");
+ throw(PARSER_UNEXPECTED_TOKEN);
+ }
+ }
}
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_PUB, &is_pub));
@@ -294,7 +306,7 @@ static CHECK_RESULT LhsExpr* parser_parse_declaration_lhs(Parser *self) {
decl_flag |= DECL_FLAG_PUB;
if(self->has_func_parent) {
self->error = tokenizer_create_error(&self->tokenizer,
- tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data),
+ tokenizer_get_error_index(&self->tokenizer),
"Only declarations in global structs can be public");
throw(PARSER_UNEXPECTED_TOKEN);
}
@@ -306,10 +318,10 @@ static CHECK_RESULT LhsExpr* parser_parse_declaration_lhs(Parser *self) {
} else {
bool isVar;
- if(is_extern) {
+ if(is_extern || is_export) {
self->error = tokenizer_create_error(&self->tokenizer,
- tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data),
- "Extern variable have to be declared with \"const\"");
+ tokenizer_get_error_index(&self->tokenizer),
+ "Extern and exported variables have to be declared with \"const\"");
throw(PARSER_UNEXPECTED_TOKEN);
}
@@ -732,10 +744,10 @@ 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)) {
+ if(buffer_get_size(&func_decl->signature->return_types, FunctionReturnType) > 1 && (LHS_EXPR_IS_EXTERN(lhs_expr) || LHS_EXPR_IS_EXPORT(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");
+ "Extern and export closures can only have one return value");
throw(PARSER_ERR);
}
throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &result));
@@ -796,7 +808,7 @@ Ast* parser_parse_body(Parser *self) {
if(LHS_EXPR_IS_EXTERN(lhs_expr)) {
throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON));
if (lhs_expr->type.type == VARIABLE_TYPE_NONE) {
- self->error = tokenizer_create_error(&self->tokenizer, self->tokenizer.prev_index, "A variable can't be declared without a type or assignment");
+ self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, lhs_expr->var_name.data), "An extern variable can't be declared without a type");
throw(PARSER_UNEXPECTED_TOKEN);
}
return result;
@@ -804,10 +816,14 @@ Ast* parser_parse_body(Parser *self) {
throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match));
if(match) {
if(lhs_expr->type.type == VARIABLE_TYPE_SIGNATURE) {
- self->error = tokenizer_create_error(&self->tokenizer, self->tokenizer.prev_index, "Expected function declaration. Only extern functions can have empty declarations.");
+ self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, lhs_expr->var_name.data), "Expected function declaration. Only extern functions can have empty declarations.");
throw(PARSER_UNEXPECTED_TOKEN);
} else if (lhs_expr->type.type == VARIABLE_TYPE_NONE) {
- self->error = tokenizer_create_error(&self->tokenizer, self->tokenizer.prev_index, "A variable can't be declared without a type or assignment");
+ /* TODO: Allow this for non-const variables */
+ self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, lhs_expr->var_name.data), "A variable can't be declared without a type or assignment");
+ throw(PARSER_UNEXPECTED_TOKEN);
+ } else if(LHS_EXPR_IS_CONST(lhs_expr)) {
+ self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, lhs_expr->var_name.data), "A const variable can't be declared without assignment");
throw(PARSER_UNEXPECTED_TOKEN);
}
return result;