diff --git a/.gitignore b/.gitignore
index e8ba8747559abdacd563868545e2a6666be82a3c..3bb6d6cbcf2906a99d3302595285d50145395fe5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ CMakeCache.txt
 GPATH
 GRTAGS
 GTAGS
+/.clangd/
diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index ed00e3032b5efddcbfbd21124836f737889041e3..faab47780f0736c43285b3245a8ee07cc966f036 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -16,6 +16,7 @@
 #include <language/utils/ASTDotPrinter.hpp>
 #include <language/utils/ASTExecutionInfo.hpp>
 #include <language/utils/ASTPrinter.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/SymbolTable.hpp>
 #include <utils/PugsAssert.hpp>
 #include <utils/PugsUtils.hpp>
@@ -48,6 +49,8 @@ parser(const std::string& filename)
             << rang::style::reset << " ...\n";
 
   auto parse_and_execute = [](auto& input) {
+    OperatorRepository::create();
+
     std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input);
 
     ASTModulesImporter module_importer{*root_node};
@@ -81,6 +84,8 @@ parser(const std::string& filename)
     root_node->execute(exec_all);
 
     root_node->m_symbol_table->clearValues();
+
+    OperatorRepository::destroy();
   };
 
   if (not SignalManager::pauseOnError()) {
diff --git a/src/language/ast/ASTNode.hpp b/src/language/ast/ASTNode.hpp
index a3b9bd21569d490b1bc7f450eee546279b91a681..d9568c612dd3e3a6223994cff6273b43d900b3c0 100644
--- a/src/language/ast/ASTNode.hpp
+++ b/src/language/ast/ASTNode.hpp
@@ -1,9 +1,9 @@
 #ifndef AST_NODE_HPP
 #define AST_NODE_HPP
 
-#include <language/ast/ASTNodeDataType.hpp>
 #include <language/node_processor/ExecutionPolicy.hpp>
 #include <language/node_processor/INodeProcessor.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/DataVariant.hpp>
 #include <utils/PugsAssert.hpp>
 #include <utils/PugsMacros.hpp>
diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
index 66420138cd85f3fcf220ceec883f6c2b1b012759..6e712e3d84c0eb6d52064fdfecabd9dd6f9016db 100644
--- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
@@ -3,437 +3,54 @@
 #include <algebra/TinyVector.hpp>
 #include <language/PEGGrammar.hpp>
 #include <language/ast/ASTNodeNaturalConversionChecker.hpp>
-#include <language/node_processor/AffectationProcessor.hpp>
+#include <language/node_processor/INodeProcessor.hpp>
+#include <language/utils/AffectationMangler.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
-
 #include <utils/Exceptions.hpp>
 
 ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n)
 {
-  auto set_affectation_processor = [](ASTNode& n, const auto& operator_v) {
-    auto set_affectation_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-      using ValueT    = std::decay_t<decltype(value)>;
-
-      switch (data_type) {
-      case ASTNodeDataType::bool_t: {
-        n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
-        break;
-      }
-      case ASTNodeDataType::unsigned_int_t: {
-        n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
-        break;
-      }
-        // LCOV_EXCL_START
-      default: {
-        throw ParseError("unexpected error: undefined operand type for affectation",
-                         std::vector{n.children[1]->begin()});
-      }
-        // LCOV_EXCL_STOP
-      }
-    };
-
-    auto set_affectation_processor_for_vector_data = [&](const auto& value, const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-      using ValueT    = std::decay_t<decltype(value)>;
-
-      if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::vector_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
-          break;
-        }
-        case ASTNodeDataType::list_t: {
-          n.m_node_processor = std::make_unique<AffectationToTinyVectorFromListProcessor<OperatorT, ValueT>>(n);
-          break;
-        }
-        case ASTNodeDataType::bool_t: {
-          if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
-            break;
-          }
-        }
-        case ASTNodeDataType::unsigned_int_t: {
-          if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
-            break;
-          }
-        }
-        case ASTNodeDataType::int_t: {
-          if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
-            if (n.children[1]->is_type<language::integer>()) {
-              if (std::stoi(n.children[1]->string()) == 0) {
-                n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n);
-                break;
-              }
-            }
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
-            break;
-          } else if (n.children[1]->is_type<language::integer>()) {
-            if (std::stoi(n.children[1]->string()) == 0) {
-              n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n);
-              break;
-            }
-          }
-          // LCOV_EXCL_START
-          throw ParseError("unexpected error: invalid integral value", std::vector{n.children[1]->begin()});
-          // LCOV_EXCL_STOP
-        }
-        case ASTNodeDataType::double_t: {
-          if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
-            break;
-          }
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: invalid operand type", std::vector{n.children[1]->begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-      } else if constexpr (std::is_same_v<OperatorT, language::pluseq_op> or
-                           std::is_same_v<OperatorT, language::minuseq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::vector_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
-          break;
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: invalid operand type", std::vector{n.children[1]->begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-      } else if constexpr (std::is_same_v<OperatorT, language::multiplyeq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::bool_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
-          break;
-        }
-        case ASTNodeDataType::unsigned_int_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::int_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::double_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
-          break;
-        }
-        default: {
-          throw ParseError("expecting scalar operand type", std::vector{n.children[1]->begin()});
-        }
-        }
-      } else {
-        throw ParseError("invalid affectation operator for " + dataTypeName(n.m_data_type), std::vector{n.begin()});
-      }
-    };
-
-    auto set_affectation_processor_for_string_data = [&](const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-
-      if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::bool_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, bool>>(n);
-          break;
-        }
-        case ASTNodeDataType::unsigned_int_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, uint64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::int_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, int64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::double_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, double>>(n);
-          break;
-        }
-        case ASTNodeDataType::string_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, std::string>>(n);
-          break;
-        }
-        case ASTNodeDataType::vector_t: {
-          switch (data_type.dimension()) {
-          case 1: {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<1>>>(n);
-            break;
-          }
-          case 2: {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<2>>>(n);
-            break;
-          }
-          case 3: {
-            n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<3>>>(n);
-            break;
-          }
-            // LCOV_EXCL_START
-          default: {
-            throw ParseError("unexpected error: invalid vector dimension for string affectation",
-                             std::vector{n.children[1]->begin()});
-          }
-            // LCOV_EXCL_STOP
-          }
-          break;
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: undefined operand type for string affectation",
-                           std::vector{n.children[1]->begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-      } else {
-        throw ParseError("invalid affectation operator for string", std::vector{n.begin()});
-      }
-    };
-
-    auto set_affectation_processor_for_embedded_data = [&](const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-
-      if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::type_id_t: {
-          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, EmbeddedData, EmbeddedData>>(n);
-          break;
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: undefined operand type for embedded data affectation",
-                           std::vector{n.children[1]->begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-      } else {
-        throw ParseError("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'",
-                         std::vector{n.begin()});
-      }
-    };
-
-    auto set_affectation_processor_for_tuple_data = [&](const ASTNodeDataType& content_data_type,
-                                                        const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-      if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-        if ((data_type == ASTNodeDataType::list_t) or (data_type == ASTNodeDataType::tuple_t)) {
-          switch (content_data_type) {
-          case ASTNodeDataType::type_id_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, EmbeddedData>>(n);
-            break;
-          }
-          case ASTNodeDataType::bool_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, bool>>(n);
-            break;
-          }
-          case ASTNodeDataType::unsigned_int_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, uint64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::int_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, int64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::double_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, double>>(n);
-            break;
-          }
-          case ASTNodeDataType::string_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, std::string>>(n);
-            break;
-          }
-          case ASTNodeDataType::vector_t: {
-            switch (content_data_type.dimension()) {
-            case 1: {
-              n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, TinyVector<1>>>(n);
-              break;
-            }
-            case 2: {
-              n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, TinyVector<2>>>(n);
-              break;
-            }
-            case 3: {
-              n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, TinyVector<3>>>(n);
-              break;
-            }
-              // LCOV_EXCL_START
-            default: {
-              throw ParseError("unexpected error: invalid vector dimension for tuple affectation",
-                               std::vector{n.children[1]->begin()});
-            }
-              // LCOV_EXCL_STOP
-            }
-            break;
-          }
-            // LCOV_EXCL_START
-          default: {
-            throw UnexpectedError("invalid tuple content " + dataTypeName(content_data_type));
-          }
-            // LCOV_EXCL_STOP
-          }
-        } else {
-          switch (content_data_type) {
-          case ASTNodeDataType::type_id_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, EmbeddedData>>(n);
-            break;
-          }
-          case ASTNodeDataType::bool_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, bool>>(n);
-            break;
-          }
-          case ASTNodeDataType::unsigned_int_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, uint64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::int_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, int64_t>>(n);
-            break;
-          }
-          case ASTNodeDataType::double_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, double>>(n);
-            break;
-          }
-          case ASTNodeDataType::string_t: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, std::string>>(n);
-            break;
-          }
-          case ASTNodeDataType::vector_t: {
-            switch (content_data_type.dimension()) {
-            case 1: {
-              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<1>>>(n);
-              break;
-            }
-            case 2: {
-              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<2>>>(n);
-              break;
-            }
-            case 3: {
-              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<3>>>(n);
-              break;
-            }
-              // LCOV_EXCL_START
-            default: {
-              throw ParseError("unexpected error: invalid vector dimension for tuple affectation",
-                               std::vector{n.children[1]->begin()});
-            }
-              // LCOV_EXCL_STOP
-            }
-            break;
-          }
-          // LCOV_EXCL_START
-          default: {
-            throw ParseError("unexpected error: undefined operand type for tuple affectation",
-                             std::vector{n.children[1]->begin()});
-          }
-            // LCOV_EXCL_STOP
-          }
-        }
-      } else {
-        throw ParseError("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'",
-                         std::vector{n.begin()});
-      }
-    };
-
-    auto set_affectation_processor_for_value = [&](const ASTNodeDataType& value_type) {
-      const ASTNodeDataType data_type = n.children[1]->m_data_type;
-
-      switch (value_type) {
-      case ASTNodeDataType::bool_t: {
-        set_affectation_processor_for_data(bool{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::unsigned_int_t: {
-        set_affectation_processor_for_data(uint64_t{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        set_affectation_processor_for_data(int64_t{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        set_affectation_processor_for_data(double{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::vector_t: {
-        switch (value_type.dimension()) {
-        case 1: {
-          set_affectation_processor_for_vector_data(TinyVector<1>{}, data_type);
-          break;
-        }
-        case 2: {
-          set_affectation_processor_for_vector_data(TinyVector<2>{}, data_type);
-          break;
-        }
-        case 3: {
-          set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type);
-          break;
-        }
-          // LCOV_EXCL_START
-        default: {
-          throw ParseError("unexpected error: unexpected vector dimension", std::vector{n.begin()});
-        }
-          // LCOV_EXCL_STOP
-        }
-        break;
-      }
-      case ASTNodeDataType::string_t: {
-        set_affectation_processor_for_string_data(data_type);
-        break;
-      }
-      case ASTNodeDataType::type_id_t: {
-        set_affectation_processor_for_embedded_data(data_type);
-        break;
-      }
-      case ASTNodeDataType::tuple_t: {
-        const ASTNodeDataType& content_type = value_type.contentType();
-        set_affectation_processor_for_tuple_data(content_type, data_type);
-        break;
-      }
-      default: {
-        throw ParseError("unexpected error: undefined value type for affectation", std::vector{n.children[0]->begin()});
-      }
-      }
-    };
-
-    using OperatorT = std::decay_t<decltype(operator_v)>;
-
-    const ASTNodeDataType& target_data_type = n.children[0]->m_data_type;
-    const ASTNodeDataType& source_data_type = n.children[1]->m_data_type;
-
-    // Special treatment dedicated to R^1 to be able to initialize them
-    if (((target_data_type != source_data_type) and (target_data_type == ASTNodeDataType::vector_t) and
-         (target_data_type.dimension() == 1)) or
-        // Special treatment for R^d vectors and operator *=
-        ((target_data_type == ASTNodeDataType::vector_t) and (source_data_type != ASTNodeDataType::vector_t) and
-         std::is_same_v<OperatorT, language::multiplyeq_op>)) {
-      ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::build<ASTNodeDataType::double_t>()};
+  const ASTNodeDataType& target_data_type = n.children[0]->m_data_type;
+  const ASTNodeDataType& source_data_type = n.children[1]->m_data_type;
+
+  const std::string affectation_name = [&] {
+    if (n.is_type<language::eq_op>()) {
+      return affectationMangler<language::eq_op>(target_data_type, source_data_type);
+    } else if (n.is_type<language::multiplyeq_op>()) {
+      return affectationMangler<language::multiplyeq_op>(target_data_type, source_data_type);
+    } else if (n.is_type<language::divideeq_op>()) {
+      return affectationMangler<language::divideeq_op>(target_data_type, source_data_type);
+    } else if (n.is_type<language::pluseq_op>()) {
+      return affectationMangler<language::pluseq_op>(target_data_type, source_data_type);
+    } else if (n.is_type<language::minuseq_op>()) {
+      return affectationMangler<language::minuseq_op>(target_data_type, source_data_type);
     } else {
-      ASTNodeNaturalConversionChecker{*n.children[1], target_data_type};
+      throw ParseError("unexpected error: undefined affectation operator", std::vector{n.begin()});
     }
+  }();
+
+  // Special treatment dedicated to R^1 to be able to initialize them
+  if (((target_data_type != source_data_type) and (target_data_type == ASTNodeDataType::vector_t) and
+       (target_data_type.dimension() == 1)) or
+      // Special treatment for R^d vectors and operator *=
+      ((target_data_type == ASTNodeDataType::vector_t) and (source_data_type != ASTNodeDataType::vector_t) and
+       n.is_type<language::multiplyeq_op>())) {
+    ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::build<ASTNodeDataType::double_t>()};
+  } else {
+    ASTNodeNaturalConversionChecker{*n.children[1], target_data_type};
+  }
 
-    set_affectation_processor_for_value(target_data_type);
-  };
+  const auto& optional_processor_builder =
+    OperatorRepository::instance().getAffectationProcessorBuilder(affectation_name);
 
-  if (n.is_type<language::eq_op>()) {
-    set_affectation_processor(n, language::eq_op{});
-  } else if (n.is_type<language::multiplyeq_op>()) {
-    set_affectation_processor(n, language::multiplyeq_op{});
-  } else if (n.is_type<language::divideeq_op>()) {
-    set_affectation_processor(n, language::divideeq_op{});
-  } else if (n.is_type<language::pluseq_op>()) {
-    set_affectation_processor(n, language::pluseq_op{});
-  } else if (n.is_type<language::minuseq_op>()) {
-    set_affectation_processor(n, language::minuseq_op{});
+  if (optional_processor_builder.has_value()) {
+    n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
   } else {
-    throw ParseError("unexpected error: undefined affectation operator", std::vector{n.begin()});
+    std::ostringstream error_message;
+    error_message << "undefined affectation type: ";
+    error_message << rang::fgB::red << affectation_name << rang::fg::reset;
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
   }
 }
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 7cbeb6adfdc96f8c2a56796c32c83592f0839d40..7c93b50527bbae5c352d62159e40d0eba3bb7aad 100644
--- a/src/language/ast/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp
@@ -3,6 +3,7 @@
 #include <language/PEGGrammar.hpp>
 #include <language/ast/ASTNodeNaturalConversionChecker.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
 #include <language/utils/SymbolTable.hpp>
 #include <utils/PugsAssert.hpp>
@@ -282,7 +283,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
     } else if (n.is_type<language::eq_op>() or n.is_type<language::multiplyeq_op>() or
                n.is_type<language::divideeq_op>() or n.is_type<language::pluseq_op>() or
                n.is_type<language::minuseq_op>()) {
-      n.m_data_type = n.children[0]->m_data_type;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
     } else if (n.is_type<language::tuple_expression>()) {
       std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
@@ -351,52 +352,135 @@ 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>()) {
-      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
-
-      const ASTNode& operand_node = *n.children[0];
-      ASTNodeNaturalConversionChecker{operand_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
-
-    } 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>()};
+    } else if (n.is_type<language::unary_not>() or n.is_type<language::unary_minus>()) {
+      auto& operator_repository = OperatorRepository::instance();
 
-      const ASTNode& rhs_node = *n.children[1];
-      ASTNodeNaturalConversionChecker{rhs_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
+      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
+        }
+      }();
 
-    } else if (n.is_type<language::unary_minus>()) {
-      n.m_data_type = n.children[0]->m_data_type;
-      if ((n.children[0]->m_data_type == ASTNodeDataType::unsigned_int_t) or
-          (n.children[0]->m_data_type == ASTNodeDataType::bool_t)) {
-        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+      if (optional_value_type.has_value()) {
+        n.m_data_type = optional_value_type.value();
       } else {
-        n.m_data_type = n.children[0]->m_data_type;
+        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>()) {
-      n.m_data_type = n.children[0]->m_data_type;
+      auto& operator_repository = OperatorRepository::instance();
+
+      auto optional_value_type = [&] {
+        if (n.is_type<language::unary_plusplus>()) {
+          return operator_repository.getIncDecOperatorValueType(
+            incDecOperatorMangler<language::unary_plusplus>(n.children[0]->m_data_type));
+        } else if (n.is_type<language::unary_minusminus>()) {
+          return operator_repository.getIncDecOperatorValueType(
+            incDecOperatorMangler<language::unary_minusminus>(n.children[0]->m_data_type));
+        } else if (n.is_type<language::post_minusminus>()) {
+          return operator_repository.getIncDecOperatorValueType(
+            incDecOperatorMangler<language::post_minusminus>(n.children[0]->m_data_type));
+        } else if (n.is_type<language::post_plusplus>()) {
+          return operator_repository.getIncDecOperatorValueType(
+            incDecOperatorMangler<language::post_plusplus>(n.children[0]->m_data_type));
+        } 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 {
+        std::ostringstream message;
+        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());
+      }
+
     } 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 " << n.children[0]->string() << " (" << dataTypeName(type_0)
-                << ") and " << n.children[1]->string() << " (" << dataTypeName(type_1) << ')';
+                << "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 71e5c3c4b16d8535091b98cab298ff6624661508..88b1758e757797d0844a06185105480e341635c8 100644
--- a/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp
@@ -1,54 +1,47 @@
 #include <language/ast/ASTNodeIncDecExpressionBuilder.hpp>
 
 #include <language/PEGGrammar.hpp>
-#include <language/node_processor/IncDecExpressionProcessor.hpp>
+#include <language/utils/IncDecOperatorMangler.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
 
 ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n)
 {
-  auto set_inc_dec_operator_processor = [](ASTNode& n, const auto& operator_v) {
-    auto set_inc_dec_processor_for_value = [&](const ASTNodeDataType& data_type) {
-      using OperatorT = std::decay_t<decltype(operator_v)>;
-      switch (data_type) {
-      case ASTNodeDataType::unsigned_int_t: {
-        n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, uint64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, int64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        n.m_node_processor = std::make_unique<IncDecExpressionProcessor<OperatorT, double>>(n);
-        break;
-      }
-      default: {
-        throw ParseError("unexpected error: undefined data type for unary operator", std::vector{n.begin()});
-      }
-      }
-    };
-
-    if (not n.children[0]->is_type<language::name>()) {
-      if (n.children[0]->is_type<language::post_minusminus>() or n.children[0]->is_type<language::post_plusplus>() or
-          n.children[0]->is_type<language::unary_minusminus>() or n.children[0]->is_type<language::unary_plusplus>()) {
-        throw ParseError("chaining ++ or -- operators is not allowed", std::vector{n.children[0]->begin()});
-      } else {
-        throw ParseError("invalid operand type for unary operator", std::vector{n.children[0]->begin()});
-      }
+  const ASTNodeDataType& data_type = n.children[0]->m_data_type;
+
+  if (not n.children[0]->is_type<language::name>()) {
+    std::ostringstream error_message;
+    error_message << "invalid operand type. ++/-- operators only apply to variables";
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
+  }
+
+  const std::string inc_dec_operator_name = [&] {
+    if (n.is_type<language::unary_minusminus>()) {
+      return incDecOperatorMangler<language::unary_minusminus>(data_type);
+    } else if (n.is_type<language::unary_plusplus>()) {
+      return incDecOperatorMangler<language::unary_plusplus>(data_type);
+    } else if (n.is_type<language::post_minusminus>()) {
+      return incDecOperatorMangler<language::post_minusminus>(data_type);
+    } 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
     }
+  }();
+
+  const auto& optional_processor_builder =
+    OperatorRepository::instance().getIncDecProcessorBuilder(inc_dec_operator_name);
 
-    set_inc_dec_processor_for_value(n.m_data_type);
-  };
-
-  if (n.is_type<language::unary_minusminus>()) {
-    set_inc_dec_operator_processor(n, language::unary_minusminus{});
-  } else if (n.is_type<language::unary_plusplus>()) {
-    set_inc_dec_operator_processor(n, language::unary_plusplus{});
-  } else if (n.is_type<language::post_minusminus>()) {
-    set_inc_dec_operator_processor(n, language::post_minusminus{});
-  } else if (n.is_type<language::post_plusplus>()) {
-    set_inc_dec_operator_processor(n, language::post_plusplus{});
+  if (optional_processor_builder.has_value()) {
+    n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
   } else {
-    throw ParseError("unexpected error: undefined increment/decrement operator", std::vector{n.begin()});
+    std::ostringstream error_message;
+    error_message << "undefined affectation type: ";
+    error_message << rang::fgB::red << inc_dec_operator_name << rang::fg::reset;
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
   }
 }
diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.hpp b/src/language/ast/ASTNodeNaturalConversionChecker.hpp
index ebf83d7ca3d750d33fe6d18a6d0388bdea4c627c..9e96e49b90d5f7931aa4796a10f67dee0cfff6db 100644
--- a/src/language/ast/ASTNodeNaturalConversionChecker.hpp
+++ b/src/language/ast/ASTNodeNaturalConversionChecker.hpp
@@ -2,8 +2,8 @@
 #define AST_NODE_NATURAL_CONVERSION_CHECKER_HPP
 
 #include <language/ast/ASTNode.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
 #include <language/ast/ASTNodeSubDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 
 struct AllowRToR1Conversion
 {
diff --git a/src/language/ast/ASTNodeSubDataType.hpp b/src/language/ast/ASTNodeSubDataType.hpp
index d7844d367ae686fe88e05bc119d198288eca45c6..358aca9a1419309796b9fcb9baf8eb9825e7a4eb 100644
--- a/src/language/ast/ASTNodeSubDataType.hpp
+++ b/src/language/ast/ASTNodeSubDataType.hpp
@@ -2,7 +2,7 @@
 #define AST_NODE_SUB_DATA_TYPE_HPP
 
 #include <language/ast/ASTNode.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 
 struct ASTNodeSubDataType
 {
diff --git a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
index 7d94c3f58fe1762b582a0d984edc797b0fafd021..e011e693000d5b68de6fdd0ea98b4e7afe01a6f6 100644
--- a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -1,100 +1,35 @@
 #include <language/ast/ASTNodeUnaryOperatorExpressionBuilder.hpp>
 
 #include <language/PEGGrammar.hpp>
-#include <language/node_processor/UnaryExpressionProcessor.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
+#include <language/utils/UnaryOperatorMangler.hpp>
 
 ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n)
 {
-  auto set_unary_operator_processor = [](ASTNode& n, const auto& operator_v) {
-    using OperatorT = std::decay_t<decltype(operator_v)>;
+  const ASTNodeDataType& data_type = n.children[0]->m_data_type;
 
-    auto set_unary_operator_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
-      using ValueT = std::decay_t<decltype(value)>;
-      switch (data_type) {
-      case ASTNodeDataType::bool_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n);
-        break;
-      }
-      case ASTNodeDataType::unsigned_int_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n);
-        break;
-      }
-      default: {
-        throw ParseError("unexpected error: invalid operand type for unary operator",
-                         std::vector{n.children[0]->begin()});
-      }
-      }
-    };
+  const std::string unary_operator_name = [&] {
+    if (n.is_type<language::unary_minus>()) {
+      return unaryOperatorMangler<language::unary_minus>(data_type);
+    } 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
+    }
+  }();
 
-    auto set_unary_operator_processor_for_value = [&](const ASTNodeDataType& value_type) {
-      const ASTNodeDataType data_type = n.children[0]->m_data_type;
-      switch (value_type) {
-      case ASTNodeDataType::bool_t: {
-        set_unary_operator_processor_for_data(bool{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        set_unary_operator_processor_for_data(int64_t{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        set_unary_operator_processor_for_data(double{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::vector_t: {
-        if constexpr (std::is_same_v<OperatorT, language::unary_minus>) {
-          switch (data_type.dimension()) {
-          case 1: {
-            using ValueT       = TinyVector<1>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-          case 2: {
-            using ValueT       = TinyVector<2>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-          case 3: {
-            using ValueT       = TinyVector<3>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-            // LCOV_EXCL_START
-          default: {
-            throw ParseError("unexpected error: invalid vector dimension", std::vector{n.begin()});
-          }
-            // LCOV_EXCL_STOP
-          }
-        } else {
-          // LCOV_EXCL_START
-          throw ParseError("unexpected error: invalid unary operator for vector data", std::vector{n.begin()});
-          // LCOV_EXCL_STOP
-        }
-        break;
-      }
-      default: {
-        throw ParseError("undefined value type for unary operator", std::vector{n.begin()});
-      }
-      }
-    };
+  const auto& optional_processor_builder = OperatorRepository::instance().getUnaryProcessorBuilder(unary_operator_name);
 
-    set_unary_operator_processor_for_value(n.m_data_type);
-  };
-
-  if (n.is_type<language::unary_minus>()) {
-    set_unary_operator_processor(n, language::unary_minus{});
-  } else if (n.is_type<language::unary_not>()) {
-    set_unary_operator_processor(n, language::unary_not{});
+  if (optional_processor_builder.has_value()) {
+    n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
   } else {
-    throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
+    std::ostringstream error_message;
+    error_message << "undefined unary operator type: ";
+    error_message << rang::fgB::red << unary_operator_name << rang::fg::reset;
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
   }
 }
diff --git a/src/language/ast/CMakeLists.txt b/src/language/ast/CMakeLists.txt
index f4c31774302ccff20b3d24f686fd7e381ff43822..458690fbd4fa341b257fcfe997e489048d1f961c 100644
--- a/src/language/ast/CMakeLists.txt
+++ b/src/language/ast/CMakeLists.txt
@@ -9,7 +9,7 @@ add_library(PugsLanguageAST
   ASTNodeBuiltinFunctionExpressionBuilder.cpp
   ASTNodeDataTypeBuilder.cpp
   ASTNodeDataTypeChecker.cpp
-  ASTNodeDataType.cpp
+#  ASTNodeDataType.cpp
   ASTNodeDataTypeFlattener.cpp
   ASTNodeDeclarationToAffectationConverter.cpp
   ASTNodeEmptyBlockCleaner.cpp
diff --git a/src/language/modules/BuiltinModule.hpp b/src/language/modules/BuiltinModule.hpp
index 6ea3ee56ae6f4b8c3cbfd86ede3370a638d0bff4..2be1d162578fb0d111e6eac7ae93e10dae981bce 100644
--- a/src/language/modules/BuiltinModule.hpp
+++ b/src/language/modules/BuiltinModule.hpp
@@ -1,8 +1,8 @@
 #ifndef BUILTIN_MODULE_HPP
 #define BUILTIN_MODULE_HPP
 
-#include <language/ast/ASTNodeDataType.hpp>
 #include <language/modules/IModule.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 
 class IBuiltinFunctionEmbedder;
 class TypeDescriptor;
diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp
index abb5d527d4858f86ff3a25e68f4d666c2da8193b..65bfcafd1f1c85f077a97f6e932fa97da0079537 100644
--- a/src/language/modules/ModuleRepository.cpp
+++ b/src/language/modules/ModuleRepository.cpp
@@ -8,6 +8,7 @@
 #include <language/modules/SchemeModule.hpp>
 #include <language/modules/UtilsModule.hpp>
 #include <language/modules/VTKModule.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/ParseError.hpp>
 #include <language/utils/SymbolTable.hpp>
@@ -77,6 +78,11 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab
     this->_populateEmbedderTableT(module_name_node, module_name, populating_module.getNameTypeMap(),
                                   ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table,
                                   symbol_table.typeEmbedderTable());
+
+    for (auto [symbol_name, embedded] : populating_module.getNameTypeMap()) {
+      BasicAffectationRegisterFor<EmbeddedData>(ASTNodeDataType::build<ASTNodeDataType::type_id_t>(symbol_name));
+    }
+
   } else {
     throw ParseError(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()});
   }
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index 6cdb19dfdd36359f6cd798149c7f2908770aadd0..88d4488365427aecbffd48abf9e37a3b08e55707 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -391,7 +391,7 @@ class AffectationToTinyVectorFromListProcessor final : public INodeProcessor
   }
 };
 
-template <typename OperatorT, typename ValueT>
+template <typename ValueT>
 class AffectationToTupleProcessor final : public INodeProcessor
 {
  private:
@@ -403,7 +403,6 @@ class AffectationToTupleProcessor final : public INodeProcessor
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
-    static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator to tuples");
     DataVariant value = m_node.children[1]->execute(exec_policy);
 
     std::visit(
@@ -450,7 +449,7 @@ class AffectationToTupleProcessor final : public INodeProcessor
   }
 };
 
-template <typename OperatorT, typename ValueT>
+template <typename ValueT>
 class AffectationToTupleFromListProcessor final : public INodeProcessor
 {
  private:
@@ -562,8 +561,6 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor
   DataVariant
   execute(ExecutionPolicy& exec_policy)
   {
-    static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to tuple");
-
     std::visit(
       [&](auto&& value_list) {
         using ValueListT = std::decay_t<decltype(value_list)>;
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/node_processor/UnaryExpressionProcessor.hpp b/src/language/node_processor/UnaryExpressionProcessor.hpp
index c99c7f2dd828583c7dad8048338e68d26c807be2..055e3a028be043c8a30189b7e4cccddd99aeef4a 100644
--- a/src/language/node_processor/UnaryExpressionProcessor.hpp
+++ b/src/language/node_processor/UnaryExpressionProcessor.hpp
@@ -2,8 +2,8 @@
 #define UNARY_EXPRESSION_PROCESSOR_HPP
 
 #include <language/PEGGrammar.hpp>
+#include <language/ast/ASTNode.hpp>
 #include <language/node_processor/INodeProcessor.hpp>
-#include <language/utils/SymbolTable.hpp>
 
 template <typename Op>
 struct UnaryOp;
diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/utils/ASTNodeDataType.cpp
similarity index 99%
rename from src/language/ast/ASTNodeDataType.cpp
rename to src/language/utils/ASTNodeDataType.cpp
index 1f0847f865a6972e7865f4b50601898ab5930616..02a352ac3d0f7435c89445d4113b037bd0f54c2c 100644
--- a/src/language/ast/ASTNodeDataType.cpp
+++ b/src/language/utils/ASTNodeDataType.cpp
@@ -1,4 +1,4 @@
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 
 #include <language/PEGGrammar.hpp>
 #include <language/ast/ASTNode.hpp>
diff --git a/src/language/ast/ASTNodeDataType.hpp b/src/language/utils/ASTNodeDataType.hpp
similarity index 100%
rename from src/language/ast/ASTNodeDataType.hpp
rename to src/language/utils/ASTNodeDataType.hpp
diff --git a/src/language/utils/ASTNodeDataTypeTraits.hpp b/src/language/utils/ASTNodeDataTypeTraits.hpp
index 946d63483dc8a61c33ade0b223c0619a66880fdd..ed668e5e40e1ff4920602014367f379aa384adb9 100644
--- a/src/language/utils/ASTNodeDataTypeTraits.hpp
+++ b/src/language/utils/ASTNodeDataTypeTraits.hpp
@@ -1,8 +1,8 @@
-#ifndef AST_NODE_DATA_TYPE_TRAITS_H
-#define AST_NODE_DATA_TYPE_TRAITS_H
+#ifndef AST_NODE_DATA_TYPE_TRAITS_HPP
+#define AST_NODE_DATA_TYPE_TRAITS_HPP
 
 #include <algebra/TinyVector.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/FunctionSymbolId.hpp>
 
 #include <vector>
@@ -32,4 +32,4 @@ template <typename T>
 inline ASTNodeDataType ast_node_data_type_from<std::vector<T>> =
   ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type_from<T>);
 
-#endif   // AST_NODE_DATA_TYPE_TRAITS_H
+#endif   // AST_NODE_DATA_TYPE_TRAITS_HPP
diff --git a/src/language/utils/AffectationMangler.hpp b/src/language/utils/AffectationMangler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..85aaab35bfbabde5b9bdbc9b250f8440e68829e6
--- /dev/null
+++ b/src/language/utils/AffectationMangler.hpp
@@ -0,0 +1,52 @@
+#ifndef AFFECTATION_MANGLER_HPP
+#define AFFECTATION_MANGLER_HPP
+
+#include <language/utils/ASTNodeDataType.hpp>
+#include <utils/Exceptions.hpp>
+
+#include <string>
+
+namespace language
+{
+struct eq_op;
+struct multiplyeq_op;
+struct divideeq_op;
+struct pluseq_op;
+struct minuseq_op;
+}   // namespace language
+
+template <typename AffectationOperatorT>
+std::string
+affectationMangler(const ASTNodeDataType& lhs, const ASTNodeDataType& rhs)
+{
+  const std::string lhs_name = dataTypeName(lhs);
+
+  const std::string operator_name = [] {
+    if constexpr (std::is_same_v<language::eq_op, AffectationOperatorT>) {
+      return "=";
+    } else if constexpr (std::is_same_v<language::multiplyeq_op, AffectationOperatorT>) {
+      return "*=";
+    } else if constexpr (std::is_same_v<language::divideeq_op, AffectationOperatorT>) {
+      return "/=";
+    } else if constexpr (std::is_same_v<language::pluseq_op, AffectationOperatorT>) {
+      return "+=";
+    } else if constexpr (std::is_same_v<language::minuseq_op, AffectationOperatorT>) {
+      return "-=";
+    } else {
+      static_assert(std::is_same_v<language::eq_op, AffectationOperatorT>, "undefined affectation operator");
+    }
+  }();
+
+  const std::string rhs_name = [&]() -> std::string {
+    if (rhs == ASTNodeDataType::list_t) {
+      return "list";
+    } else if (rhs == ASTNodeDataType::tuple_t) {
+      return "tuple";
+    } else {
+      return dataTypeName(rhs);
+    }
+  }();
+  return lhs_name + " " + operator_name + " " + rhs_name;
+}
+
+#endif   // AFFECTATION_MANGLER_HPP
diff --git a/src/language/utils/AffectationProcessorBuilder.hpp b/src/language/utils/AffectationProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..02042ad8825c7c890727edba6dd5dc41691a7d9e
--- /dev/null
+++ b/src/language/utils/AffectationProcessorBuilder.hpp
@@ -0,0 +1,86 @@
+#ifndef AFFECTATION_PROCESSOR_BUILDER_HPP
+#define AFFECTATION_PROCESSOR_BUILDER_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/AffectationProcessor.hpp>
+#include <language/utils/IAffectationProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename OperatorT, typename ValueT, typename DataT>
+class AffectationProcessorBuilder final : public IAffectationProcessorBuilder
+{
+ public:
+  AffectationProcessorBuilder() = default;
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    if constexpr (std::is_same_v<ValueT, TinyVector<1>> and std::is_same_v<DataT, int64_t> and
+                  std::is_same_v<OperatorT, language::eq_op>) {
+      // Special treatment for the case 0 -> R^1
+      if ((node.children[1]->is_type<language::integer>()) and (std::stoi(node.children[1]->string()) == 0)) {
+        return std::make_unique<AffectationFromZeroProcessor<ValueT>>(node);
+      } else {
+        return std::make_unique<AffectationProcessor<OperatorT, ValueT, DataT>>(node);
+      }
+    } else {
+      return std::make_unique<AffectationProcessor<OperatorT, ValueT, DataT>>(node);
+    }
+  }
+};
+
+template <typename ValueT>
+class AffectationToTupleProcessorBuilder final : public IAffectationProcessorBuilder
+{
+ public:
+  AffectationToTupleProcessorBuilder() = default;
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<AffectationToTupleProcessor<ValueT>>(node);
+  }
+};
+
+template <typename ValueT>
+class AffectationToTupleFromListProcessorBuilder final : public IAffectationProcessorBuilder
+{
+ public:
+  AffectationToTupleFromListProcessorBuilder() = default;
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<AffectationToTupleFromListProcessor<ValueT>>(node);
+  }
+};
+
+template <typename OperatorT, typename ValueT>
+class AffectationToTinyVectorFromListProcessorBuilder final : public IAffectationProcessorBuilder
+{
+ public:
+  AffectationToTinyVectorFromListProcessorBuilder() = default;
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<AffectationToTinyVectorFromListProcessor<OperatorT, ValueT>>(node);
+  }
+};
+
+template <typename OperatorT, typename ValueT>
+class AffectationFromZeroProcessorBuilder final : public IAffectationProcessorBuilder
+{
+ public:
+  AffectationFromZeroProcessorBuilder() = default;
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    if (std::stoi(node.children[1]->string()) == 0) {
+      return std::make_unique<AffectationFromZeroProcessor<ValueT>>(node);
+    }
+    // LCOV_EXCL_START
+    throw ParseError("unexpected error: invalid integral value", std::vector{node.children[1]->begin()});
+    // LCOV_EXCL_STOP
+  }
+};
+
+#endif   // AFFECTATION_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/AffectationRegisterForB.cpp b/src/language/utils/AffectationRegisterForB.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69feaee7066a7d95f17bf539df75e46cf3fe27c5
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForB.cpp
@@ -0,0 +1,10 @@
+#include <language/utils/AffectationRegisterForB.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+AffectationRegisterForB::AffectationRegisterForB()
+{
+  BasicAffectationRegisterFor<bool>{};
+}
diff --git a/src/language/utils/AffectationRegisterForB.hpp b/src/language/utils/AffectationRegisterForB.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6507ff7a1edf0d48839924a8b3aa051ff441c09
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForB.hpp
@@ -0,0 +1,10 @@
+#ifndef AFFECTATION_REGISTER_FOR_B_HPP
+#define AFFECTATION_REGISTER_FOR_B_HPP
+
+class AffectationRegisterForB
+{
+ public:
+  AffectationRegisterForB();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_B_HPP
diff --git a/src/language/utils/AffectationRegisterForN.cpp b/src/language/utils/AffectationRegisterForN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7d54008f22845f8233b8475091c8cec774c6756
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForN.cpp
@@ -0,0 +1,120 @@
+#include <language/utils/AffectationRegisterForN.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+AffectationRegisterForN::_register_eq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository
+    .addAffectation<language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                     std::make_shared<AffectationProcessorBuilder<language::eq_op, uint64_t, bool>>());
+
+  repository.addAffectation<
+    language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, uint64_t, int64_t>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N),
+                                             ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<uint64_t>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N),
+                                             ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<uint64_t>>());
+}
+
+void
+AffectationRegisterForN::_register_pluseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addAffectation<
+    language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, bool>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForN::_register_minuseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addAffectation<
+    language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, bool>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForN::_register_multiplyeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addAffectation<
+    language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                             std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, uint64_t, bool>>());
+
+  repository.addAffectation<language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, uint64_t, uint64_t>>());
+
+  repository.addAffectation<language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, uint64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForN::_register_divideeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addAffectation<
+    language::divideeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, uint64_t, bool>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, uint64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, uint64_t, int64_t>>());
+}
+
+AffectationRegisterForN::AffectationRegisterForN()
+{
+  BasicAffectationRegisterFor<uint64_t>{};
+
+  this->_register_eq_op();
+  this->_register_pluseq_op();
+  this->_register_minuseq_op();
+  this->_register_multiplyeq_op();
+  this->_register_divideeq_op();
+}
diff --git a/src/language/utils/AffectationRegisterForN.hpp b/src/language/utils/AffectationRegisterForN.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e97a652c094635fbaa54b9b267c37f3a169367a0
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForN.hpp
@@ -0,0 +1,17 @@
+#ifndef AFFECTATION_REGISTER_FOR_N_HPP
+#define AFFECTATION_REGISTER_FOR_N_HPP
+
+class AffectationRegisterForN
+{
+ private:
+  void _register_eq_op();
+  void _register_pluseq_op();
+  void _register_minuseq_op();
+  void _register_multiplyeq_op();
+  void _register_divideeq_op();
+
+ public:
+  AffectationRegisterForN();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_N_HPP
diff --git a/src/language/utils/AffectationRegisterForR.cpp b/src/language/utils/AffectationRegisterForR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae7c63c4031f39871f64713c39cc7dcba8e0bae4
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForR.cpp
@@ -0,0 +1,141 @@
+#include <language/utils/AffectationRegisterForR.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+AffectationRegisterForR::_register_eq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository
+    .addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                     std::make_shared<AffectationProcessorBuilder<language::eq_op, double, bool>>());
+
+  repository.addAffectation<
+    language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, double, uint64_t>>());
+
+  repository
+    .addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                     std::make_shared<AffectationProcessorBuilder<language::eq_op, double, int64_t>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R),
+                                             ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<double>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R),
+                                             ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<double>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R),
+                                             ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<double>>());
+}
+
+void
+AffectationRegisterForR::_register_pluseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addAffectation<
+    language::pluseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, double, bool>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, double, uint64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, double, int64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(R, R, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, double, double>>());
+}
+
+void
+AffectationRegisterForR::_register_minuseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addAffectation<
+    language::minuseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, double, bool>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, double, uint64_t>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, double, int64_t>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(R, R, std::make_shared<AffectationProcessorBuilder<language::minuseq_op, double, double>>());
+}
+
+void
+AffectationRegisterForR::_register_multiplyeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addAffectation<
+    language::multiplyeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                             std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, double, bool>>());
+
+  repository.addAffectation<language::multiplyeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, double, uint64_t>>());
+
+  repository.addAffectation<
+    language::multiplyeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                             std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, double, int64_t>>());
+
+  repository.addAffectation<
+    language::multiplyeq_op>(R, R,
+                             std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, double, double>>());
+}
+
+void
+AffectationRegisterForR::_register_divideeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addAffectation<
+    language::divideeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, double, bool>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, double, uint64_t>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, double, int64_t>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(R, R,
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, double, double>>());
+}
+
+AffectationRegisterForR::AffectationRegisterForR()
+{
+  BasicAffectationRegisterFor<double>{};
+  this->_register_eq_op();
+  this->_register_pluseq_op();
+  this->_register_minuseq_op();
+  this->_register_multiplyeq_op();
+  this->_register_divideeq_op();
+}
diff --git a/src/language/utils/AffectationRegisterForR.hpp b/src/language/utils/AffectationRegisterForR.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a004a92a276edad8dc52b015c2802aa4055aa11
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForR.hpp
@@ -0,0 +1,17 @@
+#ifndef AFFECTATION_REGISTER_FOR_R_HPP
+#define AFFECTATION_REGISTER_FOR_R_HPP
+
+class AffectationRegisterForR
+{
+ private:
+  void _register_eq_op();
+  void _register_pluseq_op();
+  void _register_minuseq_op();
+  void _register_multiplyeq_op();
+  void _register_divideeq_op();
+
+ public:
+  AffectationRegisterForR();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_R_HPP
diff --git a/src/language/utils/AffectationRegisterForRn.cpp b/src/language/utils/AffectationRegisterForRn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d38dc64c1d245d4d6c530e891ffd6eaecd63372
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForRn.cpp
@@ -0,0 +1,143 @@
+#include <language/utils/AffectationRegisterForRn.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+template <size_t Dimension>
+void
+AffectationRegisterForRn<Dimension>::_register_eq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository.addAffectation<
+    language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                     std::make_shared<AffectationFromZeroProcessorBuilder<language::eq_op, TinyVector<Dimension>>>());
+
+  repository.addAffectation<language::eq_op>(Rn,
+                                             ASTNodeDataType::build<ASTNodeDataType::list_t>(
+                                               std::vector<std::shared_ptr<const ASTNodeDataType>>{}),
+                                             std::make_shared<AffectationToTinyVectorFromListProcessorBuilder<
+                                               language::eq_op, TinyVector<Dimension>>>());
+
+  repository
+    .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn),
+                                     ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                     std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>());
+}
+
+template <>
+void
+AffectationRegisterForRn<1>::_register_eq_op()
+{
+  constexpr size_t Dimension = 1;
+
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository.addAffectation<
+    language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, bool>>());
+
+  repository.addAffectation<
+    language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, uint64_t>>());
+
+  repository.addAffectation<
+    language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, int64_t>>());
+
+  repository.addAffectation<
+    language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, double>>());
+
+  repository
+    .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn),
+                                     ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                     std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>());
+
+  repository
+    .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn),
+                                     ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                     std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>());
+
+  repository
+    .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn),
+                                     ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                     std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>());
+
+  repository
+    .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn),
+                                     ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                                     std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>());
+}
+
+template <size_t Dimension>
+void
+AffectationRegisterForRn<Dimension>::_register_pluseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository
+    .addAffectation<language::pluseq_op>(Rn, Rn,
+                                         std::make_shared<AffectationProcessorBuilder<
+                                           language::pluseq_op, TinyVector<Dimension>, TinyVector<Dimension>>>());
+}
+
+template <size_t Dimension>
+void
+AffectationRegisterForRn<Dimension>::_register_minuseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository
+    .addAffectation<language::minuseq_op>(Rn, Rn,
+                                          std::make_shared<AffectationProcessorBuilder<
+                                            language::minuseq_op, TinyVector<Dimension>, TinyVector<Dimension>>>());
+}
+
+template <size_t Dimension>
+void
+AffectationRegisterForRn<Dimension>::_register_multiplyeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, TinyVector<Dimension>, bool>>());
+
+  repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, TinyVector<Dimension>, uint64_t>>());
+
+  repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, TinyVector<Dimension>, int64_t>>());
+
+  repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, TinyVector<Dimension>, double>>());
+}
+
+template <size_t Dimension>
+AffectationRegisterForRn<Dimension>::AffectationRegisterForRn()
+{
+  BasicAffectationRegisterFor<TinyVector<Dimension>>{};
+  this->_register_eq_op();
+  this->_register_pluseq_op();
+  this->_register_minuseq_op();
+  this->_register_multiplyeq_op();
+}
+
+template class AffectationRegisterForRn<1>;
+template class AffectationRegisterForRn<2>;
+template class AffectationRegisterForRn<3>;
diff --git a/src/language/utils/AffectationRegisterForRn.hpp b/src/language/utils/AffectationRegisterForRn.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..337a340b81b7a59d35ee11dd5946d2313560ebe8
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForRn.hpp
@@ -0,0 +1,19 @@
+#ifndef AFFECTATION_REGISTER_FOR_RN_HPP
+#define AFFECTATION_REGISTER_FOR_RN_HPP
+
+#include <cstdlib>
+
+template <size_t Dimension>
+class AffectationRegisterForRn
+{
+ private:
+  void _register_eq_op();
+  void _register_pluseq_op();
+  void _register_minuseq_op();
+  void _register_multiplyeq_op();
+
+ public:
+  AffectationRegisterForRn();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_RN_HPP
diff --git a/src/language/utils/AffectationRegisterForString.cpp b/src/language/utils/AffectationRegisterForString.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..37446e243d6fcb14fcd6c3e97a845d17b831c2e6
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForString.cpp
@@ -0,0 +1,140 @@
+#include <language/utils/AffectationRegisterForString.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+AffectationRegisterForString::_register_eq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto string_t = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, bool>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, uint64_t>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, int64_t>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, double_t>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<1>>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<2>>>());
+
+  repository.addAffectation<
+    language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<3>>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t),
+                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<std::string>>());
+}
+
+void
+AffectationRegisterForString::_register_pluseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto string_t = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+
+  repository.addAffectation<language::pluseq_op>(string_t, string_t,
+                                                 std::make_shared<AffectationProcessorBuilder<
+                                                   language::pluseq_op, std::string, std::string>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, bool>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, uint64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, int64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::double_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, double>>());
+
+  repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                                 std::make_shared<AffectationProcessorBuilder<
+                                                   language::pluseq_op, std::string, TinyVector<1>>>());
+
+  repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                                                 std::make_shared<AffectationProcessorBuilder<
+                                                   language::pluseq_op, std::string, TinyVector<2>>>());
+
+  repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                                                 std::make_shared<AffectationProcessorBuilder<
+                                                   language::pluseq_op, std::string, TinyVector<3>>>());
+
+  // this->_addAffectation("string += string",
+  //                       std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string,
+  //                       std::string>>());
+  // this->_addAffectation("string += B",
+  //                       std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, bool>>());
+  // this->_addAffectation("string += N",
+  //                       std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, uint64_t>>());
+  // this->_addAffectation("string += Z",
+  //                       std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, int64_t>>());
+  // this->_addAffectation("string += R",
+  //                       std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, double>>());
+  // this
+  //   ->_addAffectation("string += R^1",
+  //                     std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string,
+  //                     TinyVector<1>>>());
+  // this
+  //   ->_addAffectation("string += R^2",
+  //                     std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string,
+  //                     TinyVector<2>>>());
+  // this
+  //   ->_addAffectation("string += R^3",
+  //                     std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string,
+  //                     TinyVector<3>>>());
+}
+
+AffectationRegisterForString::AffectationRegisterForString()
+{
+  BasicAffectationRegisterFor<std::string>{};
+  this->_register_eq_op();
+  this->_register_pluseq_op();
+}
diff --git a/src/language/utils/AffectationRegisterForString.hpp b/src/language/utils/AffectationRegisterForString.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6b6a47d4fcfe913f486d1069e73920795e1d451
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForString.hpp
@@ -0,0 +1,14 @@
+#ifndef AFFECTATION_REGISTER_FOR_STRING_HPP
+#define AFFECTATION_REGISTER_FOR_STRING_HPP
+
+class AffectationRegisterForString
+{
+ private:
+  void _register_eq_op();
+  void _register_pluseq_op();
+
+ public:
+  AffectationRegisterForString();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_STRING_HPP
diff --git a/src/language/utils/AffectationRegisterForZ.cpp b/src/language/utils/AffectationRegisterForZ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9937a0edbaedce2ae054d02fc13d7c4e1168c698
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForZ.cpp
@@ -0,0 +1,119 @@
+#include <language/utils/AffectationRegisterForZ.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+AffectationRegisterForZ::_register_eq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository
+    .addAffectation<language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                     std::make_shared<AffectationProcessorBuilder<language::eq_op, int64_t, bool>>());
+
+  repository.addAffectation<
+    language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                     std::make_shared<AffectationProcessorBuilder<language::eq_op, int64_t, uint64_t>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z),
+                                             ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<int64_t>>());
+
+  repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z),
+                                             ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                             std::make_shared<AffectationToTupleProcessorBuilder<int64_t>>());
+}
+
+void
+AffectationRegisterForZ::_register_pluseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addAffectation<
+    language::pluseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, int64_t, bool>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, int64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::pluseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                         std::make_shared<AffectationProcessorBuilder<language::pluseq_op, int64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForZ::_register_minuseq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addAffectation<
+    language::minuseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, int64_t, bool>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, int64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::minuseq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                          std::make_shared<AffectationProcessorBuilder<language::minuseq_op, int64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForZ::_register_multiplyeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addAffectation<
+    language::multiplyeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                             std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, int64_t, bool>>());
+
+  repository.addAffectation<language::multiplyeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, int64_t, uint64_t>>());
+
+  repository.addAffectation<language::multiplyeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                                                     std::make_shared<AffectationProcessorBuilder<
+                                                       language::multiplyeq_op, int64_t, int64_t>>());
+}
+
+void
+AffectationRegisterForZ::_register_divideeq_op()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addAffectation<
+    language::divideeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, int64_t, bool>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, int64_t, uint64_t>>());
+
+  repository.addAffectation<
+    language::divideeq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::int_t>(),
+                           std::make_shared<AffectationProcessorBuilder<language::divideeq_op, int64_t, int64_t>>());
+}
+
+AffectationRegisterForZ::AffectationRegisterForZ()
+{
+  BasicAffectationRegisterFor<int64_t>{};
+  this->_register_eq_op();
+  this->_register_pluseq_op();
+  this->_register_minuseq_op();
+  this->_register_multiplyeq_op();
+  this->_register_divideeq_op();
+}
diff --git a/src/language/utils/AffectationRegisterForZ.hpp b/src/language/utils/AffectationRegisterForZ.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a559c94fda9ef5a089d85af9f9773693ce9c9fb4
--- /dev/null
+++ b/src/language/utils/AffectationRegisterForZ.hpp
@@ -0,0 +1,17 @@
+#ifndef AFFECTATION_REGISTER_FOR_Z_HPP
+#define AFFECTATION_REGISTER_FOR_Z_HPP
+
+class AffectationRegisterForZ
+{
+ private:
+  void _register_eq_op();
+  void _register_pluseq_op();
+  void _register_minuseq_op();
+  void _register_multiplyeq_op();
+  void _register_divideeq_op();
+
+ public:
+  AffectationRegisterForZ();
+};
+
+#endif   // AFFECTATION_REGISTER_FOR_Z_HPP
diff --git a/src/language/utils/BasicAffectationRegistrerFor.hpp b/src/language/utils/BasicAffectationRegistrerFor.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccae4c32b596b39ce7b663da38e31e70c8dfbebc
--- /dev/null
+++ b/src/language/utils/BasicAffectationRegistrerFor.hpp
@@ -0,0 +1,36 @@
+#ifndef BASIC_AFFECTATION_REGISTRER_FOR_HPP
+#define BASIC_AFFECTATION_REGISTRER_FOR_HPP
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+template <typename T>
+class BasicAffectationRegisterFor
+{
+ public:
+  BasicAffectationRegisterFor() : BasicAffectationRegisterFor(ast_node_data_type_from<T>) {}
+
+  BasicAffectationRegisterFor(const ASTNodeDataType& ast_node_data_type)
+  {
+    OperatorRepository& repository = OperatorRepository::instance();
+
+    repository.addAffectation<language::eq_op>(ast_node_data_type, ast_node_data_type,
+                                               std::make_shared<AffectationProcessorBuilder<language::eq_op, T, T>>());
+
+    repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type),
+                                               ast_node_data_type,
+                                               std::make_shared<AffectationToTupleProcessorBuilder<T>>());
+
+    repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type),
+                                               ASTNodeDataType::build<ASTNodeDataType::list_t>(
+                                                 std::vector<std::shared_ptr<const ASTNodeDataType>>{}),
+                                               std::make_shared<AffectationToTupleFromListProcessorBuilder<T>>());
+
+    repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type),
+                                               ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type),
+                                               std::make_shared<AffectationToTupleFromListProcessorBuilder<T>>());
+  }
+};
+
+#endif   // BASIC_AFFECTATION_REGISTRER_FOR_HPP
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/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp
index d394aa20f9721a1dc12821960890d0c1f0b6db1c..afb991acadcb36236bcd55a34c7840ca399ab6f0 100644
--- a/src/language/utils/BuiltinFunctionEmbedder.hpp
+++ b/src/language/utils/BuiltinFunctionEmbedder.hpp
@@ -1,7 +1,7 @@
 #ifndef BUILTIN_FUNCTION_EMBEDDER_HPP
 #define BUILTIN_FUNCTION_EMBEDDER_HPP
 
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/DataHandler.hpp>
 #include <language/utils/DataVariant.hpp>
diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt
index 1cb991d6c6d19a18579d3c0802a6ea032891d5c2..ed105ca479f5b17c3366d44320505dba5d2eacad 100644
--- a/src/language/utils/CMakeLists.txt
+++ b/src/language/utils/CMakeLists.txt
@@ -1,11 +1,33 @@
 # ------------------- Source files --------------------
 
 add_library(PugsLanguageUtils
+  AffectationRegisterForB.cpp
+  AffectationRegisterForN.cpp
+  AffectationRegisterForR.cpp
+  AffectationRegisterForRn.cpp
+  AffectationRegisterForString.cpp
+  AffectationRegisterForZ.cpp
   ASTDotPrinter.cpp
   ASTExecutionInfo.cpp
+  ASTNodeDataType.cpp
   ASTPrinter.cpp
+  BinaryOperatorRegisterForB.cpp
+  BinaryOperatorRegisterForN.cpp
+  BinaryOperatorRegisterForR.cpp
+  BinaryOperatorRegisterForRn.cpp
+  BinaryOperatorRegisterForString.cpp
+  BinaryOperatorRegisterForZ.cpp
   DataVariant.cpp
   EmbeddedData.cpp
+  IncDecOperatorRegisterForN.cpp
+  IncDecOperatorRegisterForR.cpp
+  IncDecOperatorRegisterForZ.cpp
+  OperatorRepository.cpp
+  UnaryOperatorRegisterForB.cpp
+  UnaryOperatorRegisterForN.cpp
+  UnaryOperatorRegisterForR.cpp
+  UnaryOperatorRegisterForRn.cpp
+  UnaryOperatorRegisterForZ.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/FunctionTable.hpp b/src/language/utils/FunctionTable.hpp
index 43232fd60e4482a73dca1a4b257c7a6c0b6ef28a..6c6450c22ff8ff845ddd0c90dbcead1eec52203c 100644
--- a/src/language/utils/FunctionTable.hpp
+++ b/src/language/utils/FunctionTable.hpp
@@ -2,7 +2,7 @@
 #define FUNCTION_TABLE_HPP
 
 #include <language/ast/ASTNode.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/DataVariant.hpp>
 #include <utils/PugsAssert.hpp>
 
@@ -63,14 +63,16 @@ class FunctionTable
   }
 
   PUGS_INLINE
