From fe212a5a339ec6fe69cd8ece4812930755be65f5 Mon Sep 17 00:00:00 2001 From: mathis2003 <49711425+mathis2003@users.noreply.github.com> Date: Mon, 15 Mar 2021 16:55:35 +0100 Subject: [PATCH] Forced parentheses on unclear precedence (#109) forced parentheses to resolve issue #97 --- src/compiler/parse_expr.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index ffebdcd4c..b1de6033d 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -6,6 +6,21 @@ #include "parser_internal.h" #include "bigint.h" +#define BINOP_PREC_REQ_LEN 40 +int BINOP_PREC_REQ[BINOP_PREC_REQ_LEN] = { + // bitwise operations + [BINARYOP_BIT_OR] = 1, + [BINARYOP_BIT_XOR] = 1, + [BINARYOP_BIT_AND] = 1, + + // comparison operations + [BINARYOP_GT] = 2, + [BINARYOP_GE] = 2, + [BINARYOP_LT] = 2, + [BINARYOP_LE] = 2, + [BINARYOP_NE] = 2, + [BINARYOP_EQ] = 2 +}; typedef Expr *(*ParseFn)(Context *context, Expr *); @@ -367,6 +382,23 @@ static Expr *parse_failable(Context *context, Expr *left_side) return failable; } + +bool plain_op_precedence(Expr *left_side, Expr * main_expr, Expr *right_side) +{ + int precedence_main = BINOP_PREC_REQ[main_expr->binary_expr.operator]; + if (left_side->expr_kind == EXPR_BINARY) + { + int precedence_left = BINOP_PREC_REQ[left_side->binary_expr.operator]; + return !(precedence_left && (precedence_left == precedence_main)); + } + if (right_side->expr_kind == EXPR_BINARY) + { + int precedence_right = BINOP_PREC_REQ[right_side->binary_expr.operator]; + return !(precedence_right && (precedence_right == precedence_main)); + } + return true; +} + static Expr *parse_binary(Context *context, Expr *left_side) { assert(left_side && expr_ok(left_side)); @@ -390,6 +422,13 @@ static Expr *parse_binary(Context *context, Expr *left_side) expr->binary_expr.operator = binaryop_from_token(operator_type); expr->binary_expr.left = left_side; expr->binary_expr.right = right_side; + + // check if both sides have a binary operation where the precedence is unclear. Example: a ^ b | c + if (!plain_op_precedence(left_side, expr, right_side)) + { + SEMA_TOKEN_ERROR(context->tok, "You need to add explicit parentheses."); + } + expr->span.end_loc = right_side->span.end_loc; return expr; }