aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c175
1 files changed, 122 insertions, 53 deletions
diff --git a/src/parser.c b/src/parser.c
index e63814f..539ebd3 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -10,8 +10,9 @@
#include <stdlib.h>
#include <assert.h>
-static CHECK_RESULT int parser_queue_file(Parser *self, BufferView path);
+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);
int parser_thread_data_init(ParserThreadData *self) {
am_memset(&self->allocator, 0, sizeof(self->allocator));
@@ -42,9 +43,32 @@ int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocato
self->allocator = allocator;
self->compiler = compiler;
self->started = bool_false;
+ self->error.index = 0;
+ self->error.str = NULL;
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) {
+ for(;;) {
+ Ast body_obj;
+ bool is_end_token;
+ return_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)));
+ }
+ return PARSER_OK;
+}
+
/*
LHS = 'const'|'var' IDENTIFIER
*/
@@ -70,7 +94,7 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result) {
}
/*
-CLOSURE = '(' PARAM* ')' '{' BODY* '}'
+CLOSURE = '(' PARAM* ')' '{' BODY_LOOP '}'
*/
static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) {
bool result;
@@ -88,38 +112,65 @@ static CHECK_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl **
return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl));
return_if_error(funcdecl_init(*func_decl, self->allocator));
+ return parser_parse_body_loop(self, &(*func_decl)->body, TOK_CLOSING_BRACE);
+}
+
+/*
+FUNC_ARGS = (RHS_START)? (',' RHS_START)* ')'
+*/
+static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *func_call) {
+ bool first_arg;
+ first_arg = bool_true;
+
for(;;) {
- Ast body_obj;
- return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result));
- if(result)
+ Ast arg_expr;
+ bool is_end_token;
+ arg_expr = ast_none();
+
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_PAREN, &is_end_token));
+ if(is_end_token)
break;
- return_if_error(parser_parse_body(self, &body_obj));
- return_if_error(funcdecl_add_to_body(*func_decl, body_obj));
+ if(!first_arg)
+ return_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)));
}
+
return PARSER_OK;
}
/*
-FUNC_CALL = IDENTIFIER '(' RHS* ')'
+VARIABLE = IDENTIFIER
+FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')'
*/
-static CHECK_RESULT int parser_parse_function_call(Parser *self, FunctionCall **func_call) {
+static CHECK_RESULT int parser_parse_function_call_or_variable(Parser *self, Ast *expr) {
bool result;
- BufferView func_name;
- *func_call = NULL;
+ BufferView identifier;
+ FunctionCall *func_call;
return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &result));
if(!result)
return PARSER_OK;
- func_name = self->tokenizer.value.identifier;
- return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_PAREN));
- /* TODO: Parse arguments */
- return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN));
-
- return_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)func_call));
- funccall_init(*func_call, func_name);
- return PARSER_OK;
+ identifier = self->tokenizer.value.identifier;
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &result));
+ if(!result) {
+ Variable *variable;
+ return_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));
+ expr->type = AST_FUNCTION_CALL;
+ expr->value.func_call = func_call;
+ return parser_parse_function_args(self, func_call);
}
/*
@@ -138,32 +189,56 @@ static CHECK_RESULT int parser_parse_import(Parser *self, Import **import) {
return PARSER_OK;
}
+static CHECK_RESULT int parser_parse_number(Parser *self, Ast *rhs_expr) {
+ bool result;
+ Number *number;
+
+ return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_NUMBER, &result));
+ if(!result)
+ return PARSER_OK;
+
+ return_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;
+ return PARSER_OK;
+}
+
/*
-RHS = CLOSURE | FUNC_CALL | IMPORT
+RHS = STRING | NUMBER | FUNC_CALL_OR_VARIABLE
*/
static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
- FunctionDecl *func_decl;
- FunctionCall *func_call;
- Import *import;
- /* bool result;*/
+ bool result;
-/*
return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &result));
if(result) {
String *string;
return_if_error(scoped_allocator_alloc(self->allocator, sizeof(String), (void**)&string));
- string_init(string, self->tokenizer.value.string);
+ return_if_error(string_init(string, self->tokenizer.value.string));
rhs_expr->type = AST_STRING;
- rhs_expr->value.string = func_call;
+ rhs_expr->value.string = string;
return PARSER_OK;
}
-*/
- return_if_error(parser_parse_function_call(self, &func_call));
- if(func_call) {
- rhs_expr->type = AST_FUNCTION_CALL;
- rhs_expr->value.func_call = func_call;
+
+ return_if_error(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));
+ 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;
+}
+
+/*
+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));
if(func_decl) {
@@ -180,24 +255,26 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) {
return PARSER_OK;
}
- /* TODO: Convert token to string */
- tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call");
- return PARSER_UNEXPECTED_TOKEN;
+ 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;
}
/*
-BODY = (LHS '=' RHS) |
- RHS
+BODY = (LHS '=' RHS_START) |
+ RHS_START
*/
int parser_parse_body(Parser *self, Ast *ast) {
LhsExpr *lhs_expr;
Ast rhs_expr;
+ rhs_expr = ast_none();
return_if_error(parser_parse_lhs(self, &lhs_expr));
if(lhs_expr)
return_if_error(tokenizer_accept(&self->tokenizer, TOK_EQUALS));
- return_if_error(parser_parse_rhs(self, &rhs_expr));
+ return_if_error(parser_parse_rhs_start(self, &rhs_expr));
if(lhs_expr) {
lhs_expr->rhs_expr = rhs_expr;
ast->type = AST_LHS;
@@ -209,23 +286,15 @@ int parser_parse_body(Parser *self, Ast *ast) {
}
/*
-ROOT = BODY*
+ROOT = BODY_LOOP
*/
int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_name) {
- Ast ast;
+ int result;
return_if_error(tokenizer_init(&self->tokenizer, code_buffer, buffer_name));
-
- for(;;) {
- bool isEof;
- return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_END_OF_FILE, &isEof));
- if(isEof)
- break;
-
- return_if_error(parser_parse_body(self, &ast));
- return_if_error(buffer_append(&self->ast_objects, &ast, sizeof(ast)));
- }
-
- return PARSER_OK;
+ 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);
+ return result;
}
int parser_parse_file(Parser *self, BufferView filepath) {