diff --git a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp
index 64ff14deb191921c81e28ef1b3f36a0651ffc0e2..b6904220a9c42f2fcbfd49e8ce5881fbd9b7cf3a 100644
--- a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp
@@ -3,205 +3,59 @@
 #include <language/PEGGrammar.hpp>
 #include <language/node_processor/BinaryExpressionProcessor.hpp>
 #include <language/node_processor/ConcatExpressionProcessor.hpp>
+#include <language/utils/BinaryOperatorMangler.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
 
 ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(ASTNode& n)
 {
-  auto set_binary_operator_processor = [](ASTNode& n, const auto& operator_v) {
-    auto set_binary_operator_processor_for_data_b = [&](const auto data_a, const ASTNodeDataType& data_type_b) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-      using DataTA    = std::decay_t<decltype(data_a)>;
-
-      if constexpr (std::is_same_v<DataTA, std::string>) {
-        if constexpr (std::is_same_v<OperatorT, language::plus_op>) {
-          switch (data_type_b) {
-          case ASTNodeDataType::bool_t: {
-            n.m_node_processor = std::make_unique<ConcatExpressionProcessor<bool>>(n);
-            break;
-          }
-          case ASTNodeDataType::unsigned_int_t: {
-            n.m_node_processor = std::make_unique<ConcatExpressionProcessor<uint64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::int_t: {
-            n.m_node_processor = std::make_unique<ConcatExpressionProcessor<int64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::double_t: {
-            n.m_node_processor = std::make_unique<ConcatExpressionProcessor<double>>(n);
-            break;
-          }
-          case ASTNodeDataType::string_t: {
-            n.m_node_processor = std::make_unique<ConcatExpressionProcessor<std::string>>(n);
-            break;
-          }
-          default: {
-            throw ParseError("undefined operand type for binary operator", std::vector{n.children[1]->begin()});
-          }
-          }
-
-        } else if constexpr ((std::is_same_v<OperatorT, language::eqeq_op>) or
-                             (std::is_same_v<OperatorT, language::not_eq_op>)) {
-          if (data_type_b == ASTNodeDataType::string_t) {
-            n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, std::string>>(n);
-          } else {
-            throw ParseError("undefined operand type for binary operator", std::vector{n.begin()});
-          }
-        } else {
-          throw ParseError("undefined operand type for binary operator", std::vector{n.begin()});
-        }
-      } else if constexpr (std::is_same_v<DataTA, TinyVector<1>> or std::is_same_v<DataTA, TinyVector<2>> or
-                           std::is_same_v<DataTA, TinyVector<3>>) {
-        if ((data_type_b == ASTNodeDataType::vector_t)) {
-          if constexpr (std::is_same_v<OperatorT, language::plus_op> or std::is_same_v<OperatorT, language::minus_op> or
-                        std::is_same_v<OperatorT, language::eqeq_op> or
-                        std::is_same_v<OperatorT, language::not_eq_op>) {
-            if (data_a.dimension() == data_type_b.dimension()) {
-              n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, DataTA>>(n);
-            } else {
-              throw ParseError("incompatible dimensions of operands", std::vector{n.begin()});
-            }
-          } else {
-            throw ParseError("invalid binary operator", std::vector{n.begin()});
-          }
-        } else {
-          // LCOV_EXCL_START
-          throw ParseError("unexpected error: invalid operand type for binary operator",
-                           std::vector{n.children[1]->begin()});
-          // LCOV_EXCL_STOP
-        }
-      } else {
-        switch (data_type_b) {
-        case ASTNodeDataType::bool_t: {
-          n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, bool>>(n);
-          break;
-        }
-        case ASTNodeDataType::unsigned_int_t: {
-          n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, uint64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::int_t: {
-          n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, int64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::double_t: {
-          n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, double>>(n);
-          break;
-        }
-        case ASTNodeDataType::vector_t: {
-          if constexpr (std::is_same_v<OperatorT, language::multiply_op>) {
-            switch (data_type_b.dimension()) {
-            case 1: {
-              n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, TinyVector<1>>>(n);
-              break;
-            }
-            case 2: {
-              n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, TinyVector<2>>>(n);
-              break;
-            }
-            case 3: {
-              n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, TinyVector<3>>>(n);
-              break;
-            }
-              // LCOV_EXCL_START
-            default: {
-              throw ParseError("unexpected error: invalid dimension", std::vector{n.children[0]->begin()});
-            }
-              // LCOV_EXCL_STOP
-            }
-            break;
-          }
-        }
-        default: {
-          throw ParseError("undefined operand type for binary operator", std::vector{n.children[1]->begin()});
-        }
-        }
-      }
-    };
-
-    auto set_binary_operator_processor_for_data_a = [&](const ASTNodeDataType& data_type_a) {
-      const ASTNodeDataType data_type_b = n.children[1]->m_data_type;
-      switch (data_type_a) {
-      case ASTNodeDataType::bool_t: {
-        set_binary_operator_processor_for_data_b(bool{}, data_type_b);
-        break;
-      }
-      case ASTNodeDataType::unsigned_int_t: {
-        set_binary_operator_processor_for_data_b(uint64_t{}, data_type_b);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        set_binary_operator_processor_for_data_b(int64_t{}, data_type_b);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        set_binary_operator_processor_for_data_b(double{}, data_type_b);
-        break;
-      }
-      case ASTNodeDataType::string_t: {
-        set_binary_operator_processor_for_data_b(std::string{}, data_type_b);
-        break;
-      }
-      case ASTNodeDataType::vector_t: {
-        switch (data_type_a.dimension()) {
-        case 1: {
-          set_binary_operator_processor_for_data_b(TinyVector<1>{}, data_type_b);
-          break;
-        }
-        case 2: {
-          set_binary_operator_processor_for_data_b(TinyVector<2>{}, data_type_b);
-          break;
-        }
-        case 3: {
-          set_binary_operator_processor_for_data_b(TinyVector<3>{}, data_type_b);
-          break;
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: invalid dimension", std::vector{n.children[0]->begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-        break;
-      }
-      default: {
-        throw ParseError("undefined operand type for binary operator", std::vector{n.children[0]->begin()});
-      }
-      }
-    };
-
-    set_binary_operator_processor_for_data_a(n.children[0]->m_data_type);
-  };
-
-  if (n.is_type<language::multiply_op>()) {
-    set_binary_operator_processor(n, language::multiply_op{});
-  } else if (n.is_type<language::divide_op>()) {
-    set_binary_operator_processor(n, language::divide_op{});
-  } else if (n.is_type<language::plus_op>()) {
-    set_binary_operator_processor(n, language::plus_op{});
-  } else if (n.is_type<language::minus_op>()) {
-    set_binary_operator_processor(n, language::minus_op{});
-
-  } else if (n.is_type<language::or_op>()) {
-    set_binary_operator_processor(n, language::or_op{});
-  } else if (n.is_type<language::and_op>()) {
-    set_binary_operator_processor(n, language::and_op{});
-  } else if (n.is_type<language::xor_op>()) {
-    set_binary_operator_processor(n, language::xor_op{});
-
-  } else if (n.is_type<language::greater_op>()) {
-    set_binary_operator_processor(n, language::greater_op{});
-  } else if (n.is_type<language::greater_or_eq_op>()) {
-    set_binary_operator_processor(n, language::greater_or_eq_op{});
-  } else if (n.is_type<language::lesser_op>()) {
-    set_binary_operator_processor(n, language::lesser_op{});
-  } else if (n.is_type<language::lesser_or_eq_op>()) {
-    set_binary_operator_processor(n, language::lesser_or_eq_op{});
-  } else if (n.is_type<language::eqeq_op>()) {
-    set_binary_operator_processor(n, language::eqeq_op{});
-  } else if (n.is_type<language::not_eq_op>()) {
-    set_binary_operator_processor(n, language::not_eq_op{});
+  const ASTNodeDataType& lhs_data_type = n.children[0]->m_data_type;
+  const ASTNodeDataType& rhs_data_type = n.children[1]->m_data_type;
+
+  const std::string binary_operator_name = [&]() -> std::string {
+    if (n.is_type<language::multiply_op>()) {
+      return binaryOperatorMangler<language::multiply_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::divide_op>()) {
+      return binaryOperatorMangler<language::divide_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::plus_op>()) {
+      return binaryOperatorMangler<language::plus_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::minus_op>()) {
+      return binaryOperatorMangler<language::minus_op>(lhs_data_type, rhs_data_type);
+
+    } else if (n.is_type<language::or_op>()) {
+      return binaryOperatorMangler<language::or_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::and_op>()) {
+      return binaryOperatorMangler<language::and_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::xor_op>()) {
+      return binaryOperatorMangler<language::xor_op>(lhs_data_type, rhs_data_type);
+
+    } else if (n.is_type<language::greater_op>()) {
+      return binaryOperatorMangler<language::greater_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::greater_or_eq_op>()) {
+      return binaryOperatorMangler<language::greater_or_eq_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::lesser_op>()) {
+      return binaryOperatorMangler<language::lesser_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::lesser_or_eq_op>()) {
+      return binaryOperatorMangler<language::lesser_or_eq_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::eqeq_op>()) {
+      return binaryOperatorMangler<language::eqeq_op>(lhs_data_type, rhs_data_type);
+    } else if (n.is_type<language::not_eq_op>()) {
+      return binaryOperatorMangler<language::not_eq_op>(lhs_data_type, rhs_data_type);
+    } else {
+      throw ParseError("unexpected error: undefined binary operator", std::vector{n.begin()});
+    }
+  }();
+
+  const auto& optional_processor_builder =
+    OperatorRepository::instance().getBinaryProcessorBuilder(binary_operator_name);
+
+  if (optional_processor_builder.has_value()) {
+    n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
   } else {
-    throw ParseError("unexpected error: undefined binary operator", std::vector{n.begin()});
+    std::ostringstream error_message;
+    error_message << "undefined binary operator type: ";
+    error_message << rang::fgB::red << binary_operator_name << rang::fg::reset;
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
   }
 }
diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp
index 74806be26a1d95f07a33cf682f78a407a11845d5..7c93b50527bbae5c352d62159e40d0eba3bb7aad 100644
--- a/src/language/ast/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp
@@ -352,11 +352,22 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       const ASTNode& test_node = *n.children[1];
       ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
-    } else if (n.is_type<language::unary_not>()) {
+    } else if (n.is_type<language::unary_not>() or n.is_type<language::unary_minus>()) {
       auto& operator_repository = OperatorRepository::instance();
 
-      auto optional_value_type = operator_repository.getUnaryOperatorValueType(
-        unaryOperatorMangler<language::unary_not>(n.children[0]->m_data_type));
+      auto optional_value_type = [&] {
+        if (n.is_type<language::unary_not>()) {
+          return operator_repository.getUnaryOperatorValueType(
+            unaryOperatorMangler<language::unary_not>(n.children[0]->m_data_type));
+        } else if (n.is_type<language::unary_minus>()) {
+          return operator_repository.getUnaryOperatorValueType(
+            unaryOperatorMangler<language::unary_minus>(n.children[0]->m_data_type));
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid unary operator type");
+          // LCOV_EXCL_STOP
+        }
+      }();
 
       if (optional_value_type.has_value()) {
         n.m_data_type = optional_value_type.value();
@@ -368,34 +379,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         throw ParseError(message.str(), n.begin());
       }
 
-    } else if (n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or
-               n.is_type<language::greater_op>() or n.is_type<language::greater_or_eq_op>() or
-               n.is_type<language::eqeq_op>() or n.is_type<language::not_eq_op>()) {
-      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
-    } else if (n.is_type<language::and_op>() or n.is_type<language::or_op>() or n.is_type<language::xor_op>()) {
-      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
-
-      const ASTNode& lhs_node = *n.children[0];
-      ASTNodeNaturalConversionChecker{lhs_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
-
-      const ASTNode& rhs_node = *n.children[1];
-      ASTNodeNaturalConversionChecker{rhs_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
-
-    } else if (n.is_type<language::unary_minus>()) {
-      auto& operator_repository = OperatorRepository::instance();
-
-      auto optional_value_type = operator_repository.getUnaryOperatorValueType(
-        unaryOperatorMangler<language::unary_minus>(n.children[0]->m_data_type));
-
-      if (optional_value_type.has_value()) {
-        n.m_data_type = optional_value_type.value();
-      } else {
-        std::ostringstream message;
-        message << "undefined unary operator\n"
-                << "note: unexpected operand type " << rang::fgB::red << dataTypeName(n.children[0]->m_data_type)
-                << rang::style::reset;
-        throw ParseError(message.str(), n.begin());
-      }
     } else if (n.is_type<language::unary_plusplus>() or n.is_type<language::unary_minusminus>() or
                n.is_type<language::post_plusplus>() or n.is_type<language::post_minusminus>()) {
       auto& operator_repository = OperatorRepository::instance();
@@ -424,28 +407,80 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         n.m_data_type = optional_value_type.value();
       } else {
         std::ostringstream message;
-        message << "undefined unary operator\n"
+        message << "undefined increment/decrement operator\n"
                 << "note: unexpected operand type " << rang::fgB::red << dataTypeName(n.children[0]->m_data_type)
                 << rang::style::reset;
         throw ParseError(message.str(), n.begin());
       }
 
-      n.m_data_type = n.children[0]->m_data_type;
     } else if (n.is_type<language::plus_op>() or n.is_type<language::minus_op>() or
-               n.is_type<language::multiply_op>() or n.is_type<language::divide_op>()) {
+               n.is_type<language::multiply_op>() or n.is_type<language::divide_op>() or
+               n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or
+               n.is_type<language::greater_op>() or n.is_type<language::greater_or_eq_op>() or
+               n.is_type<language::eqeq_op>() or n.is_type<language::not_eq_op>() or n.is_type<language::and_op>() or
+               n.is_type<language::or_op>() or n.is_type<language::xor_op>()) {
       const ASTNodeDataType type_0 = n.children[0]->m_data_type;
       const ASTNodeDataType type_1 = n.children[1]->m_data_type;
-      if ((type_0 == ASTNodeDataType::bool_t) and (type_1 == ASTNodeDataType::bool_t)) {
-        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+      auto& operator_repository    = OperatorRepository::instance();
+
+      auto optional_value_type = [&] {
+        if (n.is_type<language::plus_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::plus_op>(type_0, type_1));
+        } else if (n.is_type<language::minus_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::minus_op>(type_0, type_1));
+        } else if (n.is_type<language::multiply_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::multiply_op>(type_0, type_1));
+        } else if (n.is_type<language::divide_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::divide_op>(type_0, type_1));
+
+        } else if (n.is_type<language::lesser_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::lesser_op>(type_0, type_1));
+        } else if (n.is_type<language::lesser_or_eq_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::lesser_or_eq_op>(type_0, type_1));
+        } else if (n.is_type<language::greater_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::greater_op>(type_0, type_1));
+        } else if (n.is_type<language::greater_or_eq_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::greater_or_eq_op>(type_0, type_1));
+        } else if (n.is_type<language::eqeq_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::eqeq_op>(type_0, type_1));
+        } else if (n.is_type<language::not_eq_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::not_eq_op>(type_0, type_1));
+
+        } else if (n.is_type<language::and_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::and_op>(type_0, type_1));
+        } else if (n.is_type<language::or_op>()) {
+          return operator_repository.getBinaryOperatorValueType(binaryOperatorMangler<language::or_op>(type_0, type_1));
+        } else if (n.is_type<language::xor_op>()) {
+          return operator_repository.getBinaryOperatorValueType(
+            binaryOperatorMangler<language::xor_op>(type_0, type_1));
+
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("unexpected operator type");
+          // LCOV_EXCL_STOP
+        }
+      }();
+
+      if (optional_value_type.has_value()) {
+        n.m_data_type = optional_value_type.value();
       } else {
-        n.m_data_type = dataTypePromotion(type_0, type_1);
-      }
-      if (n.m_data_type == ASTNodeDataType::undefined_t) {
         std::ostringstream message;
         message << "undefined binary operator\n"
                 << "note: incompatible operand types " << dataTypeName(type_0) << " and " << dataTypeName(type_1);
         throw ParseError(message.str(), n.begin());
       }
