From 73acd9111e60dab6d0183962702c68c1e8d6547f Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 9 Dec 2023 20:03:36 -0600 Subject: [PATCH] fixed: precedence of if-expressions --- compiler/src/parser.c | 36 +++++++++++++++++++++++------------- tests/nested-if-exprs | 3 +++ tests/nested-if-exprs.onyx | 11 +++++++++++ 3 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 tests/nested-if-exprs create mode 100644 tests/nested-if-exprs.onyx diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 0898ba6c..5199e973 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -954,19 +954,6 @@ static AstTyped* parse_factor(OnyxParser* parser) { break; } - case Token_Type_Keyword_If: { - AstIfExpression* if_expression = make_node(AstIfExpression, Ast_Kind_If_Expression); - if_expression->token = expect_token(parser, Token_Type_Keyword_If); - - if_expression->true_expr = retval; - if_expression->cond = parse_expression(parser, 0); - expect_token(parser, Token_Type_Keyword_Else); - if_expression->false_expr = parse_expression(parser, 0); - - retval = (AstTyped *) if_expression; - break; - } - case '?': { AstUnaryOp* unop = make_node(AstUnaryOp, Ast_Kind_Unary_Op); unop->token = expect_token(parser, '?'); @@ -1159,6 +1146,29 @@ static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) { while (1) { if (parser->hit_unexpected_token) return root; + if (parser->curr->type == Token_Type_Keyword_If) { + AstIfExpression *ifexpr = make_node(AstIfExpression, Ast_Kind_If_Expression); + ifexpr->token = expect_token(parser, Token_Type_Keyword_If); + + ifexpr->true_expr = root; + ifexpr->cond = parse_expression(parser, 0); + expect_token(parser, Token_Type_Keyword_Else); + ifexpr->false_expr = parse_expression(parser, 0); + + // Check for the x = y if cond else z case. + // This would parse as (x = 1) if cond else z, but that is incorrect. + if (root->kind == Ast_Kind_Binary_Op && binop_is_assignment(((AstBinaryOp *) root)->operation)) { + AstBinaryOp *r = (AstBinaryOp *) root; + ifexpr->true_expr = r->right; + r->right = (AstTyped *) ifexpr; + + } else { + root = (AstTyped *) ifexpr; + } + + goto expression_done; + } + bin_op_kind = binary_op_from_token_type(parser->curr->type); if (bin_op_kind == Binary_Op_Count) goto expression_done; if (binop_is_assignment(bin_op_kind) && !assignment_allowed) goto expression_done; diff --git a/tests/nested-if-exprs b/tests/nested-if-exprs new file mode 100644 index 00000000..cd5a5358 --- /dev/null +++ b/tests/nested-if-exprs @@ -0,0 +1,3 @@ +cmp(1, 2): -1 +cmp(2, 2): 0 +cmp(3, 2): 1 diff --git a/tests/nested-if-exprs.onyx b/tests/nested-if-exprs.onyx new file mode 100644 index 00000000..c638857a --- /dev/null +++ b/tests/nested-if-exprs.onyx @@ -0,0 +1,11 @@ +use core {printf} + +main :: () { + printf("cmp(1, 2): {}\n", cmp(1, 2)); + printf("cmp(2, 2): {}\n", cmp(2, 2)); + printf("cmp(3, 2): {}\n", cmp(3, 2)); +} + +cmp :: (a: i32, b: i32) -> i32 { + return 0 if a == b else -1 if a < b else 1; +} \ No newline at end of file -- 2.25.1