#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; }