+
     } else if (n.is_type<language::function_evaluation>()) {
       if (n.children[0]->m_data_type == ASTNodeDataType::function_t) {
         const std::string& function_name = n.children[0]->string();
diff --git a/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp b/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp
index c877d3ca2b8f728cf3370ec8bef2fc7aaf7a557e..88b1758e757797d0844a06185105480e341635c8 100644
--- a/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp
@@ -26,7 +26,9 @@ ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n)
     } else if (n.is_type<language::post_plusplus>()) {
       return incDecOperatorMangler<language::post_plusplus>(data_type);
     } else {
+      // LCOV_EXCL_START
       throw ParseError("unexpected error: undefined inc/dec operator", std::vector{n.begin()});
+      // LCOV_EXCL_STOP
     }
   }();
 
diff --git a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
index bfba2e0f8325986ec08f32167fb162f60e758a57..e011e693000d5b68de6fdd0ea98b4e7afe01a6f6 100644
--- a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -15,7 +15,9 @@ ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(AST
     } else if (n.is_type<language::unary_not>()) {
       return unaryOperatorMangler<language::unary_not>(data_type);
     } else {
+      // LCOV_EXCL_START
       throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
+      // LCOV_EXCL_STOP
     }
   }();
 
diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp
index 8f5d9c3220cf3018104d5d53e2036b9bb8217214..cfbff72617d7b99e68ea9693eca96fa718c3f918 100644
--- a/src/language/node_processor/BinaryExpressionProcessor.hpp
+++ b/src/language/node_processor/BinaryExpressionProcessor.hpp
@@ -6,6 +6,8 @@
 #include <language/node_processor/INodeProcessor.hpp>
 #include <language/utils/ParseError.hpp>
 
+#include <type_traits>
+
 template <typename Op>
 struct BinOp;
 
@@ -154,68 +156,49 @@ struct BinOp<language::divide_op>
   }
 };
 
-template <typename BinaryOpT, typename A_DataT, typename B_DataT>
-class BinaryExpressionProcessor final : public INodeProcessor
+template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT>
+struct BinaryExpressionProcessor final : public INodeProcessor
 {
+ private:
   ASTNode& m_node;
 
   PUGS_INLINE DataVariant
   _eval(const DataVariant& a, const DataVariant& b)
   {
-    // Add 'signed' when necessary to avoid signed/unsigned comparison warnings
-    if constexpr ((not(std::is_same_v<A_DataT, bool> or std::is_same_v<B_DataT, bool>)) and
-                  (std::is_same_v<BinaryOpT, language::and_op> or std::is_same_v<BinaryOpT, language::or_op> or
-                   std::is_same_v<BinaryOpT, language::xor_op> or std::is_same_v<BinaryOpT, language::eqeq_op> or
-                   std::is_same_v<BinaryOpT, language::not_eq_op> or std::is_same_v<BinaryOpT, language::lesser_op> or
-                   std::is_same_v<BinaryOpT, language::lesser_or_eq_op> or
-                   std::is_same_v<BinaryOpT, language::greater_op> or
-                   std::is_same_v<BinaryOpT, language::greater_or_eq_op>) and
-                  (std::is_signed_v<A_DataT> xor std::is_signed_v<B_DataT>)) {
-      if constexpr (std::is_unsigned_v<A_DataT>) {
-        using signed_A_DataT          = std::make_signed_t<A_DataT>;
-        const signed_A_DataT signed_a = static_cast<signed_A_DataT>(std::get<A_DataT>(a));
-        return BinOp<BinaryOpT>().eval(signed_a, std::get<B_DataT>(b));
+    if constexpr (std::is_arithmetic_v<A_DataT> and std::is_arithmetic_v<B_DataT>) {
+      if constexpr (std::is_signed_v<A_DataT> and not std::is_signed_v<B_DataT>) {
+        if constexpr (std::is_same_v<B_DataT, bool>) {
+          return static_cast<ValueT>(
+            BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), static_cast<int64_t>(std::get<B_DataT>(b))));
+        } else {
+          return static_cast<ValueT>(
+            BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::make_signed_t<B_DataT>(std::get<B_DataT>(b))));
+        }
+
+      } else if constexpr (not std::is_signed_v<A_DataT> and std::is_signed_v<B_DataT>) {
+        if constexpr (std::is_same_v<A_DataT, bool>) {
+          return static_cast<ValueT>(
+            BinOp<BinaryOpT>().eval(static_cast<int64_t>(std::get<A_DataT>(a)), std::get<B_DataT>(b)));
+        } else {
+          return static_cast<ValueT>(
+            BinOp<BinaryOpT>().eval(std::make_signed_t<A_DataT>(std::get<A_DataT>(a)), std::get<B_DataT>(b)));
+        }
       } else {
-        using signed_B_DataT          = std::make_signed_t<B_DataT>;
-        const signed_B_DataT signed_b = static_cast<signed_B_DataT>(std::get<B_DataT>(b));
-        return BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), signed_b);
+        return static_cast<ValueT>(BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)));
       }
     } else {
-      auto result = BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b));
-      if constexpr (std::is_same_v<decltype(result), int>) {
-        return static_cast<int64_t>(result);
-      } else {
-        return result;
-      }
+      return static_cast<ValueT>(BinOp<BinaryOpT>().eval(std::get<A_DataT>(a), std::get<B_DataT>(b)));
     }
   }
 
-  static inline const bool m_is_defined{[] {
-    if constexpr (std::is_same_v<BinaryOpT, language::xor_op>) {
-      return std::is_same_v<std::decay_t<A_DataT>, std::decay_t<B_DataT>> and std::is_integral_v<std::decay_t<A_DataT>>;
-    }
-    return true;
-  }()};
-
  public:
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
-    if constexpr (m_is_defined) {
-      return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
-    } else {
-      return {};   // LCOV_EXCL_LINE
-    }
+    return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy));
   }
 