-  FunctionDescriptor& operator[](size_t function_id)
+  FunctionDescriptor&
+  operator[](size_t function_id)
   {
     Assert(function_id < m_function_descriptor_list.size());
     return m_function_descriptor_list[function_id];
   }
 
   PUGS_INLINE
-  const FunctionDescriptor& operator[](size_t function_id) const
+  const FunctionDescriptor&
+  operator[](size_t function_id) const
   {
     Assert(function_id < m_function_descriptor_list.size());
     return m_function_descriptor_list[function_id];
diff --git a/src/language/utils/IAffectationProcessorBuilder.hpp b/src/language/utils/IAffectationProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d5f8540df9435bba4b86e6bee22f980b5727d7b
--- /dev/null
+++ b/src/language/utils/IAffectationProcessorBuilder.hpp
@@ -0,0 +1,17 @@
+#ifndef I_AFFECTATION_PROCESSOR_BUILDER_HPP
+#define I_AFFECTATION_PROCESSOR_BUILDER_HPP
+
+class ASTNode;
+class INodeProcessor;
+
+#include <memory>
+
+class IAffectationProcessorBuilder
+{
+ public:
+  virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+
+  virtual ~IAffectationProcessorBuilder() = default;
+};
+
+#endif   // I_AFFECTATION_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
new file mode 100644
index 0000000000000000000000000000000000000000..b84974a332326afa293757576efd6e2bdf40795e
--- /dev/null
+++ b/src/language/utils/IIncDecOperatorProcessorBuilder.hpp
@@ -0,0 +1,20 @@
+#ifndef I_INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
+#define I_INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
+
+class ASTNode;
+class INodeProcessor;
+#include <language/utils/ASTNodeDataType.hpp>
+
+#include <memory>
+
+class IIncDecOperatorProcessorBuilder
+{
+ public:
+  [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+
+  [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0;
+
+  virtual ~IIncDecOperatorProcessorBuilder() = default;
+};
+
+#endif   // I_INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..19b36e2feb42b9efc558ff5e554532c0f3d32824
--- /dev/null
+++ b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,21 @@
+#ifndef I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+class ASTNode;
+class INodeProcessor;
+
+#include <language/utils/ASTNodeDataType.hpp>
+
+#include <memory>
+
+class IUnaryOperatorProcessorBuilder
+{
+ public:
+  [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+
+  [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0;
+
+  virtual ~IUnaryOperatorProcessorBuilder() = default;
+};
+
+#endif   // I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/IncDecOperatorMangler.hpp b/src/language/utils/IncDecOperatorMangler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed5a84ae44c327116dbddef71880bd7b601fd97f
--- /dev/null
+++ b/src/language/utils/IncDecOperatorMangler.hpp
@@ -0,0 +1,34 @@
+#ifndef INC_DEC_OPERATOR_MANGLER_HPP
+#define INC_DEC_OPERATOR_MANGLER_HPP
+
+#include <language/utils/ASTNodeDataType.hpp>
+#include <utils/Exceptions.hpp>
+
+#include <string>
+
+namespace language
+{
+struct unary_minusminus;
+struct unary_plusplus;
+struct post_minusminus;
+struct post_plusplus;
+}   // namespace language
+
+template <typename IncDecOperatorT>
+std::string
+incDecOperatorMangler(const ASTNodeDataType& operand)
+{
+  if constexpr (std::is_same_v<language::unary_minusminus, IncDecOperatorT>) {
+    return std::string{"-- "} + dataTypeName(operand);
+  } else if constexpr (std::is_same_v<language::post_minusminus, IncDecOperatorT>) {
+    return dataTypeName(operand) + " --";
+  } else if constexpr (std::is_same_v<language::unary_plusplus, IncDecOperatorT>) {
+    return std::string{"++ "} + dataTypeName(operand);
+  } else if constexpr (std::is_same_v<language::post_plusplus, IncDecOperatorT>) {
+    return dataTypeName(operand) + " ++";
+  } else {
+    static_assert(std::is_same_v<language::unary_minusminus, IncDecOperatorT>, "undefined inc/dec operator");
+  }
+}
+
+#endif   // INC_DEC_OPERATOR_MANGLER_HPP
diff --git a/src/language/utils/IncDecOperatorProcessorBuilder.hpp b/src/language/utils/IncDecOperatorProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..40da865ddf9c6ed480a859e9a158d21cb5562848
--- /dev/null
+++ b/src/language/utils/IncDecOperatorProcessorBuilder.hpp
@@ -0,0 +1,31 @@
+#ifndef INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
+#define INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/IncDecExpressionProcessor.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/IIncDecOperatorProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename OperatorT, typename DataT>
+class IncDecOperatorProcessorBuilder final : public IIncDecOperatorProcessorBuilder
+{
+ public:
+  IncDecOperatorProcessorBuilder() = default;
+
+  ASTNodeDataType
+  getReturnValueType() const
+  {
+    return ast_node_data_type_from<DataT>;
+  }
+
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<IncDecExpressionProcessor<OperatorT, DataT>>(node);
+  }
+};
+
+#endif   // INC_DEC_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/IncDecOperatorRegisterForN.cpp b/src/language/utils/IncDecOperatorRegisterForN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e6a6369fcef13242abde08ffb59e75778b4793a
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForN.cpp
@@ -0,0 +1,58 @@
+#include <language/utils/IncDecOperatorRegisterForN.hpp>
+
+#include <language/utils/IncDecOperatorProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+IncDecOperatorRegisterForN::_register_unary_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addIncDecOperator<language::unary_minusminus>(N, std::make_shared<IncDecOperatorProcessorBuilder<
+                                                                language::unary_minusminus, uint64_t>>());
+}
+
+void
+IncDecOperatorRegisterForN::_register_unary_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addIncDecOperator<
+    language::unary_plusplus>(N,
+                              std::make_shared<IncDecOperatorProcessorBuilder<language::unary_plusplus, uint64_t>>());
+}
+
+void
+IncDecOperatorRegisterForN::_register_post_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addIncDecOperator<
+    language::post_minusminus>(N,
+                               std::make_shared<IncDecOperatorProcessorBuilder<language::post_minusminus, uint64_t>>());
+}
+
+void
+IncDecOperatorRegisterForN::_register_post_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addIncDecOperator<
+    language::post_plusplus>(N, std::make_shared<IncDecOperatorProcessorBuilder<language::post_plusplus, uint64_t>>());
+}
+
+IncDecOperatorRegisterForN::IncDecOperatorRegisterForN()
+{
+  this->_register_unary_minusminus();
+  this->_register_unary_plusplus();
+  this->_register_post_minusminus();
+  this->_register_post_plusplus();
+}
diff --git a/src/language/utils/IncDecOperatorRegisterForN.hpp b/src/language/utils/IncDecOperatorRegisterForN.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3e2682d8a0fb0122f813ec633bb08a37e997922
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForN.hpp
@@ -0,0 +1,16 @@
+#ifndef INC_DEC_OPERATOR_REGISTER_FOR_N_HPP
+#define INC_DEC_OPERATOR_REGISTER_FOR_N_HPP
+
+class IncDecOperatorRegisterForN
+{
+ private:
+  void _register_unary_minusminus();
+  void _register_unary_plusplus();
+  void _register_post_minusminus();
+  void _register_post_plusplus();
+
+ public:
+  IncDecOperatorRegisterForN();
+};
+
+#endif   // INC_DEC_OPERATOR_REGISTER_FOR_N_HPP
diff --git a/src/language/utils/IncDecOperatorRegisterForR.cpp b/src/language/utils/IncDecOperatorRegisterForR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5031751468f6593d5eab1839cdf1f778c56837e7
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForR.cpp
@@ -0,0 +1,58 @@
+#include <language/utils/IncDecOperatorRegisterForR.hpp>
+
+#include <language/utils/IncDecOperatorProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+IncDecOperatorRegisterForR::_register_unary_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addIncDecOperator<language::unary_minusminus>(R, std::make_shared<IncDecOperatorProcessorBuilder<
+                                                                language::unary_minusminus, double_t>>());
+}
+
+void
+IncDecOperatorRegisterForR::_register_unary_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addIncDecOperator<
+    language::unary_plusplus>(R,
+                              std::make_shared<IncDecOperatorProcessorBuilder<language::unary_plusplus, double_t>>());
+}
+
+void
+IncDecOperatorRegisterForR::_register_post_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addIncDecOperator<
+    language::post_minusminus>(R,
+                               std::make_shared<IncDecOperatorProcessorBuilder<language::post_minusminus, double_t>>());
+}
+
+void
+IncDecOperatorRegisterForR::_register_post_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addIncDecOperator<
+    language::post_plusplus>(R, std::make_shared<IncDecOperatorProcessorBuilder<language::post_plusplus, double_t>>());
+}
+
+IncDecOperatorRegisterForR::IncDecOperatorRegisterForR()
+{
+  this->_register_unary_minusminus();
+  this->_register_unary_plusplus();
+  this->_register_post_minusminus();
+  this->_register_post_plusplus();
+}
diff --git a/src/language/utils/IncDecOperatorRegisterForR.hpp b/src/language/utils/IncDecOperatorRegisterForR.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ede6b9999347788f9447d7b5eeb9fe28b8e4da7
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForR.hpp
@@ -0,0 +1,16 @@
+#ifndef INC_DEC_OPERATOR_REGISTER_FOR_R_HPP
+#define INC_DEC_OPERATOR_REGISTER_FOR_R_HPP
+
+class IncDecOperatorRegisterForR
+{
+ private:
+  void _register_unary_minusminus();
+  void _register_unary_plusplus();
+  void _register_post_minusminus();
+  void _register_post_plusplus();
+
+ public:
+  IncDecOperatorRegisterForR();
+};
+
+#endif   // INC_DEC_OPERATOR_REGISTER_FOR_Z_HPP
diff --git a/src/language/utils/IncDecOperatorRegisterForZ.cpp b/src/language/utils/IncDecOperatorRegisterForZ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5a0bc0faa8bcf3ef0bcbed4837c44f5c9f147aa3
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForZ.cpp
@@ -0,0 +1,57 @@
+#include <language/utils/IncDecOperatorRegisterForZ.hpp>
+
+#include <language/utils/IncDecOperatorProcessorBuilder.hpp>
+#include <language/utils/OperatorRepository.hpp>
+
+void
+IncDecOperatorRegisterForZ::_register_unary_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addIncDecOperator<language::unary_minusminus>(Z, std::make_shared<IncDecOperatorProcessorBuilder<
+                                                                language::unary_minusminus, int64_t>>());
+}
+
+void
+IncDecOperatorRegisterForZ::_register_unary_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addIncDecOperator<
+    language::unary_plusplus>(Z, std::make_shared<IncDecOperatorProcessorBuilder<language::unary_plusplus, int64_t>>());
+}
+
+void
+IncDecOperatorRegisterForZ::_register_post_minusminus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addIncDecOperator<
+    language::post_minusminus>(N,
+                               std::make_shared<IncDecOperatorProcessorBuilder<language::post_minusminus, int64_t>>());
+}
+
+void
+IncDecOperatorRegisterForZ::_register_post_plusplus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addIncDecOperator<
+    language::post_plusplus>(Z, std::make_shared<IncDecOperatorProcessorBuilder<language::post_plusplus, int64_t>>());
+}
+
+IncDecOperatorRegisterForZ::IncDecOperatorRegisterForZ()
+{
+  this->_register_unary_minusminus();
+  this->_register_unary_plusplus();
+  this->_register_post_minusminus();
+  this->_register_post_plusplus();
+}
diff --git a/src/language/utils/IncDecOperatorRegisterForZ.hpp b/src/language/utils/IncDecOperatorRegisterForZ.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4ab27770b5a144245a297751a48d0b00f8322ba
--- /dev/null
+++ b/src/language/utils/IncDecOperatorRegisterForZ.hpp
@@ -0,0 +1,16 @@
+#ifndef INC_DEC_OPERATOR_REGISTER_FOR_Z_HPP
+#define INC_DEC_OPERATOR_REGISTER_FOR_Z_HPP
+
+class IncDecOperatorRegisterForZ
+{
+ private:
+  void _register_unary_minusminus();
+  void _register_unary_plusplus();
+  void _register_post_minusminus();
+  void _register_post_plusplus();
+
+ public:
+  IncDecOperatorRegisterForZ();
+};
+
+#endif   // INC_DEC_OPERATOR_REGISTER_FOR_Z_HPP
diff --git a/src/language/utils/OperatorRepository.cpp b/src/language/utils/OperatorRepository.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..93856da8c33793cad9189a25285b612b550f8d61
--- /dev/null
+++ b/src/language/utils/OperatorRepository.cpp
@@ -0,0 +1,90 @@
+#include <language/utils/OperatorRepository.hpp>
+
+#include <language/utils/AffectationProcessorBuilder.hpp>
+#include <language/utils/AffectationRegisterForB.hpp>
+#include <language/utils/AffectationRegisterForN.hpp>
+#include <language/utils/AffectationRegisterForR.hpp>
+#include <language/utils/AffectationRegisterForRn.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>
+#include <language/utils/UnaryOperatorRegisterForRn.hpp>
+#include <language/utils/UnaryOperatorRegisterForZ.hpp>
+
+#include <utils/PugsAssert.hpp>
+
+OperatorRepository* OperatorRepository::m_instance = nullptr;
+
+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();
+}
+
+void
+OperatorRepository::create()
+{
+  Assert(m_instance == nullptr, "AffectationRepository was already created");
+  m_instance = new OperatorRepository;
+  m_instance->_initialize();
+}
+
+void
+OperatorRepository::destroy()
+{
+  Assert(m_instance != nullptr, "AffectationRepository was not created");
+  delete m_instance;
+  m_instance = nullptr;
+}
+
+void
+OperatorRepository::_initialize()
+{
+  AffectationRegisterForB{};
+  AffectationRegisterForN{};
+  AffectationRegisterForZ{};
+  AffectationRegisterForR{};
+  AffectationRegisterForRn<1>{};
+  AffectationRegisterForRn<2>{};
+  AffectationRegisterForRn<3>{};
+  AffectationRegisterForString{};
+
+  BinaryOperatorRegisterForB{};
+  BinaryOperatorRegisterForN{};
+  BinaryOperatorRegisterForZ{};
+  BinaryOperatorRegisterForR{};
+  BinaryOperatorRegisterForRn<1>{};
+  BinaryOperatorRegisterForRn<2>{};
+  BinaryOperatorRegisterForRn<3>{};
+  BinaryOperatorRegisterForString{};
+
+  IncDecOperatorRegisterForN{};
+  IncDecOperatorRegisterForR{};
+  IncDecOperatorRegisterForZ{};
+
+  UnaryOperatorRegisterForB{};
+  UnaryOperatorRegisterForN{};
+  UnaryOperatorRegisterForZ{};
+  UnaryOperatorRegisterForR{};
+  UnaryOperatorRegisterForRn<1>{};
+  UnaryOperatorRegisterForRn<2>{};
+  UnaryOperatorRegisterForRn<3>{};
+}
diff --git a/src/language/utils/OperatorRepository.hpp b/src/language/utils/OperatorRepository.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ac61e6e245f8f545e4794ffb4bd4703d4806b82
--- /dev/null
+++ b/src/language/utils/OperatorRepository.hpp
@@ -0,0 +1,224 @@
+#ifndef OPERATOR_REPOSITORY_HPP
+#define OPERATOR_REPOSITORY_HPP
+
+#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>
+#include <language/utils/UnaryOperatorMangler.hpp>
+
+#include <utils/Exceptions.hpp>
+
+#include <optional>
+#include <unordered_map>
+
+class OperatorRepository
+{
+ private:
+  template <typename ProcessorBuilderT>
+  class Descriptor
+  {
+   private:
+    ASTNodeDataType m_value_type;
+    std::shared_ptr<const ProcessorBuilderT> m_processor_builder;
+
+   public:
+    const ASTNodeDataType&
+    valueType() const
+    {
+      return m_value_type;
+    }
+
+    const std::shared_ptr<const ProcessorBuilderT>&
+    processorBuilder() const
+    {
+      return m_processor_builder;
+    }
+
+    Descriptor(const ASTNodeDataType& value_type, const std::shared_ptr<const ProcessorBuilderT>& processor_builder)
+      : m_value_type{value_type}, m_processor_builder{processor_builder}
+    {}
+
+    Descriptor(const Descriptor&) = default;
+    Descriptor(Descriptor&&)      = default;
+    Descriptor()                  = default;
+    ~Descriptor()                 = default;
+  };
+
+  std::unordered_map<std::string, Descriptor<IAffectationProcessorBuilder>> m_affectation_builder_list;
+
+  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();
+
+ 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,
+                 const ASTNodeDataType& rhs_type,
+                 const std::shared_ptr<const IAffectationProcessorBuilder>& processor_builder)
+  {
+    const std::string affectation_type_name = affectationMangler<OperatorTypeT>(lhs_type, rhs_type);
+    if (not m_affectation_builder_list
+              .try_emplace(affectation_type_name,
+                           Descriptor{ASTNodeDataType::build<ASTNodeDataType::void_t>(), processor_builder})
+              .second) {
+      // LCOV_EXCL_START
+      throw UnexpectedError(affectation_type_name + " has already an entry");
+      // LCOV_EXCL_STOP
+    }
+  }
+
+  template <typename OperatorTypeT>
+  void
+  addIncDecOperator(const ASTNodeDataType& operand_type,
+                    const std::shared_ptr<const IIncDecOperatorProcessorBuilder>& processor_builder)
+  {
+    const std::string inc_dec_operator_type_name = incDecOperatorMangler<OperatorTypeT>(operand_type);
+    if (auto [i_descriptor, success] =
+          m_inc_dec_operator_builder_list.try_emplace(inc_dec_operator_type_name,
+                                                      Descriptor{processor_builder->getReturnValueType(),
+                                                                 processor_builder});
+        not success) {
+      // LCOV_EXCL_START
+      throw UnexpectedError(inc_dec_operator_type_name + " has already an entry");
+      // LCOV_EXCL_STOP
+    }
+  }
+
+  template <typename OperatorTypeT>
+  void
+  addUnaryOperator(const ASTNodeDataType& operand_type,
+                   const std::shared_ptr<const IUnaryOperatorProcessorBuilder>& processor_builder)
+  {
+    const std::string unary_operator_type_name = unaryOperatorMangler<OperatorTypeT>(operand_type);
+    if (auto [i_descriptor, success] =
+          m_unary_operator_builder_list.try_emplace(unary_operator_type_name,
+                                                    Descriptor{processor_builder->getReturnValueType(),
+                                                               processor_builder});
+        not success) {
+      // LCOV_EXCL_START
+      throw UnexpectedError(unary_operator_type_name + " has already an entry");
+      // LCOV_EXCL_STOP
+    }
+  }
+
+  [[nodiscard]] std::optional<std::shared_ptr<const IAffectationProcessorBuilder>>
+  getAffectationProcessorBuilder(const std::string& name) const
+  {
+    auto&& processor_builder = m_affectation_builder_list.find(name);
+    if (processor_builder != m_affectation_builder_list.end()) {
+      return processor_builder->second.processorBuilder();
+    }
+    return {};
+  }
+
+  [[nodiscard]] std::optional<std::shared_ptr<const IIncDecOperatorProcessorBuilder>>
+  getIncDecProcessorBuilder(const std::string& name) const
+  {
+    auto&& processor_builder = m_inc_dec_operator_builder_list.find(name);
+    if (processor_builder != m_inc_dec_operator_builder_list.end()) {
+      return processor_builder->second.processorBuilder();
+    }
+    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
+  {
+    auto&& processor_builder = m_unary_operator_builder_list.find(name);
+    if (processor_builder != m_unary_operator_builder_list.end()) {
+      return processor_builder->second.processorBuilder();
+    }
+    return {};
+  }
+
+  [[nodiscard]] std::optional<ASTNodeDataType>
+  getIncDecOperatorValueType(const std::string& name) const
+  {
+    auto&& processor_builder = m_inc_dec_operator_builder_list.find(name);
+    if (processor_builder != m_inc_dec_operator_builder_list.end()) {
+      return processor_builder->second.valueType();
+    }
+    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
+  {
+    auto&& processor_builder = m_unary_operator_builder_list.find(name);
+    if (processor_builder != m_unary_operator_builder_list.end()) {
+      return processor_builder->second.valueType();
+    }
+    return {};
+  }
+
+  static void create();
+
+  PUGS_INLINE
+  static OperatorRepository&
+  instance()
+  {
+    Assert(m_instance != nullptr);
+    return *m_instance;
+  }
+
+  static void destroy();
+
+ private:
+  static OperatorRepository* m_instance;
+
+  OperatorRepository() = default;
+
+  ~OperatorRepository() = default;
+};
+
+#endif   // OPERATOR_REPOSITORY_HPP
diff --git a/src/language/utils/PugsFunctionAdapter.hpp b/src/language/utils/PugsFunctionAdapter.hpp
index 17d97f509c2466b97d3a8ee46cc34ca8ee6b06fe..278c7274ff702cfc5e97f7b6075b5487e440580b 100644
--- a/src/language/utils/PugsFunctionAdapter.hpp
+++ b/src/language/utils/PugsFunctionAdapter.hpp
@@ -2,8 +2,8 @@
 #define PUGS_FUNCTION_ADAPTER_HPP
 
 #include <language/ast/ASTNode.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
 #include <language/node_processor/ExecutionPolicy.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/SymbolTable.hpp>
 #include <utils/Array.hpp>
diff --git a/src/language/utils/SymbolTable.hpp b/src/language/utils/SymbolTable.hpp
index 39d414b1e120255e9d51c17266512458fcc5f1b8..6aa089bd8de7aa5a3a6a6cf2a8115e77de25dbe8 100644
--- a/src/language/utils/SymbolTable.hpp
+++ b/src/language/utils/SymbolTable.hpp
@@ -1,7 +1,7 @@
 #ifndef SYMBOL_TABLE_HPP
 #define SYMBOL_TABLE_HPP
 
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/DataVariant.hpp>
 #include <language/utils/EmbedderTable.hpp>
 #include <language/utils/FunctionTable.hpp>
diff --git a/src/language/utils/UnaryOperatorMangler.hpp b/src/language/utils/UnaryOperatorMangler.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..380eb6fa0c5e260340eb2ab463f3a7567c6a301a
--- /dev/null
+++ b/src/language/utils/UnaryOperatorMangler.hpp
@@ -0,0 +1,32 @@
+#ifndef UNARY_OPERATOR_MANGLER_HPP
+#define UNARY_OPERATOR_MANGLER_HPP
+
+#include <language/utils/ASTNodeDataType.hpp>
+#include <utils/Exceptions.hpp>
+
+#include <string>
+
+namespace language
+{
+struct unary_minus;
+struct unary_not;
+}   // namespace language
+
+template <typename UnaryOperatorT>
+std::string
+unaryOperatorMangler(const ASTNodeDataType& operand)
+{
+  const std::string operator_name = [] {
+    if constexpr (std::is_same_v<language::unary_minus, UnaryOperatorT>) {
+      return "-";
+    } else if constexpr (std::is_same_v<language::unary_not, UnaryOperatorT>) {
+      return "not";
+    } else {
+      static_assert(std::is_same_v<language::unary_minus, UnaryOperatorT>, "undefined unary operator");
+    }
+  }();
+
+  return operator_name + " " + dataTypeName(operand);
+}
+
+#endif   // UNARY_OPERATOR_MANGLER_HPP
diff --git a/src/language/utils/UnaryOperatorProcessorBuilder.hpp b/src/language/utils/UnaryOperatorProcessorBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d99d2e17536de2b31a3ac2c48f39800a2461f17d
--- /dev/null
+++ b/src/language/utils/UnaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,31 @@
+#ifndef UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/UnaryExpressionProcessor.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename OperatorT, typename ValueT, typename DataT>
+class UnaryOperatorProcessorBuilder final : public IUnaryOperatorProcessorBuilder
+{
+ public:
+  UnaryOperatorProcessorBuilder() = default;
+
+  ASTNodeDataType
+  getReturnValueType() const
+  {
+    return ast_node_data_type_from<ValueT>;
+  }
+
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, DataT>>(node);
+  }
+};
+
+#endif   // UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForB.cpp b/src/language/utils/UnaryOperatorRegisterForB.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..33173e82b896e8d013f125a3b47ce42682ac132d
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForB.cpp
@@ -0,0 +1,32 @@
+#include <language/utils/UnaryOperatorRegisterForB.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForB::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, bool>>());
+}
+
+void
+UnaryOperatorRegisterForB::_register_unary_not()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+
+  repository.addUnaryOperator<
+    language::unary_not>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_not, bool, bool>>());
+}
+
+UnaryOperatorRegisterForB::UnaryOperatorRegisterForB()
+{
+  this->_register_unary_minus();
+  this->_register_unary_not();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForB.hpp b/src/language/utils/UnaryOperatorRegisterForB.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..49f1f8f4e8cf02dab86d1e0b8c7008d03a137546
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForB.hpp
@@ -0,0 +1,14 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_B_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_B_HPP
+
+class UnaryOperatorRegisterForB
+{
+ private:
+  void _register_unary_minus();
+  void _register_unary_not();
+
+ public:
+  UnaryOperatorRegisterForB();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_B_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForN.cpp b/src/language/utils/UnaryOperatorRegisterForN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..baed0e43eef169229cfbff58fb0592f894b83163
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForN.cpp
@@ -0,0 +1,21 @@
+#include <language/utils/UnaryOperatorRegisterForN.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForN::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(N,
+                           std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, uint64_t>>());
+}
+
+UnaryOperatorRegisterForN::UnaryOperatorRegisterForN()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForN.hpp b/src/language/utils/UnaryOperatorRegisterForN.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6a4ff62ed93e0db85b53f503de096f3dcc527ba
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForN.hpp
@@ -0,0 +1,13 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_N_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_N_HPP
+
+class UnaryOperatorRegisterForN
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForN();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_N_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForR.cpp b/src/language/utils/UnaryOperatorRegisterForR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c0c60a31f5f6c222232999c3b392a18f30a767c1
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR.cpp
@@ -0,0 +1,20 @@
+#include <language/utils/UnaryOperatorRegisterForR.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForR::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(R, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, double, double>>());
+}
+
+UnaryOperatorRegisterForR::UnaryOperatorRegisterForR()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForR.hpp b/src/language/utils/UnaryOperatorRegisterForR.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..308fe639039da194c2419f3902a1f98868482716
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR.hpp
@@ -0,0 +1,13 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_R_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_R_HPP
+
+class UnaryOperatorRegisterForR
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForR();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_R_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForRn.cpp b/src/language/utils/UnaryOperatorRegisterForRn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85cc03fa476a34a6bec65f2c7f88f1d76fbad809
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForRn.cpp
@@ -0,0 +1,28 @@
+#include <language/utils/UnaryOperatorRegisterForRn.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+template <size_t Dimension>
+void
+UnaryOperatorRegisterForRn<Dimension>::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension);
+
+  repository
+    .addUnaryOperator<language::unary_minus>(Rn,
+                                             std::make_shared<UnaryOperatorProcessorBuilder<
+                                               language::unary_minus, TinyVector<Dimension>, TinyVector<Dimension>>>());
+}
+
+template <size_t Dimension>
+UnaryOperatorRegisterForRn<Dimension>::UnaryOperatorRegisterForRn()
+{
+  this->_register_unary_minus();
+}
+
+template class UnaryOperatorRegisterForRn<1>;
+template class UnaryOperatorRegisterForRn<2>;
+template class UnaryOperatorRegisterForRn<3>;
diff --git a/src/language/utils/UnaryOperatorRegisterForRn.hpp b/src/language/utils/UnaryOperatorRegisterForRn.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0000f2f588bdc84ccc77e3c03515a92126aac14
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForRn.hpp
@@ -0,0 +1,16 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_RN_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_RN_HPP
+
+#include <cstdlib>
+
+template <size_t Dimension>
+class UnaryOperatorRegisterForRn
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForRn();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_RN_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForZ.cpp b/src/language/utils/UnaryOperatorRegisterForZ.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..89e0b4972a0a1e2a2556d2210ab4658b35f7b976
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForZ.cpp
@@ -0,0 +1,21 @@
+#include <language/utils/UnaryOperatorRegisterForZ.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForZ::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(Z,
+                           std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, int64_t>>());
+}
+
+UnaryOperatorRegisterForZ::UnaryOperatorRegisterForZ()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForZ.hpp b/src/language/utils/UnaryOperatorRegisterForZ.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0e3065b139a23e1898bc4954b3b76a1df3f7e44
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForZ.hpp
@@ -0,0 +1,13 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_Z_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_Z_HPP
+
+class UnaryOperatorRegisterForZ
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForZ();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_Z_HPP
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/CMakeLists.txt b/tests/CMakeLists.txt
index edaa8069ad867aeaa139f68f646519a6219097d0..5ae8aeef954932a6051be1f6f916d20dbad2b9f3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -125,7 +125,16 @@ target_link_libraries (unit_tests
 
 target_link_libraries (mpi_unit_tests
   test_Pugs_MeshDataBase
+  PugsAlgebra
+  PugsUtils
+  PugsLanguage
+  PugsLanguageAST
+  PugsLanguageModules
+  PugsLanguageAlgorithms
+  PugsMesh
+  PugsAlgebra
   PugsUtils
+  PugsLanguageUtils  PugsUtils
   PugsAlgebra
   PugsMesh
   kokkos
diff --git a/tests/mpi_test_main.cpp b/tests/mpi_test_main.cpp
index 87953af0c1d98a6b099b8d99606d8f4eaa686a40..44162aba3edce0e992b7f37e6df6cca1040b3291 100644
--- a/tests/mpi_test_main.cpp
+++ b/tests/mpi_test_main.cpp
@@ -4,6 +4,7 @@
 #include <Kokkos_Core.hpp>
 
 #include <algebra/PETScWrapper.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <mesh/DiamondDualConnectivityManager.hpp>
 #include <mesh/DiamondDualMeshManager.hpp>
 #include <mesh/MeshDataManager.hpp>
@@ -78,8 +79,12 @@ main(int argc, char* argv[])
         }
       }
 
