From 29318a294cc4105e0d96302a950938f096356aec Mon Sep 17 00:00:00 2001
From: Nora Abi Akar <nora.abiakar@gmail.com>
Date: Wed, 13 Oct 2021 10:38:02 +0200
Subject: [PATCH] Swap && and || operator precedence in modcc (#1710)

---
 modcc/lexer.cpp                 |  6 +++---
 modcc/parser.cpp                |  2 +-
 test/unit-modcc/test_parser.cpp | 23 +++++++++++++++++++++++
 3 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/modcc/lexer.cpp b/modcc/lexer.cpp
index 4ada753b..f89c3d32 100644
--- a/modcc/lexer.cpp
+++ b/modcc/lexer.cpp
@@ -435,10 +435,10 @@ void Lexer::binop_prec_init() {
         return;
 
     // I have taken the operator precedence from C++
-    // Note that only infix operators require precidence.
+    // Note that only infix operators require precedence.
     binop_prec_[tok::eq]       = 1;
-    binop_prec_[tok::land]     = 2;
-    binop_prec_[tok::lor]      = 3;
+    binop_prec_[tok::lor]      = 2;
+    binop_prec_[tok::land]     = 3;
     binop_prec_[tok::equality] = 4;
     binop_prec_[tok::ne]       = 4;
     binop_prec_[tok::lt]       = 5;
diff --git a/modcc/parser.cpp b/modcc/parser.cpp
index e54c9830..4b80992c 100644
--- a/modcc/parser.cpp
+++ b/modcc/parser.cpp
@@ -1333,7 +1333,7 @@ expression_ptr Parser::parse_expression(int prec, tok stop_token) {
         auto p_op = binop_precedence(op.type);
 
         // Note: all tokens that are not infix binary operators have
-        // precidence of -1, so expressions like function calls will short
+        // precedence of -1, so expressions like function calls will short
         // circuit this loop here.
         if (p_op <= prec) return lhs;
 
diff --git a/test/unit-modcc/test_parser.cpp b/test/unit-modcc/test_parser.cpp
index ba8cc363..5916704c 100644
--- a/test/unit-modcc/test_parser.cpp
+++ b/test/unit-modcc/test_parser.cpp
@@ -602,6 +602,13 @@ double eval(Expression* e) {
         case tok::minus: return lhs - rhs;
         case tok::times: return lhs * rhs;
         case tok::divide: return lhs / rhs;
+        case tok::lt:    return lhs < rhs;
+        case tok::lte:   return lhs <= rhs;
+        case tok::gt:    return lhs > rhs;
+        case tok::gte:   return lhs >= rhs;
+        case tok::lnot:  return lhs != rhs;
+        case tok::land:  return lhs && rhs;
+        case tok::lor:   return lhs || rhs;
         case tok::pow: return std::pow(lhs, rhs);
         case tok::min: return std::min(lhs, rhs);
         case tok::max: return std::max(lhs, rhs);
@@ -665,6 +672,22 @@ TEST(Parser, parse_binop) {
         EXPECT_TRUE(check_parse(e, &Parser::parse_expression, test_case.first));
         EXPECT_NEAR(eval(e.get()), test_case.second, 1e-10);
     }
+
+    std::pair<const char*, bool> bool_tests[] = {
+        {"0 && 0 || 1", true},
+        {"(0 && 0) || 1", true},
+        {"0 && (0 || 1)", false},
+        {"3<2 && 1 || 4>1", true},
+        {"(3<2 && 1) || 4>1", true},
+        {"3<2 && (1 || 4>1)", false},
+        {"(3<2) && (1 || (4>1))", false},
+    };
+
+    for (const auto& test_case: bool_tests) {
+        std::unique_ptr<Expression> e;
+        EXPECT_TRUE(check_parse(e, &Parser::parse_expression, test_case.first));
+        EXPECT_EQ(eval(e.get()), test_case.second);
+    }
 }
 
 TEST(Parser, parse_state_block) {
-- 
GitLab