aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-02-24 02:10:58 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:40 +0200
commit11dc4b81935e3dfee997c421d8d6fa166edd7a05 (patch)
treeccb08be54209a4900c740c9ed58e8f9c2910811d /src/parser.c
Initial commit, Function declaration work somewhat
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c187
1 files changed, 187 insertions, 0 deletions
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 <stdio.h>
+
+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;
+}