+      OperatorRepository::create();
+
       result = session.run();
 
+      OperatorRepository::destroy();
+
       MeshDataBaseForTests::destroy();
 
       DiamondDualMeshManager::destroy();
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index 64d60d9bfbed21703850f2d945092a9d5ae49fe0..ecd72b1f04b52b47431e10d07b83d3dab441066e 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -10,33 +10,40 @@
 #include <language/ast/ASTSymbolTableBuilder.hpp>
 #include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/ASTPrinter.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/EmbeddedData.hpp>
 #include <language/utils/TypeDescriptor.hpp>
 #include <utils/Demangle.hpp>
 #include <utils/Exceptions.hpp>
 
 #include <pegtl/string_input.hpp>
 
-#define CHECK_AST(data, expected_output)                                                            \
-  {                                                                                                 \
-    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                  \
-    static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view> or      \
-                  std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>);            \
-                                                                                                    \
-    string_input input{data, "test.pgs"};                                                           \
-    auto ast = ASTBuilder::build(input);                                                            \
-                                                                                                    \
-    ASTSymbolTableBuilder{*ast};                                                                    \
-    ASTNodeDataTypeBuilder{*ast};                                                                   \
-                                                                                                    \
-    ASTNodeDeclarationToAffectationConverter{*ast};                                                 \
-    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                            \
-                                                                                                    \
-    ASTNodeExpressionBuilder{*ast};                                                                 \
-                                                                                                    \
-    std::stringstream ast_output;                                                                   \
-    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}}; \
-                                                                                                    \
-    REQUIRE(ast_output.str() == expected_output);                                                   \
+#define CHECK_AST(data, expected_output)                                                                        \
+  {                                                                                                             \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                              \
+    static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view> or                  \
+                  std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>);                        \
+                                                                                                                \
+    string_input input{data, "test.pgs"};                                                                       \
+                                                                                                                \
+    BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \
+                                                                                                                \
+    auto ast = ASTBuilder::build(input);                                                                        \
+                                                                                                                \
+    ASTSymbolTableBuilder{*ast};                                                                                \
+    ASTNodeDataTypeBuilder{*ast};                                                                               \
+                                                                                                                \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                             \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                        \
+                                                                                                                \
+    ASTNodeExpressionBuilder{*ast};                                                                             \
+                                                                                                                \
+    std::stringstream ast_output;                                                                               \
+    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}};             \
+                                                                                                                \
+    REQUIRE(ast_output.str() == expected_output);                                                               \
+                                                                                                                \
+    OperatorRepository::instance().reset();                                                                     \
   }
 
 template <>
