From 5e240bdab90c45f935e7d2b33181de13295e7e6b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 2 Mar 2019 21:20:33 +0100 Subject: Add string, variable and number. Fix identifier match against const and var --- src/parser.c | 175 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 53 deletions(-) (limited to 'src/parser.c') 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 #include -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) { -- cgit v1.2.3