-  BinaryExpressionProcessor(ASTNode& node) : m_node{node}
-  {
-    if constexpr (not m_is_defined) {
-      // LCOV_EXCL_START
-      throw ParseError("invalid operands to binary expression", std::vector{m_node.begin()});
-      // LCOV_EXCL_STOP
-    }
-  }
+  BinaryExpressionProcessor(ASTNode& node) : m_node{node} {}
 };
 
 #endif   // BINARY_EXPRESSION_PROCESSOR_HPP
diff --git a/src/language/node_processor/ConcatExpressionProcessor.hpp b/src/language/node_processor/ConcatExpressionProcessor.hpp
index e47178494fe2bf88f8c7e5bebf9455c58732b08e..bb6357c87124110e973730ff6fb3eb9d5fdde5a3 100644
--- a/src/language/node_processor/ConcatExpressionProcessor.hpp
+++ b/src/language/node_processor/ConcatExpressionProcessor.hpp
@@ -16,8 +16,12 @@ class ConcatExpressionProcessor final : public INodeProcessor
   {
     if constexpr (std::is_same_v<B_DataT, std::string>) {
       return a + std::get<B_DataT>(b);
-    } else {
+    } else if constexpr (std::is_arithmetic_v<B_DataT>) {
       return a + std::to_string(std::get<B_DataT>(b));
+    } else {
+      std::ostringstream os;
+      os << a << b;
+      return os.str();
     }
   }
 
diff --git a/src/language/node_processor/INodeProcessor.hpp b/src/language/node_processor/INodeProcessor.hpp
index ce06b9484f7c7b141861bddfc88f5b5c3bf9eecc..2c35b6c49cadd69536c415f5a86e5786c953a86c 100644
--- a/src/language/node_processor/INodeProcessor.hpp
+++ b/src/language/node_processor/INodeProcessor.hpp
@@ -8,8 +8,9 @@
 #include <string>
 #include <typeinfo>
 