@@ -44,51 +51,55 @@ inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
   ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t");
 const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>;
 
-#define CHECK_AST_WITH_BUILTIN(data, expected_output)                                                         \
-  {                                                                                                           \
-    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                            \
-    static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view> or                \
-                  std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>);                      \
-                                                                                                              \
-    string_input input{data, "test.pgs"};                                                                     \
-    auto ast = ASTBuilder::build(input);                                                                      \
-                                                                                                              \
-    SymbolTable& symbol_table = *ast->m_symbol_table;                                                         \
-    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin());             \
-    if (not success) {                                                                                        \
-      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");        \
-    }                                                                                                         \
-                                                                                                              \
-    i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>());            \
-    i_symbol->attributes().setIsInitialized();                                                                \
-    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();                                 \
-    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \
-                                                                                                              \
-    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                       \
-    if (not success_a) {                                                                                      \
-      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                  \
-    }                                                                                                         \
-    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
-    i_symbol_a->attributes().setIsInitialized();                                                              \
-    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                       \
-    if (not success_b) {                                                                                      \
-      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                  \
-    }                                                                                                         \
-    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
-    i_symbol_b->attributes().setIsInitialized();                                                              \
-                                                                                                              \
-    ASTSymbolTableBuilder{*ast};                                                                              \
-    ASTNodeDataTypeBuilder{*ast};                                                                             \
-                                                                                                              \
-    ASTNodeDeclarationToAffectationConverter{*ast};                                                           \
-    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                      \
-                                                                                                              \
-    ASTNodeExpressionBuilder{*ast};                                                                           \
-                                                                                                              \
-    std::stringstream ast_output;                                                                             \
-    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}};           \
-                                                                                                              \
-    REQUIRE(ast_output.str() == expected_output);                                                             \
+#define CHECK_AST_WITH_BUILTIN(data, expected_output)                                                           \
+  {                                                                                                             \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                              \
+    static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view> or                  \
+                  std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>);                        \
+                                                                                                                \
+    BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \
+                                                                                                                \
+    string_input input{data, "test.pgs"};                                                                       \
+    auto ast = ASTBuilder::build(input);                                                                        \
+                                                                                                                \
+    SymbolTable& symbol_table = *ast->m_symbol_table;                                                           \
+    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin());               \
+    if (not success) {                                                                                          \
+      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");          \
+    }                                                                                                           \
+                                                                                                                \
+    i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>());              \
+    i_symbol->attributes().setIsInitialized();                                                                  \
+    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();                                   \
+    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId()));   \
+                                                                                                                \
+    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                         \
+    if (not success_a) {                                                                                        \
+      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                    \
+    }                                                                                                           \
+    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);               \
+    i_symbol_a->attributes().setIsInitialized();                                                                \
+    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                         \
+    if (not success_b) {                                                                                        \
+      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                    \
+    }                                                                                                           \
+    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);               \
+    i_symbol_b->attributes().setIsInitialized();                                                                \
+                                                                                                                \
+    ASTSymbolTableBuilder{*ast};                                                                                \
+    ASTNodeDataTypeBuilder{*ast};                                                                               \
+                                                                                                                \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                             \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                        \
+                                                                                                                \
+    ASTNodeExpressionBuilder{*ast};                                                                             \
+                                                                                                                \
+    std::stringstream ast_output;                                                                               \
+    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}};             \
+                                                                                                                \
+    REQUIRE(ast_output.str() == expected_output);                                                               \
+                                                                                                                \
+    OperatorRepository::instance().reset();                                                                     \
   }
 
 #define CHECK_AST_THROWS_WITH(data, expected_error)                                           \
@@ -109,46 +120,50 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
     REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error);                      \
   }
 
