From b3b0c807a75c4f854495b547d8e00a598979cbf6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 3 Mar 2019 13:18:08 +0100 Subject: Add arithmetic (binop) parsing --- src/parser.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 4 deletions(-) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index 6ea8d1d..52c5bfe 100644 --- a/src/parser.c +++ b/src/parser.c @@ -70,7 +70,7 @@ static CHECK_RESULT int parser_parse_body_loop(Parser *self, Buffer *body_list, } /* -LHS = 'const'|'var' IDENTIFIER +LHS = 'const'|'var' TOK_IDENTIFIER */ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment) { bool isConst; @@ -92,6 +92,12 @@ static CHECK_RESULT int parser_parse_lhs(Parser *self, LhsExpr **result, bool *a return_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result)); lhsexpr_init(*result, isConst, var_name); + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match)); + if(match) { + return_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); + (*result)->type_name = self->tokenizer.value.identifier; + } + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match)); if(match) { *assignment = bool_true; @@ -165,7 +171,7 @@ static CHECK_RESULT int parser_parse_function_args(Parser *self, FunctionCall *f } /* -VARIABLE = IDENTIFIER +VARIABLE = TOK_IDENTIFIER FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')' */ static CHECK_RESULT int parser_parse_function_call_or_variable(Parser *self, Ast *expr) { @@ -227,10 +233,11 @@ static CHECK_RESULT int parser_parse_number(Parser *self, Ast *rhs_expr) { } /* -RHS = STRING | NUMBER | FUNC_CALL_OR_VARIABLE +RHS_S = STRING | NUMBER | FUNC_CALL_OR_VARIABLE */ -static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { +static CHECK_RESULT int parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { bool match; + *rhs_expr = ast_none(); return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match)); if(match) { @@ -254,6 +261,95 @@ static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { return PARSER_UNEXPECTED_TOKEN; } +static CHECK_RESULT int parser_parse_rhs_binop(Parser *self, Ast *expr); + +/* +RHS_BINOP_PAREN = '(' RHS_BINOP ')' (TOK_BINOP RHS_BINOP) +*/ +static CHECK_RESULT int parser_parse_rhs_binop_paren(Parser *self, bool *match, Ast *expr) { + bool binop_match; + Ast lhs; + Ast rhs; + BinopType binop_type; + + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, match)); + if(!*match) + return PARSER_OK; + + return_if_error(parser_parse_rhs_binop(self, &lhs)); + return_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); + + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &binop_match)); + if(!binop_match) { + *expr = lhs; + return PARSER_OK; + } + binop_type = self->tokenizer.value.binop_type; + + return_if_error(parser_parse_rhs_binop(self, &rhs)); + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); + binop_init(expr->value.binop); + expr->value.binop->type = binop_type; + expr->value.binop->lhs = lhs; + expr->value.binop->rhs = rhs; + expr->type = AST_BINOP; + return PARSER_OK; +} + +/* +RHS_BINOP_WO_PAREN = RHS_S | (RHS_S TOK_BINOP RHS_BINOP) +*/ +static CHECK_RESULT int parser_parse_rhs_binop_without_paren(Parser *self, Ast *expr) { + bool match; + Ast lhs; + Ast rhs; + BinopType binop_type; + + return_if_error(parser_parse_rhs_single_expr(self, &lhs)); + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); + if(!match) { + *expr = lhs; + return PARSER_OK; + } + binop_type = self->tokenizer.value.binop_type; + + return_if_error(parser_parse_rhs_binop(self, &rhs)); + return_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&expr->value.binop)); + binop_init(expr->value.binop); + expr->value.binop->type = binop_type; + expr->value.binop->lhs = lhs; + expr->value.binop->rhs = rhs; + expr->type = AST_BINOP; + return PARSER_OK; +} + +/* +RHS_BINOP = RHS_BINOP_PAREN | RHS_BINOP_WO_PAREN + +Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis. +*/ +int parser_parse_rhs_binop(Parser *self, Ast *expr) { + bool match; + return_if_error(parser_parse_rhs_binop_paren(self, &match, expr)); + if(match) + return PARSER_OK; + return parser_parse_rhs_binop_without_paren(self, expr); +} + +/* +RHS = RHS_BINOP ';' + +Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis. +*/ +static CHECK_RESULT int parser_parse_rhs(Parser *self, Ast *rhs_expr) { + /* TODO: If binop only contains one expression, then use that directly for @rhs_expr */ + return_if_error(parser_parse_rhs_binop(self, rhs_expr)); + + /* TODO: Implement this */ + /*binop_reorder_by_precedence(binop);*/ + return PARSER_OK; +} + /* RHS_START = CLOSURE | IMPORT | RHS */ @@ -312,6 +408,17 @@ int parser_parse_body(Parser *self, Ast *ast) { *ast = rhs_expr; } + if(rhs_expr.type == AST_BINOP) { + bool match; + return_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); + if(!match) { + /* TODO: Specify all the binop characters instead of "binop" which doesn't make sense for the user */ + self->error = tokenizer_create_error(&self->tokenizer, "Expected ';' or binop"); + return PARSER_UNEXPECTED_TOKEN; + } + return PARSER_OK; + } + /* TODO: Check for struct and tables */ if(rhs_expr.type != AST_FUNCTION_DECL) return_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON)); -- cgit v1.2.3