-struct INodeProcessor
+class INodeProcessor
 {
+ public:
   virtual DataVariant execute(ExecutionPolicy& exec_policy) = 0;
 
   std::string
diff --git a/src/language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp b/src/language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..758117182df0c170c1c00c00ea38938668eae2c6
--- /dev/null
+++ b/src/language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp
@@ -0,0 +1,34 @@
+#ifndef BASIC_BINARY_OPERATOR_REGISTER_COMPARISON_OF_HPP
+#define BASIC_BINARY_OPERATOR_REGISTER_COMPARISON_OF_HPP
+
+#include <language/utils/BinaryOperatorProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+template <typename A_DataT, typename B_DataT>
+struct BasicBinaryOperatorRegisterComparisonOf
+{
+  BasicBinaryOperatorRegisterComparisonOf()
+  {
+    OperatorRepository& repository = OperatorRepository::instance();
+
+    repository.addBinaryOperator<language::eqeq_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::eqeq_op, bool, A_DataT, B_DataT>>());
+
+    repository.addBinaryOperator<language::not_eq_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::not_eq_op, bool, A_DataT, B_DataT>>());
+
+    repository.addBinaryOperator<language::greater_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::greater_op, bool, A_DataT, B_DataT>>());
+
+    repository.addBinaryOperator<language::greater_or_eq_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::greater_or_eq_op, bool, A_DataT, B_DataT>>());
+
+    repository.addBinaryOperator<language::lesser_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::lesser_op, bool, A_DataT, B_DataT>>());
+
+    repository.addBinaryOperator<language::lesser_or_eq_op>(
+      std::make_shared<BinaryOperatorProcessorBuilder<language::lesser_or_eq_op, bool, A_DataT, B_DataT>>());
+  }
+};
+
+#endif   // BASIC_BINARY_OPERATOR_REGISTER_COMPARISON_OF_HPP
diff --git a/src/language/utils/BinaryOperatorMangler.hpp b/src/language/utils/BinaryOperatorMangler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f3648f3fb860a6207b70ad712aee9935b669e493
--- /dev/null
+++ b/src/language/utils/BinaryOperatorMangler.hpp
@@ -0,0 +1,67 @@
+#ifndef BINARY_OPERATOR_MANGLER_HPP
+#define BINARY_OPERATOR_MANGLER_HPP
+
+#include <language/utils/ASTNodeDataType.hpp>
+#include <utils/Exceptions.hpp>
+
+#include <string>
+
+namespace language
+{
+struct multiply_op;
+struct divide_op;
+struct plus_op;
+struct minus_op;
+
+struct or_op;
+struct and_op;
+struct xor_op;
+
+struct greater_op;
+struct greater_or_eq_op;
+struct lesser_op;
+struct lesser_or_eq_op;
+struct eqeq_op;
+struct not_eq_op;
+}   // namespace language
+
+template <typename BinaryOperatorT>
+std::string
+binaryOperatorMangler(const ASTNodeDataType& lhs_data_type, const ASTNodeDataType& rhs_data_type)
+{
+  const std::string operator_name = [] {
+    if constexpr (std::is_same_v<BinaryOperatorT, language::multiply_op>) {
+      return "*";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::divide_op>) {
+      return "/";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::plus_op>) {
+      return "+";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::minus_op>) {
+      return "-";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::or_op>) {
+      return "or";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::and_op>) {
+      return "and";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::xor_op>) {
+      return "xor";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::greater_op>) {
+      return ">";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::greater_or_eq_op>) {
+      return ">=";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::lesser_op>) {
+      return "<";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::lesser_or_eq_op>) {
+      return "<=";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::eqeq_op>) {
+      return "==";
+    } else if constexpr (std::is_same_v<BinaryOperatorT, language::not_eq_op>) {
+      return "!=";
+    } else {
+      static_assert(std::is_same_v<language::multiply_op, BinaryOperatorT>, "undefined binary operator");
+    }
+  }();
+
+  return dataTypeName(lhs_data_type) + " " + operator_name + " " + dataTypeName(rhs_data_type);
+}
+
+#endif   // BINARY_OPERATOR_MANGLER_HPP
diff --git a/src/language/utils/BinaryOperatorProcessorBuilder.hpp b/src/language/utils/BinaryOperatorProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b8cb572d1e79c1882ed0288d79a4b73c6c130e5c
--- /dev/null
+++ b/src/language/utils/BinaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,43 @@
+#ifndef BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/BinaryExpressionProcessor.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/IBinaryOperatorProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename OperatorT, typename ValueT, typename A_DataT, typename B_DataT>
+class BinaryOperatorProcessorBuilder final : public IBinaryOperatorProcessorBuilder
+{
+ public:
+  BinaryOperatorProcessorBuilder() = default;
+
+  ASTNodeDataType
+  getDataTypeOfA() const
+  {
+    return ast_node_data_type_from<A_DataT>;
+  }
+
+  ASTNodeDataType
+  getDataTypeOfB() const
+  {
+    return ast_node_data_type_from<B_DataT>;
+  }
+
+  ASTNodeDataType
+  getReturnValueType() const
+  {
+    return ast_node_data_type_from<ValueT>;
+  }
+
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<BinaryExpressionProcessor<OperatorT, ValueT, A_DataT, B_DataT>>(node);
+  }
+};
+
+#endif   // BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForB.cpp b/src/language/utils/BinaryOperatorRegisterForB.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cba803aaf3e3d7d4c72be7b69ca1a835203a49b2
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForB.cpp
@@ -0,0 +1,70 @@
+#include <language/utils/BinaryOperatorRegisterForB.hpp>
+
+#include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp>
+
+void
+BinaryOperatorRegisterForB::_register_comparisons()
+{
+  BasicBinaryOperatorRegisterComparisonOf<bool, bool>{};
+}
+
+void
+BinaryOperatorRegisterForB::_register_logical_operators()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::and_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::and_op, bool, bool, bool>>());
+
+  repository.addBinaryOperator<language::or_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::or_op, bool, bool, bool>>());
+
+  repository.addBinaryOperator<language::xor_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::xor_op, bool, bool, bool>>());
+}
+
+void
+BinaryOperatorRegisterForB::_register_plus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::plus_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, uint64_t, bool, bool>>());
+}
+
+void
+BinaryOperatorRegisterForB::_register_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::minus_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, int64_t, bool, bool>>());
+}
+
+void
+BinaryOperatorRegisterForB::_register_multiply()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::multiply_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, uint64_t, bool, bool>>());
+}
+
+void
+BinaryOperatorRegisterForB::_register_divide()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::divide_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, uint64_t, bool, bool>>());
+}
+
+BinaryOperatorRegisterForB::BinaryOperatorRegisterForB()
+{
+  this->_register_comparisons();
+  this->_register_logical_operators();
+  this->_register_plus();
+  this->_register_minus();
+  this->_register_multiply();
+  this->_register_divide();
+}
diff --git a/src/language/utils/BinaryOperatorRegisterForB.hpp b/src/language/utils/BinaryOperatorRegisterForB.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..651411bf7f2cd8e8386d26c071220d36cb79a691
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForB.hpp
@@ -0,0 +1,18 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_B_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_B_HPP
+
+class BinaryOperatorRegisterForB
+{
+ private:
+  void _register_comparisons();
+  void _register_logical_operators();
+  void _register_plus();
+  void _register_minus();
+  void _register_multiply();
+  void _register_divide();
+
+ public:
+  BinaryOperatorRegisterForB();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_B_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForN.cpp b/src/language/utils/BinaryOperatorRegisterForN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66d589405545924af9e2de137f7738c9b40b8430
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForN.cpp
@@ -0,0 +1,50 @@
+#include <language/utils/BinaryOperatorRegisterForN.hpp>
+
+#include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp>
+
+void
+BinaryOperatorRegisterForN::_register_comparisons()
+{
+  BasicBinaryOperatorRegisterComparisonOf<bool, uint64_t>{};
+  BasicBinaryOperatorRegisterComparisonOf<uint64_t, bool>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<uint64_t, uint64_t>{};
+}
+
+template <typename OperatorT>
+void
+BinaryOperatorRegisterForN::_register_arithmetic()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, uint64_t, uint64_t, bool>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, uint64_t, bool, uint64_t>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, uint64_t, uint64_t, uint64_t>>());
+}
+
+void
+BinaryOperatorRegisterForN::_register_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::minus_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, int64_t, uint64_t, bool>>());
+  repository.addBinaryOperator<language::minus_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, int64_t, bool, uint64_t>>());
+
+  repository.addBinaryOperator<language::minus_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, int64_t, uint64_t, uint64_t>>());
+}
+
+BinaryOperatorRegisterForN::BinaryOperatorRegisterForN()
+{
+  this->_register_comparisons();
+  this->_register_arithmetic<language::plus_op>();
+  this->_register_minus();
+  this->_register_arithmetic<language::multiply_op>();
+  this->_register_arithmetic<language::divide_op>();
+}
diff --git a/src/language/utils/BinaryOperatorRegisterForN.hpp b/src/language/utils/BinaryOperatorRegisterForN.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..80dc52b013f36e05e08f7bf561f2ac3b41ccbfbf
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForN.hpp
@@ -0,0 +1,16 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_N_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_N_HPP
+
+class BinaryOperatorRegisterForN
+{
+ private:
+  template <typename OperatorT>
+  void _register_arithmetic();
+  void _register_comparisons();
+  void _register_minus();
+
+ public:
+  BinaryOperatorRegisterForN();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_N_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForR.cpp b/src/language/utils/BinaryOperatorRegisterForR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f69988925e373fbd7369bff3d0bb87860b1aa3d
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForR.cpp
@@ -0,0 +1,52 @@
+#include <language/utils/BinaryOperatorRegisterForR.hpp>
+
+#include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp>
+
+void
+BinaryOperatorRegisterForR::_register_comparisons()
+{
+  BasicBinaryOperatorRegisterComparisonOf<bool, double>{};
+  BasicBinaryOperatorRegisterComparisonOf<double, bool>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<uint64_t, double>{};
+  BasicBinaryOperatorRegisterComparisonOf<double, uint64_t>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<int64_t, double>{};
+  BasicBinaryOperatorRegisterComparisonOf<double, int64_t>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<double, double>{};
+}
+
+template <typename OperatorT>
+void
+BinaryOperatorRegisterForR::_register_arithmetic()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, double, bool>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, bool, double>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, double, uint64_t>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, uint64_t, double_t>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, double, int64_t>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, int64_t, double_t>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, double, double, double>>());
+}
+
+BinaryOperatorRegisterForR::BinaryOperatorRegisterForR()
+{
+  this->_register_comparisons();
+  this->_register_arithmetic<language::plus_op>();
+  this->_register_arithmetic<language::minus_op>();
+  this->_register_arithmetic<language::multiply_op>();
+  this->_register_arithmetic<language::divide_op>();
+}
diff --git a/src/language/utils/BinaryOperatorRegisterForR.hpp b/src/language/utils/BinaryOperatorRegisterForR.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cbde82fb3d36e565ef84d99b95b58c6c0556eb01
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForR.hpp
@@ -0,0 +1,15 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_R_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_R_HPP
+
+class BinaryOperatorRegisterForR
+{
+ private:
+  template <typename OperatorT>
+  void _register_arithmetic();
+  void _register_comparisons();
+
+ public:
+  BinaryOperatorRegisterForR();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_R_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForRn.cpp b/src/language/utils/BinaryOperatorRegisterForRn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..41e5b031f7e3db02d8e59a9962e028c046f813a8
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForRn.cpp
@@ -0,0 +1,67 @@
+#include <language/utils/BinaryOperatorRegisterForRn.hpp>
+
+#include <language/utils/BinaryOperatorProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+template <size_t Dimension>
+void
+BinaryOperatorRegisterForRn<Dimension>::_register_comparisons()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  using Rn = TinyVector<Dimension>;
+
+  repository.addBinaryOperator<language::eqeq_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::eqeq_op, bool, Rn, Rn>>());
+
+  repository.addBinaryOperator<language::not_eq_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::not_eq_op, bool, Rn, Rn>>());
+}
+
+template <size_t Dimension>
+void
+BinaryOperatorRegisterForRn<Dimension>::_register_product_by_a_scalar()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  using Rn = TinyVector<Dimension>;
+
+  repository.addBinaryOperator<language::multiply_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rn, bool, Rn>>());
+
+  repository.addBinaryOperator<language::multiply_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rn, uint64_t, Rn>>());
+
+  repository.addBinaryOperator<language::multiply_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rn, int64_t, Rn>>());
+
+  repository.addBinaryOperator<language::multiply_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rn, double, Rn>>());
+}
+
+template <size_t Dimension>
+template <typename OperatorT>
+void
+BinaryOperatorRegisterForRn<Dimension>::_register_arithmetic()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  using Rn = TinyVector<Dimension>;
+
+  repository.addBinaryOperator<OperatorT>(std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, Rn, Rn, Rn>>());
+}
+
+template <size_t Dimension>
+BinaryOperatorRegisterForRn<Dimension>::BinaryOperatorRegisterForRn()
+{
+  this->_register_comparisons();
+
+  this->_register_product_by_a_scalar();
+
+  this->_register_arithmetic<language::plus_op>();
+  this->_register_arithmetic<language::minus_op>();
+}
+
+template class BinaryOperatorRegisterForRn<1>;
+template class BinaryOperatorRegisterForRn<2>;
+template class BinaryOperatorRegisterForRn<3>;
diff --git a/src/language/utils/BinaryOperatorRegisterForRn.hpp b/src/language/utils/BinaryOperatorRegisterForRn.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b9f27d4165d236b913e3393e342a144019fe6015
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForRn.hpp
@@ -0,0 +1,21 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_RN_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_RN_HPP
+
+#include <cstdlib>
+
+template <size_t Dimension>
+class BinaryOperatorRegisterForRn
+{
+ private:
+  void _register_comparisons();
+
+  void _register_product_by_a_scalar();
+
+  template <typename OperatorT>
+  void _register_arithmetic();
+
+ public:
+  BinaryOperatorRegisterForRn();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_RN_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForString.cpp b/src/language/utils/BinaryOperatorRegisterForString.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1323e21ea0cd17cca712a286c6cf4192447e88e4
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForString.cpp
@@ -0,0 +1,40 @@
+#include <language/utils/BinaryOperatorRegisterForString.hpp>
+
+#include <language/utils/BinaryOperatorProcessorBuilder.hpp>
+#include <language/utils/ConcatExpressionProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+BinaryOperatorRegisterForString::_register_comparisons()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::eqeq_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::eqeq_op, bool, std::string, std::string>>());
+
+  repository.addBinaryOperator<language::not_eq_op>(
+    std::make_shared<BinaryOperatorProcessorBuilder<language::not_eq_op, bool, std::string, std::string>>());
+}
+
+template <typename RHS_T>
+void
+BinaryOperatorRegisterForString::_register_concat()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<language::plus_op>(std::make_shared<ConcatExpressionProcessorBuilder<RHS_T>>());
+}
+
+BinaryOperatorRegisterForString::BinaryOperatorRegisterForString()
+{
+  this->_register_comparisons();
+
+  this->_register_concat<bool>();
+  this->_register_concat<unsigned long>();
+  this->_register_concat<long>();
+  this->_register_concat<double>();
+  this->_register_concat<TinyVector<1>>();
+  this->_register_concat<TinyVector<2>>();
+  this->_register_concat<TinyVector<3>>();
+  this->_register_concat<std::string>();
+}
diff --git a/src/language/utils/BinaryOperatorRegisterForString.hpp b/src/language/utils/BinaryOperatorRegisterForString.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..36af13ee6442086244ee5234ad496f3580f79c22
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForString.hpp
@@ -0,0 +1,16 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_STRING_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_STRING_HPP
+
+class BinaryOperatorRegisterForString
+{
+ private:
+  void _register_comparisons();
+
+  template <typename RHS_T>
+  void _register_concat();
+
+ public:
+  BinaryOperatorRegisterForString();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_STRING_HPP
diff --git a/src/language/utils/BinaryOperatorRegisterForZ.cpp b/src/language/utils/BinaryOperatorRegisterForZ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc8b22d117a8bebc557efff84083b8e45dcf8602
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForZ.cpp
@@ -0,0 +1,44 @@
+#include <language/utils/BinaryOperatorRegisterForZ.hpp>
+
+#include <language/utils/BasicBinaryOperatorRegisterComparisonOf.hpp>
+
+void
+BinaryOperatorRegisterForZ::_register_comparisons()
+{
+  BasicBinaryOperatorRegisterComparisonOf<bool, int64_t>{};
+  BasicBinaryOperatorRegisterComparisonOf<int64_t, bool>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<uint64_t, int64_t>{};
+  BasicBinaryOperatorRegisterComparisonOf<int64_t, uint64_t>{};
+
+  BasicBinaryOperatorRegisterComparisonOf<int64_t, int64_t>{};
+}
+
+template <typename OperatorT>
+void
+BinaryOperatorRegisterForZ::_register_arithmetic()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, int64_t, int64_t, bool>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, int64_t, bool, int64_t>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, int64_t, int64_t, uint64_t>>());
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, int64_t, uint64_t, int64_t>>());
+
+  repository.addBinaryOperator<OperatorT>(
+    std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, int64_t, int64_t, int64_t>>());
+}
+
+BinaryOperatorRegisterForZ::BinaryOperatorRegisterForZ()
+{
+  this->_register_comparisons();
+  this->_register_arithmetic<language::plus_op>();
+  this->_register_arithmetic<language::minus_op>();
+  this->_register_arithmetic<language::multiply_op>();
+  this->_register_arithmetic<language::divide_op>();
+}
diff --git a/src/language/utils/BinaryOperatorRegisterForZ.hpp b/src/language/utils/BinaryOperatorRegisterForZ.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f9a7c30c2f8e3674e6ebda7e9069153a6162f13
--- /dev/null
+++ b/src/language/utils/BinaryOperatorRegisterForZ.hpp
@@ -0,0 +1,15 @@
+#ifndef BINARY_OPERATOR_REGISTER_FOR_Z_HPP
+#define BINARY_OPERATOR_REGISTER_FOR_Z_HPP
+
+class BinaryOperatorRegisterForZ
+{
+ private:
+  template <typename OperatorT>
+  void _register_arithmetic();
+  void _register_comparisons();
+
+ public:
+  BinaryOperatorRegisterForZ();
+};
+
+#endif   // BINARY_OPERATOR_REGISTER_FOR_Z_HPP
diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt
index 3efa30bc1b107d3bbdf31fdcb0f9d06734846f18..0e456e4d142ed8db2e772e1f00d6d64328510e22 100644
--- a/src/language/utils/CMakeLists.txt
+++ b/src/language/utils/CMakeLists.txt
@@ -13,6 +13,12 @@ add_library(PugsLanguageUtils
   ASTExecutionInfo.cpp
   ASTNodeDataType.cpp
   ASTPrinter.cpp
+  BinaryOperatorRegisterForB.cpp
+  BinaryOperatorRegisterForN.cpp
+  BinaryOperatorRegisterForR.cpp
+  BinaryOperatorRegisterForRn.cpp
+  BinaryOperatorRegisterForString.cpp
+  BinaryOperatorRegisterForZ.cpp
   DataVariant.cpp
   EmbeddedData.cpp
   IncDecOperatorRegisterForN.cpp
diff --git a/src/language/utils/ConcatExpressionProcessorBuilder.hpp b/src/language/utils/ConcatExpressionProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8fed359622883368f8bdc3cbdfbebf524e314c50
--- /dev/null
+++ b/src/language/utils/ConcatExpressionProcessorBuilder.hpp
@@ -0,0 +1,42 @@
+#ifndef CONCAT_EXPRESSION_PROCESSOR_BUILDER_HPP
+#define CONCAT_EXPRESSION_PROCESSOR_BUILDER_HPP
+
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/ConcatExpressionProcessor.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/IBinaryOperatorProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename B_DataT>
+class ConcatExpressionProcessorBuilder final : public IBinaryOperatorProcessorBuilder
+{
+ public:
+  ConcatExpressionProcessorBuilder() = default;
+
+  ASTNodeDataType
+  getDataTypeOfA() const
+  {
+    return ast_node_data_type_from<std::string>;
+  }
+
+  ASTNodeDataType
+  getDataTypeOfB() const
+  {
+    return ast_node_data_type_from<B_DataT>;
+  }
+
+  ASTNodeDataType
+  getReturnValueType() const
+  {
+    return ast_node_data_type_from<std::string>;
+  }
+
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<ConcatExpressionProcessor<B_DataT>>(node);
+  }
+};
+
+#endif   // CONCAT_EXPRESSION_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/IBinaryOperatorProcessorBuilder.hpp b/src/language/utils/IBinaryOperatorProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..46a3a23010ed6e8bd0d6373f80f53d8bfd45e8c7
--- /dev/null
+++ b/src/language/utils/IBinaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,23 @@
+#ifndef I_BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define I_BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+class ASTNode;
+class INodeProcessor;
+
+#include <language/utils/ASTNodeDataType.hpp>
+
+#include <memory>
+
+class IBinaryOperatorProcessorBuilder
+{
+ public:
+  [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+
+  [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0;
+  [[nodiscard]] virtual ASTNodeDataType getDataTypeOfA() const     = 0;
+  [[nodiscard]] virtual ASTNodeDataType getDataTypeOfB() const     = 0;
+
+  virtual ~IBinaryOperatorProcessorBuilder() = default;
+};
+
+#endif   // I_BINARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/IIncDecOperatorProcessorBuilder.hpp b/src/language/utils/IIncDecOperatorProcessorBuilder.hpp
index 918cef6a047828459a9b2937823e99308dcd137c..b84974a332326afa293757576efd6e2bdf40795e 100644
--- a/src/language/utils/IIncDecOperatorProcessorBuilder.hpp
+++ b/src/language/utils/IIncDecOperatorProcessorBuilder.hpp
@@ -10,9 +10,9 @@ class INodeProcessor;
 class IIncDecOperatorProcessorBuilder
 {
  public:
-  virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+  [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
 
-  virtual ASTNodeDataType getReturnValueType() const = 0;
+  [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0;
 
   virtual ~IIncDecOperatorProcessorBuilder() = default;
 };
diff --git a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
index b56ca3f466c1eb8ca886a20b64df4cbb7ea3b003..19b36e2feb42b9efc558ff5e554532c0f3d32824 100644
--- a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
+++ b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
@@ -11,9 +11,9 @@ class INodeProcessor;
 class IUnaryOperatorProcessorBuilder
 {
  public:
-  virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+  [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
 
-  virtual ASTNodeDataType getReturnValueType() const = 0;
+  [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0;
 
   virtual ~IUnaryOperatorProcessorBuilder() = default;
 };
diff --git a/src/language/utils/OperatorRepository.cpp b/src/language/utils/OperatorRepository.cpp
index ba91ff3f68200f8115a54461edd5f4c1692e77f2..77aa5578b396c280d14372b5fbb13f696b83c0f3 100644
--- a/src/language/utils/OperatorRepository.cpp
+++ b/src/language/utils/OperatorRepository.cpp
@@ -9,9 +9,18 @@
 #include <language/utils/AffectationRegisterForR3.hpp>
 #include <language/utils/AffectationRegisterForString.hpp>
 #include <language/utils/AffectationRegisterForZ.hpp>
+
+#include <language/utils/BinaryOperatorRegisterForB.hpp>
+#include <language/utils/BinaryOperatorRegisterForN.hpp>
+#include <language/utils/BinaryOperatorRegisterForR.hpp>
+#include <language/utils/BinaryOperatorRegisterForRn.hpp>
+#include <language/utils/BinaryOperatorRegisterForString.hpp>
+#include <language/utils/BinaryOperatorRegisterForZ.hpp>
+
 #include <language/utils/IncDecOperatorRegisterForN.hpp>
 #include <language/utils/IncDecOperatorRegisterForR.hpp>
 #include <language/utils/IncDecOperatorRegisterForZ.hpp>
+
 #include <language/utils/UnaryOperatorRegisterForB.hpp>
 #include <language/utils/UnaryOperatorRegisterForN.hpp>
 #include <language/utils/UnaryOperatorRegisterForR.hpp>
@@ -28,6 +37,7 @@ void
 OperatorRepository::reset()
 {
   m_affectation_builder_list.clear();
+  m_binary_operator_builder_list.clear();
   m_inc_dec_operator_builder_list.clear();
   m_unary_operator_builder_list.clear();
   this->_initialize();
@@ -61,6 +71,15 @@ OperatorRepository::_initialize()
   AffectationRegisterForR3{};
   AffectationRegisterForString{};
 
+  BinaryOperatorRegisterForB{};
+  BinaryOperatorRegisterForN{};
+  BinaryOperatorRegisterForZ{};
+  BinaryOperatorRegisterForR{};
+  BinaryOperatorRegisterForRn<1>{};
+  BinaryOperatorRegisterForRn<2>{};
+  BinaryOperatorRegisterForRn<3>{};
+  BinaryOperatorRegisterForString{};
+
   IncDecOperatorRegisterForN{};
   IncDecOperatorRegisterForR{};
   IncDecOperatorRegisterForZ{};
diff --git a/src/language/utils/OperatorRepository.hpp b/src/language/utils/OperatorRepository.hpp
index e7c1ea2f3a9bfc7ee21ddae4977f688894ae909a..6ac61e6e245f8f545e4794ffb4bd4703d4806b82 100644
--- a/src/language/utils/OperatorRepository.hpp
+++ b/src/language/utils/OperatorRepository.hpp
@@ -4,7 +4,9 @@
 #include <language/node_processor/INodeProcessor.hpp>
 #include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/AffectationMangler.hpp>
+#include <language/utils/BinaryOperatorMangler.hpp>
 #include <language/utils/IAffectationProcessorBuilder.hpp>
+#include <language/utils/IBinaryOperatorProcessorBuilder.hpp>
 #include <language/utils/IIncDecOperatorProcessorBuilder.hpp>
 #include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
 #include <language/utils/IncDecOperatorMangler.hpp>
@@ -13,6 +15,7 @@
 #include <utils/Exceptions.hpp>
 
 #include <optional>
+#include <unordered_map>
 
 class OperatorRepository
 {
@@ -51,6 +54,8 @@ class OperatorRepository
 
   std::unordered_map<std::string, Descriptor<IIncDecOperatorProcessorBuilder>> m_inc_dec_operator_builder_list;
 
+  std::unordered_map<std::string, Descriptor<IBinaryOperatorProcessorBuilder>> m_binary_operator_builder_list;
+
   std::unordered_map<std::string, Descriptor<IUnaryOperatorProcessorBuilder>> m_unary_operator_builder_list;
 
   void _initialize();
@@ -58,6 +63,23 @@ class OperatorRepository
  public:
   void reset();
 
+  template <typename BinaryOperatorTypeT>
+  void
+  addBinaryOperator(const std::shared_ptr<const IBinaryOperatorProcessorBuilder>& processor_builder)
+  {
+    const std::string binary_operator_type_name =
+      binaryOperatorMangler<BinaryOperatorTypeT>(processor_builder->getDataTypeOfA(),
+                                                 processor_builder->getDataTypeOfB());
+    if (not m_binary_operator_builder_list
+              .try_emplace(binary_operator_type_name,
+                           Descriptor{processor_builder->getReturnValueType(), processor_builder})
+              .second) {
+      // LCOV_EXCL_START
+      throw UnexpectedError(binary_operator_type_name + " has already an entry");
+      // LCOV_EXCL_STOP
+    }
+  }
+
   template <typename OperatorTypeT>
   void
   addAffectation(const ASTNodeDataType& lhs_type,
@@ -129,6 +151,16 @@ class OperatorRepository
     return {};
   }
 
+  [[nodiscard]] std::optional<std::shared_ptr<const IBinaryOperatorProcessorBuilder>>
+  getBinaryProcessorBuilder(const std::string& name) const
+  {
+    auto&& processor_builder = m_binary_operator_builder_list.find(name);
+    if (processor_builder != m_binary_operator_builder_list.end()) {
+      return processor_builder->second.processorBuilder();
+    }
+    return {};
+  }
+
   [[nodiscard]] std::optional<std::shared_ptr<const IUnaryOperatorProcessorBuilder>>
   getUnaryProcessorBuilder(const std::string& name) const
   {
@@ -149,6 +181,16 @@ class OperatorRepository
     return {};
   }
 
+  [[nodiscard]] std::optional<ASTNodeDataType>
+  getBinaryOperatorValueType(const std::string& name) const
+  {
+    auto&& processor_builder = m_binary_operator_builder_list.find(name);
+    if (processor_builder != m_binary_operator_builder_list.end()) {
+      return processor_builder->second.valueType();
+    }
+    return {};
+  }
+
   [[nodiscard]] std::optional<ASTNodeDataType>
   getUnaryOperatorValueType(const std::string& name) const
   {
diff --git a/src/utils/Timer.hpp b/src/utils/Timer.hpp
index e1ba542f2cda3969c1af397decc05451e7a3aaa4..786d7b789fb02993e2279f5e557c22423663a4e9 100644
--- a/src/utils/Timer.hpp
+++ b/src/utils/Timer.hpp
@@ -32,7 +32,9 @@ class Timer
   {
     switch (m_status) {
     case Status::running: {
-      return (m_elapsed_sum + std::chrono::duration<double>{std::chrono::system_clock::now() - m_start}).count();
+      return (m_elapsed_sum + std::chrono::duration<double>{std::chrono::system_clock::now().time_since_epoch() -
+                                                            m_start.time_since_epoch()})
+        .count();
     }
     case Status::paused:
     case Status::stopped: {
diff --git a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
index 7226ec270bc72889cc13d37ebda069cbad7d3512..1c030e91791827d6a4b69a087c116b2cdd61fc33 100644
--- a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
+++ b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
@@ -35,6 +35,18 @@
     REQUIRE(ast_output.str() == expected_output);                                                   \
   }
 
+#define REQUIRE_AST_THROWS_WITH(data, expected_output)                             \
+  {                                                                                \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
+                                                                                   \
+    string_input input{data, "test.pgs"};                                          \
+    auto ast = ASTBuilder::build(input);                                           \
+                                                                                   \
+    ASTSymbolTableBuilder{*ast};                                                   \
+    REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, expected_output);            \
+  }
+
+/*
 #define REQUIRE_AST_THROWS_WITH(data, expected_output)                             \
   {                                                                                \
     static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
@@ -50,6 +62,7 @@
                                                                                    \
     REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_output);          \
   }
+*/
 
 // clazy:excludeall=non-pod-global-static
 
@@ -67,11 +80,11 @@ false*b*true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, bool, bool>)
+ +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, bool>)
-     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, bool, bool>)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, unsigned long, bool>)
+     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -90,8 +103,8 @@ n*m*n;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, unsigned long>)
-     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, unsigned long>)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, unsigned long, unsigned long>)
+     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, unsigned long, unsigned long, unsigned long>)
      |   +-(language::name:n:NameProcessor)
      |   `-(language::name:m:NameProcessor)
      `-(language::name:n:NameProcessor)
@@ -109,8 +122,8 @@ a*3*a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long>)
-     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long>)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long, long>)
+     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long, long>)
      |   +-(language::name:a:NameProcessor)
      |   `-(language::integer:3:ValueProcessor)
      `-(language::name:a:NameProcessor)