-#define CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, expected_error)                                              \
-  {                                                                                                           \
-    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                            \
-    static_assert(std::is_same_v<std::decay_t<decltype(expected_error)>, std::string_view> or                 \
-                  std::is_same_v<std::decay_t<decltype(expected_error)>, std::string>);                       \
-                                                                                                              \
-    string_input input{data, "test.pgs"};                                                                     \
-    auto ast = ASTBuilder::build(input);                                                                      \
-                                                                                                              \
-    SymbolTable& symbol_table = *ast->m_symbol_table;                                                         \
-    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin());             \
-    if (not success) {                                                                                        \
-      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");        \
-    }                                                                                                         \
-                                                                                                              \
-    i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>());            \
-    i_symbol->attributes().setIsInitialized();                                                                \
-    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();                                 \
-    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \
-                                                                                                              \
-    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                       \
-    if (not success_a) {                                                                                      \
-      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                  \
-    }                                                                                                         \
-    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
-    i_symbol_a->attributes().setIsInitialized();                                                              \
-    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                       \
-    if (not success_b) {                                                                                      \
-      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                  \
-    }                                                                                                         \
-    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
-    i_symbol_b->attributes().setIsInitialized();                                                              \
-                                                                                                              \
-    ASTSymbolTableBuilder{*ast};                                                                              \
-    ASTNodeDataTypeBuilder{*ast};                                                                             \
-                                                                                                              \
-    ASTNodeDeclarationToAffectationConverter{*ast};                                                           \
-    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                      \
-                                                                                                              \
-    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error);                                      \
+#define CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, expected_error)                                                \
+  {                                                                                                             \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                              \
+    static_assert(std::is_same_v<std::decay_t<decltype(expected_error)>, std::string_view> or                   \
+                  std::is_same_v<std::decay_t<decltype(expected_error)>, std::string>);                         \
+                                                                                                                \
+    BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \
+                                                                                                                \
+    string_input input{data, "test.pgs"};                                                                       \
+    auto ast = ASTBuilder::build(input);                                                                        \
+                                                                                                                \
+    SymbolTable& symbol_table = *ast->m_symbol_table;                                                           \
+    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin());               \
+    if (not success) {                                                                                          \
+      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");          \
+    }                                                                                                           \
+                                                                                                                \
+    i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>());              \
+    i_symbol->attributes().setIsInitialized();                                                                  \
+    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();                                   \
+    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId()));   \
+                                                                                                                \
+    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                         \
+    if (not success_a) {                                                                                        \
+      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                    \
+    }                                                                                                           \
+    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);               \
+    i_symbol_a->attributes().setIsInitialized();                                                                \
+    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                         \
+    if (not success_b) {                                                                                        \
+      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                    \
+    }                                                                                                           \
+    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);               \
+    i_symbol_b->attributes().setIsInitialized();                                                                \
+                                                                                                                \
+    ASTSymbolTableBuilder{*ast};                                                                                \
+    ASTNodeDataTypeBuilder{*ast};                                                                               \
+                                                                                                                \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                             \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                        \
+                                                                                                                \
+    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error);                                        \
+                                                                                                                \
+    OperatorRepository::instance().reset();                                                                     \
   }
 
 // clazy:excludeall=non-pod-global-static
@@ -672,7 +687,7 @@ let t : (B), t = (true, false);
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, bool>)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<bool>)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::true_kw:ValueProcessor)
@@ -690,7 +705,7 @@ let t : (N), t = (1, 2, 3, 5);
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, unsigned long>)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<unsigned long>)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::integer:1:ValueProcessor)
@@ -714,7 +729,7 @@ let t : (Z), t = (2, n, true);
  +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
  |   +-(language::name:n:NameProcessor)
  |   `-(language::integer:3:ValueProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, long>)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<long>)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::integer:2:ValueProcessor)
@@ -733,7 +748,7 @@ let t : (R), t = (2, 3.1, 5);
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, double>)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<double>)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::integer:2:ValueProcessor)
@@ -760,7 +775,7 @@ let t3 : (R^1), t3 = (1, 2.3, 0);
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::integer:2:ValueProcessor)
  |       `-(language::real:3.1:ValueProcessor)
