#include "../include/parser.h" #include "../include/ast.h" #include "../include/misc.h" #include "../include/alloc.h" #include static CHECK_RESULT int parser_parse_body(Parser *self, Ast *ast); int parser_init(Parser *self) { return_if_error(scoped_allocator_init(&self->allocator)); return_if_error(buffer_init(&self->ast_objects, &self->allocator, sizeof(Ast) * 8)); return PARSER_OK; } void parser_deinit(Parser *self) { scoped_allocator_deinit(&self->allocator); } /* LHS = 'const'|'var' IDENTIFIER */ static CHECK_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(scoped_allocator_alloc(&self->allocator, sizeof(LhsExpr), (void**)result)); lhsexpr_init(*result, isConst, var_name); return PARSER_OK; } /* FUNC_DECL = '(' PARAM* ')' '{' BODY* '}' */ static CHECK_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(scoped_allocator_alloc(&self->allocator, sizeof(FunctionDecl), (void**)func_decl)); cleanup_if_error(funcdecl_init(*func_decl, &self->allocator)); 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: *func_decl = NULL; return PARSER_ERR; } /* FUNC_CALL = IDENTIFIER '(' ARGS* ')' */ static CHECK_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(scoped_allocator_alloc(&self->allocator, sizeof(FunctionCall), (void**)func_call)); funccall_init(*func_call, func_name); return PARSER_OK; } /* RHS = FUNC_DECL | FUNC_CALL */ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { FunctionDecl *func_decl; FunctionCall *func_call; Token token; func_decl = NULL; func_call = NULL; return_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; } 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 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; } /* BODY = (LHS '=' RHS) | RHS */ 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)); return_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; } /* ROOT = BODY* */ int parser_parse_buffer(Parser *self, BufferView code_buffer) { Ast ast; return_if_error(tokenizer_init(&self->tokenizer, code_buffer)); 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; }