@@ -127,9 +140,9 @@ a*3*a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, bool>)
-     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, long>)
-     |   +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, double>)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, double, bool>)
+     +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, double, long>)
+     |   +-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, double, double, double>)
      |   |   +-(language::real:2.3:ValueProcessor)
      |   |   `-(language::real:1.2:ValueProcessor)
      |   `-(language::integer:2:ValueProcessor)
@@ -151,7 +164,7 @@ let x : R^1, x = 3.7;
  +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<1ul, double>, double>)
  |   +-(language::name:x:NameProcessor)
  |   `-(language::real:3.7:ValueProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, TinyVector<1ul, double> >)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, TinyVector<1ul, double>, long, TinyVector<1ul, double> >)
      +-(language::integer:2:ValueProcessor)
      `-(language::name:x:NameProcessor)
 )";
@@ -173,7 +186,7 @@ let x : R^2, x = (3.2,6);
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::real:3.2:ValueProcessor)
  |       `-(language::integer:6:ValueProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, TinyVector<2ul, double> >)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, TinyVector<2ul, double>, long, TinyVector<2ul, double> >)
      +-(language::integer:2:ValueProcessor)
      `-(language::name:x:NameProcessor)
 )";
@@ -196,7 +209,7 @@ let x : R^3, x = (3.2,6,1.2);
  |       +-(language::real:3.2:ValueProcessor)
  |       +-(language::integer:6:ValueProcessor)
  |       `-(language::real:1.2:ValueProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, TinyVector<3ul, double> >)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, TinyVector<3ul, double>, long, TinyVector<3ul, double> >)
      +-(language::integer:2:ValueProcessor)
      `-(language::name:x:NameProcessor)
 )";