- +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<2ul, double> >)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<2ul, double> >)
  |   +-(language::name:t1:NameProcessor)
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::name:a:NameProcessor)
@@ -768,12 +783,12 @@ let t3 : (R^1), t3 = (1, 2.3, 0);
  |       |   +-(language::integer:1:ValueProcessor)
  |       |   `-(language::integer:2:ValueProcessor)
  |       `-(language::integer:0:ValueProcessor)
- +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<3ul, double> >)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<3ul, double> >)
  |   +-(language::name:t2:NameProcessor)
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::integer:0:ValueProcessor)
  |       `-(language::integer:0:ValueProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<1ul, double> >)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<1ul, double> >)
      +-(language::name:t3:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::integer:1:ValueProcessor)
@@ -792,7 +807,7 @@ let t : (string), t = ("foo", "bar");
 
         std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, )" +
+ `-(language::eq_op:AffectationToTupleFromListProcessor<)" +
                              demangled_stdstring + R"( >)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
@@ -811,7 +826,7 @@ let t : (builtin_t), t= (a,b,a);
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, EmbeddedData>)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<EmbeddedData>)
      +-(language::name:t:NameProcessor)
      `-(language::expression_list:ASTNodeExpressionListProcessor)
          +-(language::name:a:NameProcessor)
@@ -833,7 +848,7 @@ let t : (B), t = true;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, bool>)
+ `-(language::eq_op:AffectationToTupleProcessor<bool>)
      +-(language::name:t:NameProcessor)
      `-(language::true_kw:ValueProcessor)
 )";
@@ -849,7 +864,7 @@ let t : (N), t = 1;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, unsigned long>)
+ `-(language::eq_op:AffectationToTupleProcessor<unsigned long>)
      +-(language::name:t:NameProcessor)
      `-(language::integer:1:ValueProcessor)
 )";
@@ -869,7 +884,7 @@ let t : (Z), t = n;
  +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
  |   +-(language::name:n:NameProcessor)
  |   `-(language::integer:3:ValueProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, long>)
+ `-(language::eq_op:AffectationToTupleProcessor<long>)
      +-(language::name:t:NameProcessor)
      `-(language::name:n:NameProcessor)
 )";
@@ -885,7 +900,7 @@ let t : (R), t = 3.1;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, double>)
+ `-(language::eq_op:AffectationToTupleProcessor<double>)
      +-(language::name:t:NameProcessor)
      `-(language::real:3.1:ValueProcessor)
 )";
@@ -909,13 +924,13 @@ let t3 : (R^1), t3 = 2.3;
  |   `-(language::expression_list:ASTNodeExpressionListProcessor)
  |       +-(language::integer:2:ValueProcessor)
  |       `-(language::real:3.1:ValueProcessor)
- +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<2ul, double> >)
+ +-(language::eq_op:AffectationToTupleProcessor<TinyVector<2ul, double> >)
  |   +-(language::name:t1:NameProcessor)
  |   `-(language::name:a:NameProcessor)
- +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<3ul, double> >)
+ +-(language::eq_op:AffectationToTupleProcessor<TinyVector<3ul, double> >)
  |   +-(language::name:t2:NameProcessor)
  |   `-(language::integer:0:ValueProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<1ul, double> >)
+ `-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >)
      +-(language::name:t3:NameProcessor)
      `-(language::real:2.3:ValueProcessor)
 )";
@@ -931,7 +946,7 @@ let t : (string), t = "foo";
 
         std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, )" +
+ `-(language::eq_op:AffectationToTupleProcessor<)" +
                              demangled_stdstring + R"( >)
      +-(language::name:t:NameProcessor)
      `-(language::literal:"foo":ValueProcessor)
@@ -948,7 +963,7 @@ let t : (builtin_t), t = a;
 
         std::string_view result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, EmbeddedData>)
+ `-(language::eq_op:AffectationToTupleProcessor<EmbeddedData>)
      +-(language::name:t:NameProcessor)
      `-(language::name:a:NameProcessor)
 )";
@@ -1511,33 +1526,20 @@ let x : R, x=1; x/=2.3;
   {
     SECTION("Invalid affectation operator")
     {
-      auto ast = std::make_unique<ASTNode>();
+      auto ast         = std::make_unique<ASTNode>();
+      ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+      {
+        auto child_0         = std::make_unique<ASTNode>();
+        child_0->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+        auto child_1         = std::make_unique<ASTNode>();
+        child_1->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+        ast->children.emplace_back(std::move(child_0));
+        ast->children.emplace_back(std::move(child_1));
+      }
       REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast},
                           "unexpected error: undefined affectation operator");
     }
 
-    SECTION("Invalid lhs")
-    {
-      auto ast = std::make_unique<ASTNode>();
-      ast->set_type<language::eq_op>();
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-      REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast},
-                          "unexpected error: undefined value type for affectation");
-    }
-
-    SECTION("Invalid rhs")
-    {
-      auto ast = std::make_unique<ASTNode>();
-      ast->set_type<language::eq_op>();
-
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-      REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast},
-                          "unexpected error: invalid implicit conversion: undefined -> Z");
-    }
-
     SECTION("Invalid string rhs")
     {
       auto ast = std::make_unique<ASTNode>();
@@ -1558,7 +1560,7 @@ let x : R, x=1; x/=2.3;
 let s : string, s="foo"; s-="bar";
 )";
 
-        std::string error_message = "invalid affectation operator for string";
+        std::string error_message = "undefined affectation type: string -= string";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1569,7 +1571,7 @@ let s : string, s="foo"; s-="bar";
 let s : string, s="foo"; s*=2;
 )";
 
-        std::string error_message = "invalid affectation operator for string";
+        std::string error_message = "undefined affectation type: string *= Z";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1580,7 +1582,7 @@ let s : string, s="foo"; s*=2;
  let s : string, s="foo"; s/="bar";
 )";
 
-        std::string error_message = "invalid affectation operator for string";
+        std::string error_message = "undefined affectation type: string /= string";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1592,7 +1594,7 @@ let s : string, s="foo"; s*=2;
  let s :builtin_t, s = a; s *= b;
 )";
 
-      std::string error_message = "invalid affectation operator for 'builtin_t'";
+      std::string error_message = "undefined affectation type: builtin_t *= builtin_t";
 
       CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message);
     }
@@ -1603,7 +1605,7 @@ let s : string, s="foo"; s*=2;
  let s :(R), s=(1,2,3); s *= 4;
 )";
 
-      std::string error_message = "invalid affectation operator for 'tuple(R)'";
+      std::string error_message = "undefined affectation type: tuple(R) *= Z";
 
       CHECK_AST_THROWS_WITH(data, error_message);
     }
@@ -1614,7 +1616,7 @@ let s : string, s="foo"; s*=2;
  let s : (builtin_t), s =(a,b); s *= b;
 )";
 
