From 11dc4b81935e3dfee997c421d8d6fa166edd7a05 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 24 Feb 2019 02:10:58 +0100 Subject: Initial commit, Function declaration work somewhat --- src/parser.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/parser.c (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..ddf4a18 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,187 @@ +#include "../include/parser.h" +#include "../include/ast.h" +#include "../include/misc.h" +#include "../include/alloc.h" +#include + +static WARN_UNUSED_RESULT int parser_parse_body(Parser *self, Ast *ast); + +int parser_init(Parser *self) { + buffer_init(&self->ast_objects); + return PARSER_OK; +} + +void parser_deinit(Parser *self) { + usize i; + for(i = 0; i < self->ast_objects.size / sizeof(Ast); ++i) { + ast_deinit((Ast*)&self->ast_objects.data[i]); + } + buffer_deinit(&self->ast_objects); +} + +static WARN_UNUSED_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result) { + bool isConst; + BufferView var_name; + *result = NULL; + + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CONST, &isConst)); + if(!isConst) { + bool isVar; + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_VAR, &isVar)); + if(!isVar) + return PARSER_OK; + } + + return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); + var_name = self->tokenizer.value.identifier; + fprintf(stderr, "var name: %.*s\n", (int)var_name.size, var_name.data); + return_if_error(am_malloc(sizeof(LhsExpr), (void**)result)); + lhsexpr_init(*result, isConst, var_name); + return PARSER_OK; +} + +static WARN_UNUSED_RESULT int parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) { + bool result; + *func_decl = NULL; + + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &result)); + if(!result) + return PARSER_OK; + + /* TODO: Parse parameters */ + return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); + /* TODO: Parse return types */ + return_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); + + return_if_error(am_malloc(sizeof(FunctionDecl), (void**)func_decl)); + funcdecl_init(*func_decl); + + for(;;) { + Ast body_obj; + cleanup_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &result)); + if(result) + break; + + cleanup_if_error(parser_parse_body(self, &body_obj)); + cleanup_if_error(funcdecl_add_to_body(*func_decl, body_obj)); + } + return PARSER_OK; + + cleanup: + if(*func_decl) { + funcdecl_deinit(*func_decl); + am_free(*func_decl); + *func_decl = NULL; + } + return PARSER_ERR; +} + +static WARN_UNUSED_RESULT int parser_parse_function_call(Parser *self, FunctionCall **func_call) { + bool result; + BufferView func_name; + *func_call = NULL; + + 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(am_malloc(sizeof(FunctionCall), (void**)func_call)); + funccall_init(*func_call, func_name); + return PARSER_OK; +} + +static WARN_UNUSED_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { + FunctionDecl *func_decl; + FunctionCall *func_call; + Token token; + func_decl = NULL; + func_call = NULL; + + cleanup_if_error(parser_parse_function_decl(self, &func_decl)); + if(func_decl) { + rhs_expr->type = AST_FUNCTION_DECL; + rhs_expr->value.func_decl = func_decl; + return PARSER_OK; + } + + cleanup_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 PARSER_OK; + } + + return_if_error(tokenizer_next(&self->tokenizer, &token)); + /* TODO: Convert token to string */ + tokenizer_print_error(&self->tokenizer, "Expected function declaration or function call, got token: %d"); + return PARSER_UNEXPECTED_TOKEN; + + cleanup: + if(func_decl) { + funcdecl_deinit(func_decl); + am_free(func_decl); + } + if(func_call) { + /*funccall_deinit(func_call);*/ + am_free(func_call); + } + return PARSER_ERR; +} + +int parser_parse_body(Parser *self, Ast *ast) { + LhsExpr *lhs_expr; + Ast rhs_expr; + + return_if_error(parser_parse_lhs(self, &lhs_expr)); + if(lhs_expr) + return_if_error(tokenizer_accept(&self->tokenizer, TOK_EQUALS)); + + cleanup_if_error(parser_parse_rhs(self, &rhs_expr)); + if(lhs_expr) { + lhs_expr->rhs_expr = rhs_expr; + ast->type = AST_LHS; + ast->value.lhs_expr = lhs_expr; + } else { + *ast = rhs_expr; + } + return PARSER_OK; + + cleanup: + if(lhs_expr) { + lhsexpr_deinit(lhs_expr); + am_free(lhs_expr); + } + return PARSER_ERR; +} + +int parser_parse_buffer(Parser *self, BufferView code_buffer) { + Ast ast; + ast = ast_none(); + return_if_error(tokenizer_init(&self->tokenizer, code_buffer)); + + for(;;) { + bool isEof; + cleanup_if_error(tokenizer_consume_if(&self->tokenizer, TOK_END_OF_FILE, &isEof)); + if(isEof) + goto cleanup_noerr; + + cleanup_if_error(parser_parse_body(self, &ast)); + cleanup_if_error(buffer_append(&self->ast_objects, &ast, sizeof(ast))); + /* For cleanup, we only want to cleanup the last created ast after parser_parse_body */ + ast = ast_none(); + } + + cleanup_noerr: + tokenizer_deinit(&self->tokenizer); + return PARSER_OK; + + cleanup: + tokenizer_deinit(&self->tokenizer); + ast_deinit(&ast); + return PARSER_ERR; +} -- cgit v1.2.3