@@ -217,11 +230,11 @@ false/b/true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, bool, bool>)
+ +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, bool>)
-     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, bool, bool>)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, unsigned long, bool>)
+     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -240,8 +253,8 @@ n/m/n;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, unsigned long>)
-     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, unsigned long>)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, unsigned long, unsigned long>)
+     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, unsigned long, unsigned long, unsigned long>)
      |   +-(language::name:n:NameProcessor)
      |   `-(language::name:m:NameProcessor)
      `-(language::name:n:NameProcessor)
@@ -259,8 +272,8 @@ a/3/a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long>)
-     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long>)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long, long>)
+     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long, long>)
      |   +-(language::name:a:NameProcessor)
      |   `-(language::integer:3:ValueProcessor)
      `-(language::name:a:NameProcessor)
@@ -277,9 +290,9 @@ a/3/a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, bool>)
-     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, long>)
-     |   +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, double>)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, double, bool>)
+     +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, double, long>)
+     |   +-(language::divide_op:BinaryExpressionProcessor<language::divide_op, double, double, double>)
      |   |   +-(language::real:2.3:ValueProcessor)
      |   |   `-(language::real:1.2:ValueProcessor)
      |   `-(language::integer:2:ValueProcessor)
@@ -302,11 +315,11 @@ false+b+true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, bool, bool>)
+ +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, bool>)
-     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, bool, bool>)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, unsigned long, bool>)
+     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -325,8 +338,8 @@ n+m+n;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, unsigned long>)
-     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, unsigned long>)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, unsigned long, unsigned long>)
+     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, unsigned long, unsigned long, unsigned long>)
      |   +-(language::name:n:NameProcessor)
      |   `-(language::name:m:NameProcessor)
      `-(language::name:n:NameProcessor)
@@ -344,8 +357,8 @@ a+3+a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long>)
-     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long>)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long, long>)
+     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long, long>)
      |   +-(language::name:a:NameProcessor)
      |   `-(language::integer:3:ValueProcessor)
      `-(language::name:a:NameProcessor)
@@ -362,9 +375,9 @@ a+3+a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, bool>)
-     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, long>)
-     |   +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, double>)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, double, bool>)
+     +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, double, long>)
+     |   +-(language::plus_op:BinaryExpressionProcessor<language::plus_op, double, double, double>)
      |   |   +-(language::real:2.3:ValueProcessor)
      |   |   `-(language::real:1.2:ValueProcessor)
      |   `-(language::integer:2:ValueProcessor)
@@ -390,7 +403,7 @@ x+y;
  +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<1ul, double>, long>)
  |   +-(language::name:y:NameProcessor)
  |   `-(language::integer:2:ValueProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<1ul, double>, TinyVector<1ul, double> >)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<1ul, double>, TinyVector<1ul, double>, TinyVector<1ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -418,7 +431,7 @@ x+y;
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::real:0.3:ValueProcessor)
  |       `-(language::real:0.7:ValueProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<2ul, double>, TinyVector<2ul, double> >)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<2ul, double>, TinyVector<2ul, double>, TinyVector<2ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -448,7 +461,7 @@ x+y;
  |       +-(language::integer:4:ValueProcessor)
  |       +-(language::integer:3:ValueProcessor)
  |       `-(language::integer:2:ValueProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<3ul, double>, TinyVector<3ul, double> >)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, TinyVector<3ul, double>, TinyVector<3ul, double>, TinyVector<3ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -556,11 +569,11 @@ false-b-true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, bool, bool>)
+ +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, bool>)
-     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, bool, bool>)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long, bool>)
+     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -579,8 +592,8 @@ n-m-n;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, unsigned long, unsigned long>)
-     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, unsigned long, unsigned long>)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long, unsigned long>)
+     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, unsigned long, unsigned long>)
      |   +-(language::name:n:NameProcessor)
      |   `-(language::name:m:NameProcessor)
      `-(language::name:n:NameProcessor)
@@ -598,8 +611,8 @@ a-3-a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long>)
-     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long>)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long, long>)
+     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long, long>)
      |   +-(language::name:a:NameProcessor)
      |   `-(language::integer:3:ValueProcessor)
      `-(language::name:a:NameProcessor)
@@ -616,9 +629,9 @@ a-3-a;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, bool>)
-     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, long>)
-     |   +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, double>)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, double, bool>)
+     +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, double, long>)
+     |   +-(language::minus_op:BinaryExpressionProcessor<language::minus_op, double, double, double>)
      |   |   +-(language::real:2.3:ValueProcessor)
      |   |   `-(language::real:1.2:ValueProcessor)
      |   `-(language::integer:2:ValueProcessor)
@@ -644,7 +657,7 @@ x-y;
  +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<1ul, double>, long>)
  |   +-(language::name:y:NameProcessor)
  |   `-(language::integer:2:ValueProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<1ul, double>, TinyVector<1ul, double> >)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<1ul, double>, TinyVector<1ul, double>, TinyVector<1ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -672,7 +685,7 @@ x-y;
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::real:0.3:ValueProcessor)
  |       `-(language::real:0.7:ValueProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<2ul, double>, TinyVector<2ul, double> >)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<2ul, double>, TinyVector<2ul, double>, TinyVector<2ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -702,7 +715,7 @@ x-y;
  |       +-(language::integer:4:ValueProcessor)
  |       +-(language::integer:3:ValueProcessor)
  |       `-(language::integer:2:ValueProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<3ul, double>, TinyVector<3ul, double> >)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, TinyVector<3ul, double>, TinyVector<3ul, double>, TinyVector<3ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -723,11 +736,11 @@ false or b or true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool>)
+ +-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool>)
-     +-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool>)
+ `-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool, bool>)
+     +-(language::or_op:BinaryExpressionProcessor<language::or_op, bool, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -749,11 +762,11 @@ false and b and true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool>)
+ +-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool>)
-     +-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool>)
+ `-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool, bool>)
+     +-(language::and_op:BinaryExpressionProcessor<language::and_op, bool, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -775,11 +788,11 @@ false xor b xor true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- +-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool>)
+ +-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool, bool>)
  |   +-(language::name:b:NameProcessor)
  |   `-(language::true_kw:ValueProcessor)
- `-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool>)
-     +-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool>)
+ `-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool, bool>)
+     +-(language::xor_op:BinaryExpressionProcessor<language::xor_op, bool, bool, bool>)
      |   +-(language::false_kw:ValueProcessor)
      |   `-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
@@ -800,7 +813,7 @@ b > true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, bool>)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -818,7 +831,7 @@ n > m;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, unsigned long, unsigned long>)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -835,7 +848,7 @@ a > 3;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, long, long>)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -851,7 +864,7 @@ a > 3;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, double, double>)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -871,7 +884,7 @@ b < true;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, bool>)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -889,7 +902,7 @@ n < m;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, unsigned long>)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -906,7 +919,7 @@ a < 3;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, long, long>)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -922,7 +935,7 @@ a < 3;
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, double, double>)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -941,7 +954,7 @@ b >= true;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, bool>)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -959,7 +972,7 @@ n >= m;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, unsigned long, unsigned long>)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -976,7 +989,7 @@ a >= 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, long, long>)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -992,7 +1005,7 @@ a >= 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, double, double>)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -1012,7 +1025,7 @@ b <= true;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, bool>)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -1030,7 +1043,7 @@ n <= m;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, unsigned long, unsigned long>)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -1047,7 +1060,7 @@ a <= 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, long, long>)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -1063,7 +1076,7 @@ a <= 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, double, double>)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -1083,7 +1096,7 @@ b == true;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, bool>)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -1101,7 +1114,7 @@ n == m;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, unsigned long, unsigned long>)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -1118,7 +1131,7 @@ a == 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, long, long>)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -1134,7 +1147,7 @@ a == 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, double, double>)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -1152,7 +1165,7 @@ a == 3;
 
         std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, )" +
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, )" +
                              string_name + ", " + string_name + R"( >)
      +-(language::literal:"foo":ValueProcessor)
      `-(language::literal:"bar":ValueProcessor)
@@ -1177,7 +1190,7 @@ x==y;
  +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<1ul, double>, long>)
  |   +-(language::name:y:NameProcessor)
  |   `-(language::integer:2:ValueProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, TinyVector<1ul, double>, TinyVector<1ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1205,7 +1218,7 @@ x==y;
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::real:0.3:ValueProcessor)
  |       `-(language::real:0.7:ValueProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, TinyVector<2ul, double>, TinyVector<2ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1235,7 +1248,7 @@ x==y;
  |       +-(language::integer:4:ValueProcessor)
  |       +-(language::integer:3:ValueProcessor)
  |       `-(language::integer:2:ValueProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, TinyVector<3ul, double>, TinyVector<3ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1255,7 +1268,7 @@ b != true;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, bool>)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, bool, bool>)
      +-(language::name:b:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -1273,7 +1286,7 @@ n != m;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, unsigned long, unsigned long>)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, unsigned long, unsigned long>)
      +-(language::name:n:NameProcessor)
      `-(language::name:m:NameProcessor)
 )";
@@ -1290,7 +1303,7 @@ a != 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, long, long>)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, long, long>)
      +-(language::name:a:NameProcessor)
      `-(language::integer:3:ValueProcessor)
 )";