-      std::string error_message = "invalid affectation operator for 'tuple(builtin_t)'";
+      std::string error_message = "undefined affectation type: tuple(builtin_t) *= builtin_t";
 
       CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message);
     }
@@ -1721,7 +1723,7 @@ let x : R^2, x = 2;
 let x : R^3; let y : R^3; x /= y;
 )";
 
-        std::string error_message = "invalid affectation operator for R^3";
+        std::string error_message = "undefined affectation type: R^3 /= R^3";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1732,7 +1734,7 @@ let x : R^3; let y : R^3; x /= y;
 let x : R^2; let y : R^2; x /= y;
 )";
 
-        std::string error_message = "invalid affectation operator for R^2";
+        std::string error_message = "undefined affectation type: R^2 /= R^2";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1743,7 +1745,7 @@ let x : R^2; let y : R^2; x /= y;
 let x : R^1; let y : R^1; x /= y;
 )";
 
-        std::string error_message = "invalid affectation operator for R^1";
+        std::string error_message = "undefined affectation type: R^1 /= R^1";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1757,7 +1759,7 @@ let x : R^1; let y : R^1; x /= y;
 let x : R^3; let y : R^3; x *= y;
 )";
 
-        std::string error_message = "expecting scalar operand type";
+        std::string error_message = "undefined affectation type: R^3 *= R^3";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1768,7 +1770,7 @@ let x : R^3; let y : R^3; x *= y;
 let x : R^2; let y : R^2; x *= y;
 )";
 
-        std::string error_message = "expecting scalar operand type";
+        std::string error_message = "undefined affectation type: R^2 *= R^2";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1779,7 +1781,7 @@ let x : R^2; let y : R^2; x *= y;
 let x : R^1; let y : R^1; x *= y;
 )";
 
-        std::string error_message = "expecting scalar operand type";
+        std::string error_message = "undefined affectation type: R^1 *= R^1";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
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_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp
index 3d4ea9b6954363cdd9007679e425d5f4f4c74c36..2e6e9afb4715b86c67fa2511e7472418e912f8e8 100644
--- a/tests/test_ASTNodeDataType.cpp
+++ b/tests/test_ASTNodeDataType.cpp
@@ -2,7 +2,7 @@
 
 #include <language/PEGGrammar.hpp>
 #include <language/ast/ASTNode.hpp>
-#include <language/ast/ASTNodeDataType.hpp>
+#include <language/utils/ASTNodeDataType.hpp>
 
 namespace language
 {
diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp
index dd206297d82c52bbbf7dda7e304d6b3966524d4f..6c37b1afe9a7c411e2c1643ac1bd1e3cb1a72aeb 100644
--- a/tests/test_ASTNodeDataTypeBuilder.cpp
+++ b/tests/test_ASTNodeDataTypeBuilder.cpp
@@ -894,7 +894,7 @@ x = f(x);
  |   `-(language::expression_list:list(Z*Z))
  |       +-(language::integer:1:Z)
  |       `-(language::integer:2:Z)
- `-(language::eq_op:R^2)
+ `-(language::eq_op:void)
      +-(language::name:x:R^2)
      `-(language::function_evaluation:R^2)
          +-(language::name:f:function)
@@ -1285,7 +1285,7 @@ a = 1;
  +-(language::var_declaration:void)
  |   +-(language::name:a:N)
  |   `-(language::N_set:typename(N))
- `-(language::eq_op:N)
+ `-(language::eq_op:void)
      +-(language::name:a:N)
      `-(language::integer:1:Z)
 )";
@@ -1307,7 +1307,7 @@ a *= 1.2;
  |   +-(language::N_set:typename(N))
  |   +-(language::name:a:N)
  |   `-(language::integer:1:Z)
- `-(language::multiplyeq_op:N)
+ `-(language::multiplyeq_op:void)
      +-(language::name:a:N)
      `-(language::real:1.2:R)
 )";
@@ -1329,7 +1329,7 @@ a /= 2;
  |   +-(language::R_set:typename(R))
  |   +-(language::name:a:R)
  |   `-(language::integer:3:Z)
- `-(language::divideeq_op:R)
+ `-(language::divideeq_op:void)
      +-(language::name:a:R)
      `-(language::integer:2:Z)
 )";
@@ -1351,7 +1351,7 @@ a += 2;
  |   +-(language::Z_set:typename(Z))
  |   +-(language::name:a:Z)
  |   `-(language::integer:3:Z)
- `-(language::pluseq_op:Z)
+ `-(language::pluseq_op:void)
      +-(language::name:a:Z)
      `-(language::integer:2:Z)
 )";
@@ -1373,7 +1373,7 @@ a -= 2;
  |   +-(language::Z_set:typename(Z))
  |   +-(language::name:a:Z)
  |   `-(language::integer:1:Z)
- `-(language::minuseq_op:Z)
+ `-(language::minuseq_op:void)
      +-(language::name:a:Z)
      `-(language::integer:2:Z)
 )";
@@ -1416,10 +1416,10 @@ for (let i:Z, i=0; i<3; i += 1) { i += 2; }
      +-(language::lesser_op:B)
      |   +-(language::name:i:Z)
      |   `-(language::integer:3:Z)
-     +-(language::pluseq_op:Z)
+     +-(language::pluseq_op:void)
      |   +-(language::name:i:Z)
      |   `-(language::integer:1:Z)
-     `-(language::pluseq_op:Z)
+     `-(language::pluseq_op:void)
          +-(language::name:i:Z)
          `-(language::integer:2:Z)
 )";
diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp
index 956b5a2527e8e80bb1cef2287f9b2c72a16768aa..3b09a0bb554e6692fe1f741229e9ea43725782af 100644
--- a/tests/test_ASTNodeExpressionBuilder.cpp
+++ b/tests/test_ASTNodeExpressionBuilder.cpp
@@ -373,7 +373,10 @@ let n:N;
 
     SECTION("unary not")
     {
-      CHECK_AST_THROWS_WITH(R"(not 1;)", "invalid implicit conversion: Z -> B");
+      std::string error_message = R"(undefined unary operator
+note: unexpected operand type Z)";
+
+      CHECK_AST_THROWS_WITH(R"(not 1;)", error_message);
     }
 
     SECTION("pre-increment operator")
@@ -486,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)
 )";
@@ -502,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)
 )";
@@ -518,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)
 )";
@@ -534,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)
 )";
@@ -544,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")
@@ -565,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)
 )";
@@ -581,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)
 )";
@@ -597,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)
 )";
@@ -613,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)
 )";
@@ -629,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)
 )";
@@ -645,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)
 )";
@@ -763,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>)
@@ -788,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>)
@@ -832,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_ASTNodeIncDecExpressionBuilder.cpp b/tests/test_ASTNodeIncDecExpressionBuilder.cpp
index 627d6f96606a13a97907d01d314339f846049892..2b64fcd03c2aeedb6ab3902cf374791205344815 100644
--- a/tests/test_ASTNodeIncDecExpressionBuilder.cpp
+++ b/tests/test_ASTNodeIncDecExpressionBuilder.cpp
@@ -8,6 +8,7 @@
 #include <language/ast/ASTNodeTypeCleaner.hpp>
 #include <language/ast/ASTSymbolTableBuilder.hpp>
 #include <language/utils/ASTPrinter.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <utils/Demangle.hpp>
 
 #include <pegtl/string_input.hpp>
@@ -299,11 +300,11 @@ x--;
 
   SECTION("Errors")
   {
-    SECTION("Invalid operator type")
+    SECTION("Undefined operator")
     {
-      auto ast = std::make_unique<ASTNode>();
-      REQUIRE_THROWS_WITH(ASTNodeIncDecExpressionBuilder{*ast},
-                          "unexpected error: undefined increment/decrement operator");
+      auto& operator_repository = OperatorRepository::instance();
+      auto optional_value_type  = operator_repository.getIncDecOperatorValueType("string ++");
+      REQUIRE(not optional_value_type.has_value());
     }
 
     SECTION("Invalid operand type")
@@ -314,7 +315,8 @@ x--;
 
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
-      REQUIRE_THROWS_WITH(ASTNodeIncDecExpressionBuilder{*ast}, "invalid operand type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeIncDecExpressionBuilder{*ast},
+                          "invalid operand type. ++/-- operators only apply to variables");
     }
 
     SECTION("Invalid data type")
@@ -325,8 +327,7 @@ x--;
       ast->children.emplace_back(std::make_unique<ASTNode>());
       ast->children[0]->set_type<language::name>();
 
-      REQUIRE_THROWS_WITH(ASTNodeIncDecExpressionBuilder{*ast},
-                          "unexpected error: undefined data type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeIncDecExpressionBuilder{*ast}, "undefined affectation type: ++ undefined");
     }
 
     SECTION("Not allowed chained ++/--")
@@ -337,7 +338,7 @@ x--;
 1 ++ ++;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -348,7 +349,7 @@ x--;
 1 ++ --;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -359,7 +360,7 @@ x--;
 1 -- ++;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -370,7 +371,7 @@ x--;
 1 -- --;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -381,7 +382,7 @@ x--;
 ++ ++ 1;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -392,7 +393,7 @@ x--;
 ++ -- 1;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -403,7 +404,7 @@ x--;
 -- ++ 1;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -414,7 +415,7 @@ x--;
 -- -- 1;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -425,7 +426,7 @@ x--;
 ++ 1 ++;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -436,7 +437,7 @@ x--;
 ++ 1 --;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -447,7 +448,7 @@ x--;
 -- 1 ++;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
@@ -458,7 +459,7 @@ x--;
 -- 1 --;
 )";
 
-        std::string error_message = R"(chaining ++ or -- operators is not allowed)";
+        std::string error_message = R"(invalid operand type. ++/-- operators only apply to variables)";
 
         DISALLOWED_CHAINED_AST(data, error_message)
       }
diff --git a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
index cc31b56706d9bdf952bcfdb5b4ab6e209e2be1df..2ebe22cab68dc735836054b58ca4382340e09030 100644
--- a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -191,35 +191,27 @@ not b;
 
   SECTION("Errors")
   {
-    SECTION("Invalid unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "unexpected error: undefined unary operator");
-    }
-
-    SECTION("Invalid unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "unexpected error: undefined unary operator");
-    }
-
     SECTION("Invalid value type for unary minus")
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::unary_minus>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined value type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined unary operator type: - undefined");
     }
 
     SECTION("errors")
     {
-      CHECK_AST_THROWS_WITH(R"(let n:N; not n;)", "invalid implicit conversion: N -> B");
-      CHECK_AST_THROWS_WITH(R"(not 2;)", "invalid implicit conversion: Z -> B");
-      CHECK_AST_THROWS_WITH(R"(not -2.3;)", "invalid implicit conversion: R -> B");
-      CHECK_AST_THROWS_WITH(R"(not "foo";)", "invalid implicit conversion: string -> B");
+      auto error_message = [](std::string type_name) {
+        return std::string{R"(undefined unary operator
+note: unexpected operand type )"} +
+               type_name;
+      };
+
+      CHECK_AST_THROWS_WITH(R"(let n:N; not n;)", error_message("N"));
+      CHECK_AST_THROWS_WITH(R"(not 2;)", error_message("Z"));
+      CHECK_AST_THROWS_WITH(R"(not -2.3;)", error_message("R"));
+      CHECK_AST_THROWS_WITH(R"(not "foo";)", error_message("string"));
     }
 
     SECTION("Invalid value type for unary not")
@@ -228,18 +220,7 @@ not b;
       ast->set_type<language::unary_not>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined value type for unary operator");
-    }
-
-    SECTION("Invalid data type for unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-      ast->set_type<language::unary_minus>();
-      ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast},
-                          "unexpected error: invalid operand type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined unary operator type: not undefined");
     }
   }
 }
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_ConcatExpressionProcessor.cpp b/tests/test_ConcatExpressionProcessor.cpp
index adc5f49e0360b2e1ea3e784ea83fae60cd157d69..57b68c4e7206c9eebd59942cddf2829f2fe236ab 100644
--- a/tests/test_ConcatExpressionProcessor.cpp
+++ b/tests/test_ConcatExpressionProcessor.cpp
@@ -71,4 +71,28 @@ TEST_CASE("ConcatExpressionProcessor", "[language]")
   {
     CHECK_CONCAT_EXPRESSION_RESULT(R"(let s:string, s = "foo_"; s = s+true;)", "s", std::string{"foo_1"});
   }
+
+  SECTION("string + R^1")
+  {
+    std::ostringstream os;
+    os << "foo_" << TinyVector<1>{1};
+
+    CHECK_CONCAT_EXPRESSION_RESULT(R"(let x:R^1, x = 1; let s:string, s = "foo_"; s = s+x;)", "s", os.str());
+  }
+
+  SECTION("string + R^2")
+  {
+    std::ostringstream os;
+    os << "foo_" << TinyVector<2>{1, 2};
+
+    CHECK_CONCAT_EXPRESSION_RESULT(R"(let x:R^2, x = (1,2); let s:string, s = "foo_"; s = s+x;)", "s", os.str());
+  }
+
+  SECTION("string + R^3")
+  {
+    std::ostringstream os;
+    os << "foo_" << TinyVector<3>{1, 2, 3};
+
+    CHECK_CONCAT_EXPRESSION_RESULT(R"(let x:R^3, x = (1,2,3); let s:string, s = "foo_"; s = s+x;)", "s", os.str());
+  }
 }
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 e933902adaefd968cc3036c8bbf007b29d054f39..b309d6dd13c0791a909ab30e164325ac7d365e00 100644
--- a/tests/test_UnaryExpressionProcessor.cpp
+++ b/tests/test_UnaryExpressionProcessor.cpp
@@ -68,12 +68,29 @@ TEST_CASE("UnaryExpressionProcessor", "[language]")
 
     SECTION("errors")
     {
-      SECTION("bad implicit conversions")
+      SECTION("undefined not operator")
       {
-        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(let n:N, n = 0; not n;)", "invalid implicit conversion: N -> B");
-        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1;)", "invalid implicit conversion: Z -> B");
-        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1.3;)", "invalid implicit conversion: R -> B");
-        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not "foo";)", "invalid implicit conversion: string -> B");
+        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"(let n:N, n = 0; not n;)", error_message("N"));
+        CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1;)", error_message("Z"));
+        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"));
       }
     }
   }
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 74f695682992ad951c3b2c33e3c8c0f6b53b657a..b2703a5950eeabe8eea33ba61cab4fc2e2f9157a 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -4,6 +4,7 @@
 #include <Kokkos_Core.hpp>
 
 #include <algebra/PETScWrapper.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <mesh/DiamondDualConnectivityManager.hpp>
 #include <mesh/DiamondDualMeshManager.hpp>
 #include <mesh/MeshDataManager.hpp>
@@ -38,8 +39,12 @@ main(int argc, char* argv[])
 
       MeshDataBaseForTests::create();
 
+      OperatorRepository::create();
+
       result = session.run();
 
+      OperatorRepository::destroy();
+
       MeshDataBaseForTests::destroy();
 
       DiamondDualMeshManager::destroy();