@@ -1306,7 +1319,7 @@ a != 3;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, double, double>)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, double, double>)
      +-(language::real:2.3:ValueProcessor)
      `-(language::real:1.2:ValueProcessor)
 )";
@@ -1330,7 +1343,7 @@ x!=y;
  +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<1ul, double>, long>)
  |   +-(language::name:y:NameProcessor)
  |   `-(language::integer:2:ValueProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, TinyVector<1ul, double>, TinyVector<1ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1358,7 +1371,7 @@ x!=y;
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::real:0.3:ValueProcessor)
  |       `-(language::real:0.7:ValueProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, TinyVector<2ul, double>, TinyVector<2ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1388,7 +1401,7 @@ x!=y;
  |       +-(language::integer:4:ValueProcessor)
  |       +-(language::integer:3:ValueProcessor)
  |       `-(language::integer:2:ValueProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, TinyVector<3ul, double>, TinyVector<3ul, double> >)
      +-(language::name:x:NameProcessor)
      `-(language::name:y:NameProcessor)
 )";
@@ -1406,7 +1419,7 @@ x!=y;
 
         std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, )" +
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, )" +
                              string_name + ", " + string_name + R"( >)
      +-(language::literal:"foo":ValueProcessor)
      `-(language::literal:"bar":ValueProcessor)
@@ -1422,6 +1435,11 @@ x!=y;
     SECTION("Invalid binary operator type")
     {
       auto ast = std::make_unique<ASTNode>();
+      ast->set_type<language::ignored>();
+      ast->children.emplace_back(std::make_unique<ASTNode>());
+      ast->children.emplace_back(std::make_unique<ASTNode>());
+      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+      ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
       REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "unexpected error: undefined binary operator");
     }
@@ -1437,7 +1455,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void * Z");
       }
 
       SECTION("left string multiply")
@@ -1449,7 +1467,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: string * Z");
       }
 
       SECTION("right string multiply")
@@ -1461,7 +1479,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z * string");
       }
 
       SECTION("lhs bad divide")
@@ -1473,7 +1491,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void / Z");
       }
 
       SECTION("left string divide")
@@ -1485,7 +1503,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: string / Z");
       }
 
       SECTION("right string divide")
@@ -1497,7 +1515,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z / string");
       }
 
       SECTION("lhs bad plus")
@@ -1509,7 +1527,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void + Z");
       }
 
       SECTION("left string plus bad rhs")
@@ -1521,7 +1539,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string + void");
       }
 
       SECTION("right string plus")
@@ -1533,7 +1552,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z + string");
       }
 
       SECTION("lhs bad minus")
@@ -1545,7 +1564,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void - Z");
       }
 
       SECTION("left string minus")
@@ -1557,7 +1576,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: string - Z");
       }
 
       SECTION("right string minus")
@@ -1569,7 +1588,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z - string");
       }
 
       SECTION("lhs bad or")
@@ -1581,7 +1600,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void or Z");
       }
 
       SECTION("left string or")
@@ -1593,7 +1612,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string or Z");
       }
 
       SECTION("right string or")
@@ -1605,7 +1625,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z or string");
       }
 
       SECTION("lhs bad and")
@@ -1617,7 +1638,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void and Z");
       }
 
       SECTION("left string and")
@@ -1629,7 +1650,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string and Z");
       }
 
       SECTION("right string and")
@@ -1641,7 +1663,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z and string");
       }
 
       SECTION("lhs bad xor")
@@ -1653,7 +1676,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void xor Z");
       }
 
       SECTION("left string xor")
@@ -1665,7 +1688,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string xor Z");
       }
 
       SECTION("right string xor")
@@ -1677,7 +1701,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z xor string");
       }
 
       SECTION("lhs bad >")
@@ -1689,7 +1714,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void > Z");
       }
 
       SECTION("left string >")
@@ -1701,7 +1726,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: string > Z");
       }
 
       SECTION("right string >")
@@ -1713,7 +1738,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z > string");
       }
 
       SECTION("lhs bad <")
@@ -1725,7 +1750,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void < Z");
       }
 
       SECTION("left string <")
@@ -1737,7 +1762,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: string < Z");
       }
 
       SECTION("right string <")
@@ -1749,7 +1774,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: Z < string");
       }
 
       SECTION("lhs bad >=")
@@ -1761,7 +1786,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void >= Z");
       }
 
       SECTION("left string >=")
@@ -1773,7 +1798,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string >= Z");
       }
 
       SECTION("right string >=")
@@ -1785,7 +1811,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z >= string");
       }
 
       SECTION("lhs bad <=")
@@ -1797,7 +1824,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void <= Z");
       }
 
       SECTION("left string <=")
@@ -1809,7 +1836,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string <= Z");
       }
 
       SECTION("right string <=")
@@ -1821,7 +1849,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z <= string");
       }
 
       SECTION("lhs bad ==")
@@ -1833,7 +1862,7 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void == Z");
       }
 
       SECTION("left string ==")
@@ -1845,7 +1874,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string == Z");
       }
 
       SECTION("right string ==")
@@ -1857,7 +1887,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z == string");
       }
 
       SECTION("lhs bad !=")
@@ -1869,10 +1900,10 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined binary operator type: void != Z");
       }
 
-      SECTION("left string ==")
+      SECTION("left string !=")
       {
         auto ast = std::make_unique<ASTNode>();
         ast->set_type<language::not_eq_op>();
@@ -1881,10 +1912,11 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: string != Z");
       }
 
-      SECTION("right string ==")
+      SECTION("right string !=")
       {
         auto ast = std::make_unique<ASTNode>();
         ast->set_type<language::not_eq_op>();
@@ -1893,7 +1925,8 @@ x!=y;
         ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
         ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
-        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
+        REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast},
+                            "undefined binary operator type: Z != string");
       }
     }
 
@@ -1907,7 +1940,10 @@ let y : R^1, y = 0;
 x > y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^1 >= R^1")
@@ -1918,7 +1954,10 @@ let y : R^1, y = 0;
 x >= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^1 < R^1")
@@ -1929,7 +1968,10 @@ let y : R^1, y = 0;
 x < y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^1 <= R^1")
@@ -1940,7 +1982,10 @@ let y : R^1, y = 1;
 x <= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^1 * R^1")
@@ -1951,7 +1996,10 @@ let y : R^1, y = 0;
 x * y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^1 / R^1")
@@ -1962,7 +2010,10 @@ let y : R^1, y = 0;
 x / y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 > R^2")
@@ -1973,7 +2024,10 @@ let y : R^2, y = 0;
 x > y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 >= R^2")
@@ -1984,7 +2038,10 @@ let y : R^2, y = 0;
 x >= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 < R^2")
@@ -1995,7 +2052,10 @@ let y : R^2, y = 0;
 x < y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 <= R^2")
@@ -2006,7 +2066,10 @@ let y : R^2, y = 0;
 x <= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 * R^2")
@@ -2017,7 +2080,10 @@ let y : R^2, y = 0;
 x * y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^2 / R^2")
@@ -2028,7 +2094,10 @@ let y : R^2, y = 0;
 x / y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^2 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 > R^3")
@@ -2039,7 +2108,10 @@ let y : R^3, y = 0;
 x > y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 >= R^3")
@@ -2050,7 +2122,10 @@ let y : R^3, y = 0;
 x >= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 < R^3")
@@ -2061,7 +2136,10 @@ let y : R^3, y = 0;
 x < y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 <= R^3")
@@ -2072,7 +2150,10 @@ let y : R^3, y = 0;
 x <= y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 * R^3")
@@ -2083,7 +2164,10 @@ let y : R^3, y = 0;
 x * y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("invalid operator R^3 / R^3")
@@ -2094,7 +2178,10 @@ let y : R^3, y = 0;
 x / y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "invalid binary operator");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^3)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
     }
 
@@ -2108,7 +2195,10 @@ let y : R^1, y = 0;
 x + y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "incompatible dimensions of operands");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^1)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("incompatible operand dimensions")
@@ -2119,7 +2209,10 @@ let y : R^2, y = 0;
 x - y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "incompatible dimensions of operands");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("incompatible operand dimensions")
@@ -2130,7 +2223,10 @@ let y : R^2, y = 0;
 x == y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "incompatible dimensions of operands");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^3 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
 
       SECTION("incompatible operand dimensions")
@@ -2141,7 +2237,10 @@ let y : R^2, y = 0;
 x != y;
 )";
 
-        REQUIRE_AST_THROWS_WITH(data, "incompatible dimensions of operands");
+        const std::string error_mesh = R"(undefined binary operator
+note: incompatible operand types R^1 and R^2)";
+
+        REQUIRE_AST_THROWS_WITH(data, error_mesh);
       }
     }
   }
diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp
index 8cca350f1d165303634b86a7958ab55b81c72cb3..3b09a0bb554e6692fe1f741229e9ea43725782af 100644
--- a/tests/test_ASTNodeExpressionBuilder.cpp
+++ b/tests/test_ASTNodeExpressionBuilder.cpp
@@ -489,7 +489,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long>)
+ `-(language::multiply_op:BinaryExpressionProcessor<language::multiply_op, long, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -505,7 +505,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long>)
+ `-(language::divide_op:BinaryExpressionProcessor<language::divide_op, long, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -521,7 +521,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long>)
+ `-(language::plus_op:BinaryExpressionProcessor<language::plus_op, long, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -537,7 +537,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long>)
+ `-(language::minus_op:BinaryExpressionProcessor<language::minus_op, long, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -547,17 +547,26 @@ x[2];
 
     SECTION("or")
     {
-      CHECK_AST_THROWS_WITH(R"(1 or 2;)", "invalid implicit conversion: Z -> B");
+      const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and Z)";
+
+      CHECK_AST_THROWS_WITH(R"(1 or 2;)", error_message);
     }
 
     SECTION("and")
     {
-      CHECK_AST_THROWS_WITH(R"(1 and 2;)", "invalid implicit conversion: Z -> B");
+      const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and Z)";
+
+      CHECK_AST_THROWS_WITH(R"(1 and 2;)", error_message);
     }
 
     SECTION("xor")
     {
-      CHECK_AST_THROWS_WITH(R"(1 xor 2;)", "invalid implicit conversion: Z -> B");
+      const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and Z)";
+
+      CHECK_AST_THROWS_WITH(R"(1 xor 2;)", error_message);
     }
 
     SECTION("lesser")
@@ -568,7 +577,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, long, long>)
+ `-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -584,7 +593,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, long, long>)
+ `-(language::lesser_or_eq_op:BinaryExpressionProcessor<language::lesser_or_eq_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -600,7 +609,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, long, long>)
+ `-(language::greater_op:BinaryExpressionProcessor<language::greater_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -616,7 +625,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, long, long>)
+ `-(language::greater_or_eq_op:BinaryExpressionProcessor<language::greater_or_eq_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -632,7 +641,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, long, long>)
+ `-(language::eqeq_op:BinaryExpressionProcessor<language::eqeq_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -648,7 +657,7 @@ x[2];
 
       std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, long, long>)
+ `-(language::not_eq_op:BinaryExpressionProcessor<language::not_eq_op, bool, long, long>)
      +-(language::integer:1:ValueProcessor)
      `-(language::integer:2:ValueProcessor)
 )";
@@ -766,7 +775,7 @@ for(let i:N, i=0; i<10; ++i);
      +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
      |   +-(language::name:i:NameProcessor)
      |   `-(language::integer:0:ValueProcessor)
-     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, unsigned long, long>)
      |   +-(language::name:i:NameProcessor)
      |   `-(language::integer:10:ValueProcessor)
      +-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, unsigned long>)
@@ -791,7 +800,7 @@ for(; i<10; ++i);
  |   `-(language::integer:0:ValueProcessor)
  `-(language::for_statement:ForProcessor)
      +-(language::for_init:FakeProcessor)
-     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, unsigned long, long>)
      |   +-(language::name:i:NameProcessor)
      |   `-(language::integer:10:ValueProcessor)
      +-(language::unary_plusplus:IncDecExpressionProcessor<language::unary_plusplus, unsigned long>)
@@ -835,7 +844,7 @@ for(let i:N, i=0; i<10;);
      +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
      |   +-(language::name:i:NameProcessor)
      |   `-(language::integer:0:ValueProcessor)
-     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, unsigned long, long>)
+     +-(language::lesser_op:BinaryExpressionProcessor<language::lesser_op, bool, unsigned long, long>)
      |   +-(language::name:i:NameProcessor)
      |   `-(language::integer:10:ValueProcessor)
      +-(language::for_post:FakeProcessor)
diff --git a/tests/test_BinaryExpressionProcessor_logic.cpp b/tests/test_BinaryExpressionProcessor_logic.cpp
index f53d8557cc48551a9abe630c3bbda43aed9ae366..a0d6c12e7cbef0e5e90dc1ed0ec6bb57a6a7d406 100644
--- a/tests/test_BinaryExpressionProcessor_logic.cpp
+++ b/tests/test_BinaryExpressionProcessor_logic.cpp
@@ -42,32 +42,121 @@ TEST_CASE("BinaryExpressionProcessor logic", "[language]")
     {
       SECTION("and")
       {
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n and true;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false and n;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 and true;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false and 2;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 and true;)", "invalid implicit conversion: R -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false and 2e-2;)", "invalid implicit conversion: R -> B");
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types N and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n and true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and N)";
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false and n;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 and true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and Z)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false and 2;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types R and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 and true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and R)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false and 2e-2;)", error_message);
+        }
       }
 
       SECTION("or")
       {
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n or true;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false or n;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 or true;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false or 2;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 or true;)", "invalid implicit conversion: R -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false or 2e-2;)", "invalid implicit conversion: R -> B");
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types N and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n or true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and N)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false or n;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 or true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and Z)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false or 2;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types R and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 or true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and R)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false or 2e-2;)", error_message);
+        }
       }
 
       SECTION("xor")
       {
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n xor true;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false xor n;)", "invalid implicit conversion: N -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 xor true;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false xor 2;)", "invalid implicit conversion: Z -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 xor true;)", "invalid implicit conversion: R -> B");
-        CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false xor 2e-2;)", "invalid implicit conversion: R -> B");
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types N and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=1; n xor true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and N)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(let n:N, n=2; false xor n;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types Z and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1 xor true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and Z)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false xor 2;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types R and B)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(1.1 xor true;)", error_message);
+        }
+        {
+          const std::string error_message = R"(undefined binary operator
+note: incompatible operand types B and R)";
+
+          CHECK_BINARY_EXPRESSION_THROWS_WITH(R"(false xor 2e-2;)", error_message);
+        }
       }
     }
   }
diff --git a/tests/test_IncDecExpressionProcessor.cpp b/tests/test_IncDecExpressionProcessor.cpp
index ca13dbde2c33330515300b1fa19ba163a771c5f2..7525ca9ff5cf796ecbe3a183f570793b4ed614fb 100644
--- a/tests/test_IncDecExpressionProcessor.cpp
+++ b/tests/test_IncDecExpressionProcessor.cpp
@@ -40,6 +40,16 @@
     REQUIRE(value == expected_value);                                         \
   }
 
+#define CHECK_INCDEC_EXPRESSION_THROWS_WITH(data, error_message)      \
+  {                                                                   \
+    string_input input{data, "test.pgs"};                             \
+    auto ast = ASTBuilder::build(input);                              \
+                                                                      \
+    ASTSymbolTableBuilder{*ast};                                      \
+                                                                      \
+    REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \
+  }
+
 // clazy:excludeall=non-pod-global-static
 
 TEST_CASE("IncDecExpressionProcessor", "[language]")
@@ -127,4 +137,51 @@ TEST_CASE("IncDecExpressionProcessor", "[language]")
       CHECK_INC_DEC_RESULT(R"(let r:R, r = 2; let s:R, s = r--;)", "s", 2.);
     }
   }
+
+  SECTION("errors")
+  {
+    SECTION("undefined pre -- operator")
+    {
+      auto error_message = [](std::string type_name) {
+        return std::string{R"(undefined increment/decrement operator
+note: unexpected operand type )"} +
+               type_name;
+      };
+
+      CHECK_INCDEC_EXPRESSION_THROWS_WITH(R"(--"foo";)", error_message("string"));
+    }
+
+    SECTION("undefined pre ++ operator")
+    {
+      auto error_message = [](std::string type_name) {
+        return std::string{R"(undefined increment/decrement operator
+note: unexpected operand type )"} +
+               type_name;
+      };
+
+      CHECK_INCDEC_EXPRESSION_THROWS_WITH(R"(++true;)", error_message("B"));
+    }
+
+    SECTION("undefined post -- operator")
+    {
+      auto error_message = [](std::string type_name) {
+        return std::string{R"(undefined increment/decrement operator
+note: unexpected operand type )"} +
+               type_name;
+      };
+
+      CHECK_INCDEC_EXPRESSION_THROWS_WITH(R"(true--;)", error_message("B"));
+    }
+
+    SECTION("undefined post ++ operator")
+    {
+      auto error_message = [](std::string type_name) {
+        return std::string{R"(undefined increment/decrement operator
+note: unexpected operand type )"} +
+               type_name;
+      };
+
+      CHECK_INCDEC_EXPRESSION_THROWS_WITH(R"("bar"++;)", error_message("string"));
+    }
+  }
 }
diff --git a/tests/test_Timer.cpp b/tests/test_Timer.cpp
index adbbd69cbb8aaa4aaad8695b5ce5c0d1ec623f9e..bf85f15653eec2ba4bd6914873e6305cedaf4829 100644
--- a/tests/test_Timer.cpp
+++ b/tests/test_Timer.cpp
@@ -2,7 +2,9 @@
 
 #include <utils/Timer.hpp>
 
+#include <chrono>
 #include <sstream>
+#include <thread>
 
 // clazy:excludeall=non-pod-global-static
 
@@ -15,10 +17,12 @@ TEST_CASE("Timer", "[utils]")
     REQUIRE(t.status() == Timer::Status::running);
 
     double seconds = t.seconds();
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     REQUIRE(t.seconds() > seconds);
 
     t.start();
     seconds = t.seconds();
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     REQUIRE(t.status() == Timer::Status::running);
 
     REQUIRE(t.seconds() > seconds);
@@ -31,9 +35,9 @@ TEST_CASE("Timer", "[utils]")
     REQUIRE(t1.status() == Timer::Status::running);
     t1.pause();
 
-    REQUIRE(t1.status() == Timer::Status::paused);
     const double seconds = t1.seconds();
-
+    REQUIRE(t1.status() == Timer::Status::paused);
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     REQUIRE(t1.seconds() == seconds);
 
     std::stringstream os1;
@@ -47,6 +51,7 @@ TEST_CASE("Timer", "[utils]")
 
     REQUIRE(t1.seconds() == t2.seconds());
     t1.start();
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     REQUIRE(t1.status() == Timer::Status::running);
     REQUIRE(t1.seconds() > t2.seconds());
 
@@ -60,7 +65,9 @@ TEST_CASE("Timer", "[utils]")
     Timer t;
     REQUIRE(t.status() == Timer::Status::running);
 
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     const double seconds = t.seconds();
+
     REQUIRE(seconds > 0);
 
     t.stop();
@@ -68,6 +75,7 @@ TEST_CASE("Timer", "[utils]")
     REQUIRE(t.seconds() == 0);
 
     t.start();
+    std::this_thread::sleep_for(std::chrono::microseconds(5));
     REQUIRE(t.status() == Timer::Status::running);
     REQUIRE(t.seconds() > 0);
   }
diff --git a/tests/test_UnaryExpressionProcessor.cpp b/tests/test_UnaryExpressionProcessor.cpp
index b2cec8c797a48457b8d19c112c7490e9e275247a..b309d6dd13c0791a909ab30e164325ac7d365e00 100644
--- a/tests/test_UnaryExpressionProcessor.cpp
+++ b/tests/test_UnaryExpressionProcessor.cpp
@@ -68,7 +68,7 @@ TEST_CASE("UnaryExpressionProcessor", "[language]")
 
     SECTION("errors")
     {
-      SECTION("bad implicit conversions")
+      SECTION("undefined not operator")
       {
         auto error_message = [](std::string type_name) {
           return std::string{R"(undefined unary operator
@@ -81,6 +81,17 @@ note: unexpected operand type )"} +
         CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1.3;)", error_message("R"));
         CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not "foo";)", error_message("string"));
       }
+
+      SECTION("undefined unary minus operator")
+      {
+        auto error_message = [](std::string type_name) {
+          return std::string{R"(undefined unary operator
+note: unexpected operand type )"} +
+                 type_name;
+        };
+
+        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(-"foo";)", error_message("string"));
+      }
     }
   }
 }