C++ Mathematical Expression Library (ExprTk)  https://www.partow.net/programming/exprtk/index.html
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..8e95be7
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,34 @@
+version: 2.1
+jobs:
+
+  build_gcc_6:
+    docker:
+      - image: gcc:6
+    steps:
+      - checkout
+      - run: make all -j 2
+      - run: ./exprtk_test
+
+  build_gcc_7:
+    docker:
+      - image: gcc:7
+    steps:
+      - checkout
+      - run: make all -j 2
+      - run: ./exprtk_test
+
+  build_gcc_latest:
+    docker:
+      - image: gcc:latest
+    steps:
+      - checkout
+      - run: make all -j 2
+      - run: ./exprtk_test
+
+workflows:
+  version: 2
+  build_and_test:
+    jobs:
+      - build_gcc_6
+      - build_gcc_7
+      - build_gcc_latest
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 5ce5a53..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: cpp
-
-sudo: required
-
-dist: trusty
-
-compiler:
-  - gcc
-
-script:
-  - make clean all
-  - ./exprtk_test
diff --git a/Makefile b/Makefile
index bc602a3..76d43a0 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 # **************************************************************
 # *         C++ Mathematical Expression Toolkit Library        *
 # *                                                            *
-# * Author: Arash Partow (1999-2018)                           *
+# * Author: Arash Partow (1999-2020)                           *
 # * URL: http://www.partow.net/programming/exprtk/index.html   *
 # *                                                            *
 # * Copyright notice:                                          *
@@ -15,37 +15,18 @@
 #
 
 
-COMPILER         = -c++
-#COMPILER        = -clang
-OPTIMIZATION_OPT = -O1
-BASE_OPTIONS     = -pedantic-errors -Wall -Wextra -Werror -Wno-long-long
-OPTIONS          = $(BASE_OPTIONS) $(OPTIMIZATION_OPT)
-LINKER_OPT       = -L/usr/lib -lstdc++ -lm
-ASAN_OPT         = -g -fsanitize=address -fno-omit-frame-pointer
-MSAN_OPT         = -g -fsanitize=memory  -fno-omit-frame-pointer
-LSAN_OPT         = -g -fsanitize=leak    -fno-omit-frame-pointer
-
-BUILD_LIST+=exprtk_test
-BUILD_LIST+=exprtk_benchmark
-BUILD_LIST+=exprtk_simple_example_01
-BUILD_LIST+=exprtk_simple_example_02
-BUILD_LIST+=exprtk_simple_example_03
-BUILD_LIST+=exprtk_simple_example_04
-BUILD_LIST+=exprtk_simple_example_05
-BUILD_LIST+=exprtk_simple_example_06
-BUILD_LIST+=exprtk_simple_example_07
-BUILD_LIST+=exprtk_simple_example_08
-BUILD_LIST+=exprtk_simple_example_09
-BUILD_LIST+=exprtk_simple_example_10
-BUILD_LIST+=exprtk_simple_example_11
-BUILD_LIST+=exprtk_simple_example_12
-BUILD_LIST+=exprtk_simple_example_13
-BUILD_LIST+=exprtk_simple_example_14
-BUILD_LIST+=exprtk_simple_example_15
-BUILD_LIST+=exprtk_simple_example_16
-BUILD_LIST+=exprtk_simple_example_17
-BUILD_LIST+=exprtk_simple_example_18
-BUILD_LIST+=exprtk_simple_example_19
+COMPILER         := -c++
+#COMPILER        := -clang++
+OPTIMIZATION_OPT := -O1
+BASE_OPTIONS     := -pedantic-errors -Wall -Wextra -Werror -Wno-long-long
+OPTIONS          := $(BASE_OPTIONS) $(OPTIMIZATION_OPT)
+LINKER_OPT       := -L/usr/lib -lstdc++ -lm
+ASAN_OPT         := -g -fsanitize=address   -fno-omit-frame-pointer
+MSAN_OPT         := -g -fsanitize=memory    -fno-omit-frame-pointer
+LSAN_OPT         := -g -fsanitize=leak      -fno-omit-frame-pointer
+USAN_OPT         := -g -fsanitize=undefined -fno-omit-frame-pointer
+BUILD_SRC        := $(sort $(wildcard exprtk_*.cpp))
+BUILD_LIST       := $(BUILD_SRC:%.cpp=%)
 
 
 all: $(BUILD_LIST)
diff --git a/exprtk.hpp b/exprtk.hpp
index 2e62bf5..0b2081e 100644
--- a/exprtk.hpp
+++ b/exprtk.hpp
@@ -2,7 +2,7 @@
  ******************************************************************
  *           C++ Mathematical Expression Toolkit Library          *
  *                                                                *
- * Author: Arash Partow (1999-2018)                               *
+ * Author: Arash Partow (1999-2020)                               *
  * URL: http://www.partow.net/programming/exprtk/index.html       *
  *                                                                *
  * Copyright notice:                                              *
@@ -35,6 +35,7 @@
 
 
 #include <algorithm>
+#include <cassert>
 #include <cctype>
 #include <cmath>
 #include <complex>
@@ -67,7 +68,7 @@
    #define exprtk_error_location             \
    "exprtk.hpp:" + details::to_str(__LINE__) \
 
-   #if __GNUC__  >= 7
+   #if defined(__GNUC__) && (__GNUC__  >= 7)
 
       #define exprtk_disable_fallthrough_begin                      \
       _Pragma ("GCC diagnostic push")                               \
@@ -83,8 +84,14 @@
 
    namespace details
    {
-      typedef unsigned char uchar_t;
-      typedef char           char_t;
+      typedef unsigned char            uchar_t;
+      typedef char                      char_t;
+      typedef uchar_t*               uchar_ptr;
+      typedef char_t*                 char_ptr;
+      typedef uchar_t const*        uchar_cptr;
+      typedef char_t const*          char_cptr;
+      typedef unsigned long long int _uint64_t;
+      typedef long long int           _int64_t;
 
       inline bool is_whitespace(const char_t c)
       {
@@ -158,6 +165,12 @@
                 ('\'' != c);
       }
 
+      inline bool is_valid_string_char(const char_t c)
+      {
+         return std::isprint(static_cast<unsigned char>(c)) ||
+                is_whitespace(c);
+      }
+
       #ifndef exprtk_disable_caseinsensitivity
       inline void case_normalise(std::string& s)
       {
@@ -304,31 +317,30 @@
       }
 
       template <typename Iterator>
-      inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
+      inline bool parse_hex(Iterator& itr, Iterator end,
+                            std::string::value_type& result)
       {
          if (
-              (end !=  (itr    )) &&
-              (end !=  (itr + 1)) &&
-              (end !=  (itr + 2)) &&
-              (end !=  (itr + 3)) &&
-              ('0' == *(itr    )) &&
-              (
-                ('x' == *(itr + 1)) ||
-                ('X' == *(itr + 1))
-              ) &&
-              (is_hex_digit(*(itr + 2))) &&
-              (is_hex_digit(*(itr + 3)))
+              (end ==  (itr    ))               ||
+              (end ==  (itr + 1))               ||
+              (end ==  (itr + 2))               ||
+              (end ==  (itr + 3))               ||
+              ('0' != *(itr    ))               ||
+              ('X' != std::toupper(*(itr + 1))) ||
+              (!is_hex_digit(*(itr + 2)))       ||
+              (!is_hex_digit(*(itr + 3)))
             )
          {
-            result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
-                     hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
-            itr += 3;
+            return false;
          }
-         else
-            result = '\0';
+
+         result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
+                  hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
+
+         return true;
       }
 
-      inline void cleanup_escapes(std::string& s)
+      inline bool cleanup_escapes(std::string& s)
       {
          typedef std::string::iterator str_itr_t;
 
@@ -342,36 +354,41 @@
          {
             if ('\\' == (*itr1))
             {
-               ++removal_count;
-
                if (end == ++itr1)
-                  break;
-               else if ('\\' != (*itr1))
                {
-                  switch (*itr1)
-                  {
-                     case 'n' : (*itr1) = '\n'; break;
-                     case 'r' : (*itr1) = '\r'; break;
-                     case 't' : (*itr1) = '\t'; break;
-                     case '0' : parse_hex(itr1, end, (*itr1));
-                                removal_count += 3;
-                                break;
-                  }
-
-                  continue;
+                  return false;
                }
+               else if (parse_hex(itr1, end, *itr2))
+               {
+                  itr1+= 4;
+                  itr2+= 1;
+                  removal_count +=4;
+               }
+               else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
+               else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
+               else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; }
+               else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; }
+               else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; }
+               else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; }
+               else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; }
+               else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; }
+               else
+               {
+                  (*itr2++) = (*itr1++);
+                  ++removal_count;
+               }
+               continue;
             }
-
-            if (itr1 != itr2)
-            {
-               (*itr2) = (*itr1);
-            }
-
-            ++itr1;
-            ++itr2;
+            else
+               (*itr2++) = (*itr1++);
          }
 
+         if ((removal_count > s.size()) || (0 == removal_count))
+            return false;
+
          s.resize(s.size() - removal_count);
+
+         return true;
       }
 
       class build_string
@@ -389,7 +406,7 @@
             return (*this);
          }
 
-         inline build_string& operator << (const char_t* s)
+         inline build_string& operator << (char_cptr s)
          {
             data_ += std::string(s);
             return (*this);
@@ -576,83 +593,82 @@
 
       template <typename Iterator, typename Compare>
       inline bool match_impl(const Iterator pattern_begin,
-                             const Iterator pattern_end,
-                             const Iterator data_begin,
-                             const Iterator data_end,
+                             const Iterator pattern_end  ,
+                             const Iterator data_begin   ,
+                             const Iterator data_end     ,
                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
-                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
+                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
       {
-         if (0 == std::distance(data_begin,data_end))
-         {
-            return false;
-         }
+         const Iterator null_itr(0);
 
-         Iterator d_itr = data_begin;
-         Iterator p_itr = pattern_begin;
-         Iterator c_itr = data_begin;
-         Iterator m_itr = data_begin;
+         Iterator d_itr    = data_begin;
+         Iterator p_itr    = pattern_begin;
+         Iterator tb_p_itr = null_itr;
+         Iterator tb_d_itr = null_itr;
 
-         while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
+         while (d_itr != data_end)
          {
-            if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
+            if (zero_or_more == *p_itr)
             {
-               return false;
+               while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
+               {
+                  ++p_itr;
+               }
+
+               if (pattern_end == p_itr)
+                  return true;
+
+               const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
+
+               while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
+               {
+                  ++d_itr;
+               }
+
+               tb_p_itr = p_itr;
+               tb_d_itr = d_itr;
+
+               continue;
+            }
+            else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
+            {
+               if (null_itr == tb_d_itr)
+                  return false;
+
+               d_itr = tb_d_itr++;
+               p_itr = tb_p_itr;
+
+               continue;
             }
 
             ++p_itr;
             ++d_itr;
          }
 
-         while (data_end != d_itr)
+         while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
          {
-            if (zero_or_more == (*p_itr))
-            {
-               if (pattern_end == (++p_itr))
-               {
-                  return true;
-               }
-
-               m_itr = p_itr;
-               c_itr = d_itr;
-               ++c_itr;
-            }
-            else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
-            {
-               ++p_itr;
-               ++d_itr;
-            }
-            else
-            {
-               p_itr = m_itr;
-               d_itr = c_itr++;
-            }
+            ++p_itr;
          }
 
-         while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }
-
-         return (p_itr == pattern_end);
+         return (pattern_end == p_itr);
       }
 
       inline bool wc_match(const std::string& wild_card,
                            const std::string& str)
       {
-         return match_impl<const char_t*,cs_match>(wild_card.data(),
-                                                   wild_card.data() + wild_card.size(),
-                                                   str.data(),
-                                                   str.data() + str.size(),
-                                                   '*',
-                                                   '?');
+         return match_impl<char_cptr,cs_match>(
+                   wild_card.data(), wild_card.data() + wild_card.size(),
+                   str.data(), str.data() + str.size(),
+                   '*', '?');
       }
 
       inline bool wc_imatch(const std::string& wild_card,
                             const std::string& str)
       {
-         return match_impl<const char_t*,cis_match>(wild_card.data(),
-                                                    wild_card.data() + wild_card.size(),
-                                                    str.data(),
-                                                    str.data() + str.size(),
-                                                    '*',
-                                                    '?');
+         return match_impl<char_cptr,cis_match>(
+                   wild_card.data(), wild_card.data() + wild_card.size(),
+                   str.data(), str.data() + str.size(),
+                   '*', '?');
       }
 
       inline bool sequence_match(const std::string& pattern,
@@ -733,7 +749,7 @@
                                       1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
                                     };
 
-     static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
+      static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
 
       namespace numeric
       {
@@ -785,12 +801,12 @@
             exprtk_register_complex_type_tag(long double)
             exprtk_register_complex_type_tag(float      )
 
-            exprtk_register_int_type_tag(short                 )
-            exprtk_register_int_type_tag(int                   )
-            exprtk_register_int_type_tag(long long int         )
-            exprtk_register_int_type_tag(unsigned short        )
-            exprtk_register_int_type_tag(unsigned int          )
-            exprtk_register_int_type_tag(unsigned long long int)
+            exprtk_register_int_type_tag(short         )
+            exprtk_register_int_type_tag(int           )
+            exprtk_register_int_type_tag(_int64_t      )
+            exprtk_register_int_type_tag(unsigned short)
+            exprtk_register_int_type_tag(unsigned int  )
+            exprtk_register_int_type_tag(_uint64_t     )
 
             #undef exprtk_register_real_type_tag
             #undef exprtk_register_int_type_tag
@@ -838,9 +854,9 @@
             }
 
             template <typename T>
-            inline long long int to_int64_impl(const T v, real_type_tag)
+            inline _int64_t to_int64_impl(const T v, real_type_tag)
             {
-               return static_cast<long long int>(v);
+               return static_cast<_int64_t>(v);
             }
 
             template <typename T>
@@ -1316,8 +1332,8 @@
             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
 
-            template <typename T> inline T const_pi_impl(real_type_tag) { return numeric::constant::pi; }
-            template <typename T> inline T const_e_impl (real_type_tag) { return numeric::constant::e;  }
+            template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
+            template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e);  }
 
             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
@@ -1378,7 +1394,7 @@
          }
 
          template <typename T>
-         inline long long int to_int64(const T v)
+         inline _int64_t to_int64(const T v)
          {
             const typename details::number_type<T>::type num_type;
             return to_int64_impl(v, num_type);
@@ -1798,7 +1814,7 @@
          if ((3 != length) && (inf_length != length))
             return false;
 
-         const char_t* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
+         char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
 
          while (end != itr)
          {
@@ -1820,6 +1836,13 @@
          return true;
       }
 
+      template <typename T>
+      inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
+      {
+         return (std::numeric_limits<T>::min_exponent10 <= exponent) &&
+                (exponent <= std::numeric_limits<T>::max_exponent10) ;
+      }
+
       template <typename Iterator, typename T>
       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
       {
@@ -1839,7 +1862,7 @@
 
          bool instate = false;
 
-         static const char zero = static_cast<uchar_t>('0');
+         static const char_t zero = static_cast<uchar_t>('0');
 
          #define parse_digit_1(d)          \
          if ((digit = (*itr - zero)) < 10) \
@@ -1860,12 +1883,12 @@
 
             while ((end != itr) && (zero == (*itr))) ++itr;
 
-            unsigned int digit;
-
             while (end != itr)
             {
                // Note: For 'physical' superscalar architectures it
                // is advised that the following loop be: 4xPD1 and 1xPD2
+               unsigned int digit;
+
                #ifdef exprtk_enable_superscalar
                parse_digit_1(d)
                parse_digit_1(d)
@@ -1885,11 +1908,12 @@
             if ('.' == (*itr))
             {
                const Iterator curr = ++itr;
-               unsigned int digit;
                T tmp_d = T(0);
 
                while (end != itr)
                {
+                  unsigned int digit;
+
                   #ifdef exprtk_enable_superscalar
                   parse_digit_1(tmp_d)
                   parse_digit_1(tmp_d)
@@ -1903,7 +1927,13 @@
                if (curr != itr)
                {
                   instate = true;
-                  d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
+
+                  const int exponent = static_cast<int>(-std::distance(curr, itr));
+
+                  if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
+                     return false;
+
+                  d += compute_pow10(tmp_d, exponent);
                }
 
                #undef parse_digit_1
@@ -1974,6 +2004,8 @@
 
          if ((end != itr) || (!instate))
             return false;
+         else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
+            return false;
          else if (exponent)
             d = compute_pow10(d,exponent);
 
@@ -1986,8 +2018,8 @@
       {
          const typename numeric::details::number_type<T>::type num_type;
 
-         const char_t* begin = s.data();
-         const char_t* end   = s.data() + s.size();
+         char_cptr begin = s.data();
+         char_cptr end   = s.data() + s.size();
 
          return string_to_real(begin, end, t, num_type);
       }
@@ -2012,6 +2044,50 @@
 
    } // namespace details
 
+   struct loop_runtime_check
+   {
+      enum loop_types
+      {
+         e_invalid           = 0,
+         e_for_loop          = 1,
+         e_while_loop        = 2,
+         e_repeat_until_loop = 4,
+         e_all_loops         = 7
+      };
+
+      enum violation_type
+      {
+          e_unknown         = 0,
+          e_iteration_count = 1,
+          e_timeout         = 2
+      };
+
+      loop_types loop_set;
+
+      loop_runtime_check()
+      : loop_set(e_invalid),
+        max_loop_iterations(0)
+      {}
+
+      details::_uint64_t max_loop_iterations;
+
+      struct violation_context
+      {
+         loop_types loop;
+         violation_type violation;
+         details::_uint64_t iteration_count;
+      };
+
+      virtual void handle_runtime_violation(const violation_context&)
+      {
+         throw std::runtime_error("ExprTk Loop run-time violation.");
+      }
+
+      virtual ~loop_runtime_check() {}
+   };
+
+   typedef loop_runtime_check* loop_runtime_check_ptr;
+
    namespace lexer
    {
       struct token
@@ -2192,7 +2268,7 @@
 
          typedef token token_t;
          typedef std::vector<token_t> token_list_t;
-         typedef std::vector<token_t>::iterator token_list_itr_t;
+         typedef token_list_t::iterator token_list_itr_t;
          typedef details::char_t char_t;
 
          generator()
@@ -2316,8 +2392,8 @@
 
          inline std::string substr(const std::size_t& begin, const std::size_t& end)
          {
-            const char_t* begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
-            const char_t* end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
+            const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
+            const details::char_cptr end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
 
             return std::string(begin_itr,end_itr);
          }
@@ -2327,19 +2403,19 @@
             if (finished())
                return "";
             else if (token_list_.begin() != token_itr_)
-               return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_);
+               return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
             else
-               return std::string(base_itr_ + token_itr_->position,s_end_);
+               return std::string(base_itr_ + token_itr_->position, s_end_);
          }
 
       private:
 
-         inline bool is_end(const char_t* itr)
+         inline bool is_end(details::char_cptr itr)
          {
             return (s_end_ == itr);
          }
 
-         inline bool is_comment_start(const char_t* itr)
+         inline bool is_comment_start(details::char_cptr itr)
          {
             #ifndef exprtk_disable_comments
             const char_t c0 = *(itr + 0);
@@ -2408,7 +2484,7 @@
             else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
                return;
 
-            const char_t* cmt_start = s_itr_;
+            details::char_cptr cmt_start = s_itr_;
 
             s_itr_ += increment;
 
@@ -2564,7 +2640,7 @@
 
          inline void scan_symbol()
          {
-            const char_t* initial_itr = s_itr_;
+            details::char_cptr initial_itr = s_itr_;
 
             while (!is_end(s_itr_))
             {
@@ -2615,11 +2691,11 @@
                (15) .1234e-3
             */
 
-            const char_t* initial_itr = s_itr_;
-            bool dot_found            = false;
-            bool e_found              = false;
-            bool post_e_sign_found    = false;
-            bool post_e_digit_found   = false;
+            details::char_cptr initial_itr = s_itr_;
+            bool dot_found                 = false;
+            bool e_found                   = false;
+            bool post_e_sign_found         = false;
+            bool post_e_digit_found        = false;
             token_t t;
 
             while (!is_end(s_itr_))
@@ -2630,6 +2706,7 @@
                   {
                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
                      token_list_.push_back(t);
+
                      return;
                   }
 
@@ -2702,7 +2779,7 @@
 
          inline void scan_special_function()
          {
-            const char_t* initial_itr = s_itr_;
+            details::char_cptr initial_itr = s_itr_;
             token_t t;
 
             // $fdd(x,x,x) = at least 11 chars
@@ -2738,13 +2815,14 @@
          #ifndef exprtk_disable_string_capabilities
          inline void scan_string()
          {
-            const char_t* initial_itr = s_itr_ + 1;
+            details::char_cptr initial_itr = s_itr_ + 1;
             token_t t;
 
             if (std::distance(s_itr_,s_end_) < 2)
             {
                t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
                token_list_.push_back(t);
+
                return;
             }
 
@@ -2755,7 +2833,14 @@
 
             while (!is_end(s_itr_))
             {
-               if (!escaped && ('\\' == *s_itr_))
+               if (!details::is_valid_string_char(*s_itr_))
+               {
+                  t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
+                  token_list_.push_back(t);
+
+                  return;
+               }
+               else if (!escaped && ('\\' == *s_itr_))
                {
                   escaped_found = true;
                   escaped = true;
@@ -2770,28 +2855,17 @@
                }
                else if (escaped)
                {
-                  if (!is_end(s_itr_) && ('0' == *(s_itr_)))
+                  if (
+                       !is_end(s_itr_) && ('0' == *(s_itr_)) &&
+                       ((s_itr_ + 4) <= s_end_)
+                     )
                   {
-                     /*
-                        Note: The following 'awkward' conditional is
-                              due to various broken msvc compilers.
-                     */
-                     #if _MSC_VER == 1600
-                     const bool within_range = !is_end(s_itr_ + 2) &&
-                                               !is_end(s_itr_ + 3) ;
-                     #else
-                     const bool within_range = !is_end(s_itr_ + 1) &&
-                                               !is_end(s_itr_ + 2) &&
-                                               !is_end(s_itr_ + 3) ;
-                     #endif
+                     const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1)));
 
-                     const bool x_seperator  = ('x' == *(s_itr_ + 1)) ||
-                                               ('X' == *(s_itr_ + 1)) ;
+                     const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
+                                              details::is_hex_digit(*(s_itr_ + 3)) ;
 
-                     const bool both_digits  = details::is_hex_digit(*(s_itr_ + 2)) &&
-                                               details::is_hex_digit(*(s_itr_ + 3)) ;
-
-                     if (!within_range || !x_seperator || !both_digits)
+                     if (!(x_seperator && both_digits))
                      {
                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
                         token_list_.push_back(t);
@@ -2822,7 +2896,13 @@
             {
                std::string parsed_string(initial_itr,s_itr_);
 
-               details::cleanup_escapes(parsed_string);
+               if (!details::cleanup_escapes(parsed_string))
+               {
+                  t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
+                  token_list_.push_back(t);
+
+                  return;
+               }
 
                t.set_string(
                     parsed_string,
@@ -2838,13 +2918,13 @@
 
       private:
 
-         token_list_t     token_list_;
-         token_list_itr_t token_itr_;
-         token_list_itr_t store_token_itr_;
-         token_t eof_token_;
-         const char_t* base_itr_;
-         const char_t* s_itr_;
-         const char_t* s_end_;
+         token_list_t       token_list_;
+         token_list_itr_t   token_itr_;
+         token_list_itr_t   store_token_itr_;
+         token_t            eof_token_;
+         details::char_cptr base_itr_;
+         details::char_cptr s_itr_;
+         details::char_cptr s_end_;
 
          friend class token_scanner;
          friend class token_modifier;
@@ -3011,6 +3091,10 @@
 
             std::size_t changes = 0;
 
+            typedef std::pair<std::size_t, token> insert_t;
+            std::vector<insert_t> insert_list;
+            insert_list.reserve(10000);
+
             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
             {
                int insert_index = -1;
@@ -3034,17 +3118,36 @@
                            break;
                }
 
-               typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
-
                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
                {
-                  g.token_list_.insert(
-                     g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
-
+                  insert_list.push_back(insert_t(i, t));
                   changes++;
                }
             }
 
+            if (!insert_list.empty())
+            {
+               generator::token_list_t token_list;
+
+               std::size_t insert_index = 0;
+
+               for (std::size_t i = 0; i < g.token_list_.size(); ++i)
+               {
+                  token_list.push_back(g.token_list_[i]);
+
+                  if (
+                       (insert_index < insert_list.size()) &&
+                       (insert_list[insert_index].first == i)
+                     )
+                  {
+                     token_list.push_back(insert_list[insert_index].second);
+                     insert_index++;
+                  }
+               }
+
+               std::swap(g.token_list_,token_list);
+            }
+
             return changes;
          }
 
@@ -3079,7 +3182,7 @@
       {
       public:
 
-         token_joiner(const std::size_t& stride)
+         explicit token_joiner(const std::size_t& stride)
          : stride_(stride)
          {}
 
@@ -3103,53 +3206,82 @@
 
          inline std::size_t process_stride_2(generator& g)
          {
-            typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
-
             if (g.token_list_.size() < 2)
                return 0;
 
             std::size_t changes = 0;
 
-            for (std::size_t i = 0; i < (g.token_list_.size() - 1); ++i)
+            generator::token_list_t token_list;
+            token_list.reserve(10000);
+
+            for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 1); ++i)
             {
                token t;
 
-               while (join(g[i], g[i + 1], t))
+               for ( ; ; )
                {
-                  g.token_list_[i] = t;
+                  if (!join(g[i], g[i + 1], t))
+                  {
+                     token_list.push_back(g[i]);
+                     break;
+                  }
 
-                  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
+                  token_list.push_back(t);
 
                   ++changes;
+
+                  i+=2;
+
+                  if (static_cast<std::size_t>(i) >= g.token_list_.size())
+                     break;
                }
             }
 
+            token_list.push_back(g.token_list_.back());
+
+            std::swap(token_list, g.token_list_);
+
             return changes;
          }
 
          inline std::size_t process_stride_3(generator& g)
          {
-            typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
-
             if (g.token_list_.size() < 3)
                return 0;
 
             std::size_t changes = 0;
 
-            for (std::size_t i = 0; i < (g.token_list_.size() - 2); ++i)
+            generator::token_list_t token_list;
+            token_list.reserve(10000);
+
+            for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 2); ++i)
             {
                token t;
 
-               while (join(g[i], g[i + 1], g[i + 2], t))
+               for ( ; ; )
                {
-                  g.token_list_[i] = t;
+                  if (!join(g[i], g[i + 1], g[i + 2], t))
+                  {
+                     token_list.push_back(g[i]);
+                     break;
+                  }
 
-                  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
-                                      g.token_list_.begin() + static_cast<diff_t>(i + 3));
+                  token_list.push_back(t);
+
                   ++changes;
+
+                  i+=3;
+
+                  if (static_cast<std::size_t>(i) >= g.token_list_.size())
+                     break;
                }
             }
 
+            token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
+            token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
+
+            std::swap(token_list, g.token_list_);
+
             return changes;
          }
 
@@ -3159,11 +3291,11 @@
       namespace helper
       {
 
-         inline void dump(lexer::generator& generator)
+         inline void dump(const lexer::generator& generator)
          {
             for (std::size_t i = 0; i < generator.size(); ++i)
             {
-               lexer::token t = generator[i];
+               const lexer::token& t = generator[i];
                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
                       static_cast<int>(i),
                       static_cast<int>(t.position),
@@ -3224,6 +3356,7 @@
                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
+               else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_symbol     )) match = true;
 
                return (match) ? 1 : -1;
             }
@@ -3237,7 +3370,7 @@
          {
          public:
 
-            operator_joiner(const std::size_t& stride)
+            explicit operator_joiner(const std::size_t& stride)
             : token_joiner(stride)
             {}
 
@@ -3635,10 +3768,11 @@
             sequence_validator()
             : lexer::token_scanner(2)
             {
-               add_invalid(lexer::token::e_number ,lexer::token::e_number );
-               add_invalid(lexer::token::e_string ,lexer::token::e_string );
-               add_invalid(lexer::token::e_number ,lexer::token::e_string );
-               add_invalid(lexer::token::e_string ,lexer::token::e_number );
+               add_invalid(lexer::token::e_number, lexer::token::e_number);
+               add_invalid(lexer::token::e_string, lexer::token::e_string);
+               add_invalid(lexer::token::e_number, lexer::token::e_string);
+               add_invalid(lexer::token::e_string, lexer::token::e_number);
+
                add_invalid_set1(lexer::token::e_assign );
                add_invalid_set1(lexer::token::e_shr    );
                add_invalid_set1(lexer::token::e_shl    );
@@ -3666,7 +3800,7 @@
 
             bool operator() (const lexer::token& t0, const lexer::token& t1)
             {
-               set_t::value_type p = std::make_pair(t0.type,t1.type);
+               const set_t::value_type p = std::make_pair(t0.type,t1.type);
 
                if (invalid_bracket_check(t0.type,t1.type))
                {
@@ -3680,7 +3814,7 @@
                return true;
             }
 
-            std::size_t error_count()
+            std::size_t error_count() const
             {
                return error_list_.size();
             }
@@ -3712,21 +3846,21 @@
 
             void add_invalid_set1(lexer::token::token_type t)
             {
-               add_invalid(t,lexer::token::e_assign);
-               add_invalid(t,lexer::token::e_shr   );
-               add_invalid(t,lexer::token::e_shl   );
-               add_invalid(t,lexer::token::e_lte   );
-               add_invalid(t,lexer::token::e_ne    );
-               add_invalid(t,lexer::token::e_gte   );
-               add_invalid(t,lexer::token::e_lt    );
-               add_invalid(t,lexer::token::e_gt    );
-               add_invalid(t,lexer::token::e_eq    );
-               add_invalid(t,lexer::token::e_comma );
-               add_invalid(t,lexer::token::e_div   );
-               add_invalid(t,lexer::token::e_mul   );
-               add_invalid(t,lexer::token::e_mod   );
-               add_invalid(t,lexer::token::e_pow   );
-               add_invalid(t,lexer::token::e_colon );
+               add_invalid(t, lexer::token::e_assign);
+               add_invalid(t, lexer::token::e_shr   );
+               add_invalid(t, lexer::token::e_shl   );
+               add_invalid(t, lexer::token::e_lte   );
+               add_invalid(t, lexer::token::e_ne    );
+               add_invalid(t, lexer::token::e_gte   );
+               add_invalid(t, lexer::token::e_lt    );
+               add_invalid(t, lexer::token::e_gt    );
+               add_invalid(t, lexer::token::e_eq    );
+               add_invalid(t, lexer::token::e_comma );
+               add_invalid(t, lexer::token::e_div   );
+               add_invalid(t, lexer::token::e_mul   );
+               add_invalid(t, lexer::token::e_mod   );
+               add_invalid(t, lexer::token::e_pow   );
+               add_invalid(t, lexer::token::e_colon );
             }
 
             bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
@@ -3736,7 +3870,7 @@
                   switch (t)
                   {
                      case lexer::token::e_assign : return (']' != base);
-                     case lexer::token::e_string : return true;
+                     case lexer::token::e_string : return (')' != base);
                      default                     : return false;
                   }
                }
@@ -3757,7 +3891,7 @@
                         case lexer::token::e_sub     : return false;
                         case lexer::token::e_colon   : return false;
                         case lexer::token::e_ternary : return false;
-                        default                      : return true;
+                        default                      : return true ;
                      }
                   }
                }
@@ -3771,7 +3905,7 @@
                      case lexer::token::e_eof     : return false;
                      case lexer::token::e_colon   : return false;
                      case lexer::token::e_ternary : return false;
-                     default                      : return true;
+                     default                      : return true ;
                   }
                }
                else if (details::is_left_bracket(static_cast<char>(t)))
@@ -3792,6 +3926,91 @@
             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
          };
 
+         class sequence_validator_3tokens : public lexer::token_scanner
+         {
+         private:
+
+            typedef lexer::token::token_type token_t;
+            typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
+            typedef std::set<token_triplet_t> set_t;
+
+         public:
+
+            using lexer::token_scanner::operator();
+
+            sequence_validator_3tokens()
+            : lexer::token_scanner(3)
+            {
+               add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
+               add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
+               add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
+
+               add_invalid(lexer::token::e_add   , lexer::token::e_add   , lexer::token::e_add   );
+               add_invalid(lexer::token::e_sub   , lexer::token::e_sub   , lexer::token::e_sub   );
+               add_invalid(lexer::token::e_div   , lexer::token::e_div   , lexer::token::e_div   );
+               add_invalid(lexer::token::e_mul   , lexer::token::e_mul   , lexer::token::e_mul   );
+               add_invalid(lexer::token::e_mod   , lexer::token::e_mod   , lexer::token::e_mod   );
+               add_invalid(lexer::token::e_pow   , lexer::token::e_pow   , lexer::token::e_pow   );
+
+               add_invalid(lexer::token::e_add   , lexer::token::e_sub   , lexer::token::e_add   );
+               add_invalid(lexer::token::e_sub   , lexer::token::e_add   , lexer::token::e_sub   );
+               add_invalid(lexer::token::e_div   , lexer::token::e_mul   , lexer::token::e_div   );
+               add_invalid(lexer::token::e_mul   , lexer::token::e_div   , lexer::token::e_mul   );
+               add_invalid(lexer::token::e_mod   , lexer::token::e_pow   , lexer::token::e_mod   );
+               add_invalid(lexer::token::e_pow   , lexer::token::e_mod   , lexer::token::e_pow   );
+            }
+
+            bool result()
+            {
+               return error_list_.empty();
+            }
+
+            bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
+            {
+               const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
+
+               if (invalid_comb_.find(p) != invalid_comb_.end())
+               {
+                  error_list_.push_back(std::make_pair(t0,t1));
+               }
+
+               return true;
+            }
+
+            std::size_t error_count() const
+            {
+               return error_list_.size();
+            }
+
+            std::pair<lexer::token,lexer::token> error(const std::size_t index)
+            {
+               if (index < error_list_.size())
+               {
+                  return error_list_[index];
+               }
+               else
+               {
+                  static const lexer::token error_token;
+                  return std::make_pair(error_token,error_token);
+               }
+            }
+
+            void clear_errors()
+            {
+               error_list_.clear();
+            }
+
+         private:
+
+            void add_invalid(token_t t0, token_t t1, token_t t2)
+            {
+               invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
+            }
+
+            set_t invalid_comb_;
+            std::vector<std::pair<lexer::token,lexer::token> > error_list_;
+         };
+
          struct helper_assembly
          {
             inline bool register_scanner(lexer::token_scanner* scanner)
@@ -4046,40 +4265,6 @@
             return true;
          }
 
-         inline bool token_is_then_assign(const token_t::token_type& ttype,
-                                          std::string& token,
-                                          const token_advance_mode mode = e_advance)
-         {
-            if (current_token_.type != ttype)
-            {
-               return false;
-            }
-
-            token = current_token_.value;
-
-            advance_token(mode);
-
-            return true;
-         }
-
-         template <typename Allocator,
-                   template <typename,typename> class Container>
-         inline bool token_is_then_assign(const token_t::token_type& ttype,
-                                          Container<std::string,Allocator>& token_list,
-                                          const token_advance_mode mode = e_advance)
-         {
-            if (current_token_.type != ttype)
-            {
-               return false;
-            }
-
-            token_list.push_back(current_token_.value);
-
-            advance_token(mode);
-
-            return true;
-         }
-
          inline bool peek_token_is(const token_t::token_type& ttype)
          {
             return (lexer_.peek_next_token().type == ttype);
@@ -4166,14 +4351,14 @@
    inline vector_view<T> make_vector_view(T* data,
                                           const std::size_t size, const std::size_t offset = 0)
    {
-      return vector_view<T>(data + offset,size);
+      return vector_view<T>(data + offset, size);
    }
 
    template <typename T>
    inline vector_view<T> make_vector_view(std::vector<T>& v,
                                           const std::size_t size, const std::size_t offset = 0)
    {
-      return vector_view<T>(v.data() + offset,size);
+      return vector_view<T>(v.data() + offset, size);
    }
 
    template <typename T> class results_context;
@@ -4190,13 +4375,18 @@
       };
 
       type_store()
-      : size(0),
-        data(0),
+      : data(0),
+        size(0),
         type(e_unknown)
       {}
 
+      union
+      {
+          void*  data;
+          T*     vec_data;
+      };
+
       std::size_t size;
-      void*       data;
       store_type  type;
 
       class parameter_list
@@ -4502,27 +4692,33 @@
       {
          switch (opr)
          {
-            case e_add    : return  "+";
-            case e_sub    : return  "-";
-            case e_mul    : return  "*";
-            case e_div    : return  "/";
-            case e_mod    : return  "%";
-            case e_pow    : return  "^";
-            case e_assign : return ":=";
-            case e_addass : return "+=";
-            case e_subass : return "-=";
-            case e_mulass : return "*=";
-            case e_divass : return "/=";
-            case e_modass : return "%=";
-            case e_lt     : return  "<";
-            case e_lte    : return "<=";
-            case e_eq     : return "==";
-            case e_equal  : return  "=";
-            case e_ne     : return "!=";
-            case e_nequal : return "<>";
-            case e_gte    : return ">=";
-            case e_gt     : return  ">";
-            default       : return"N/A";
+            case e_add    : return  "+"  ;
+            case e_sub    : return  "-"  ;
+            case e_mul    : return  "*"  ;
+            case e_div    : return  "/"  ;
+            case e_mod    : return  "%"  ;
+            case e_pow    : return  "^"  ;
+            case e_assign : return ":="  ;
+            case e_addass : return "+="  ;
+            case e_subass : return "-="  ;
+            case e_mulass : return "*="  ;
+            case e_divass : return "/="  ;
+            case e_modass : return "%="  ;
+            case e_lt     : return  "<"  ;
+            case e_lte    : return "<="  ;
+            case e_eq     : return "=="  ;
+            case e_equal  : return  "="  ;
+            case e_ne     : return "!="  ;
+            case e_nequal : return "<>"  ;
+            case e_gte    : return ">="  ;
+            case e_gt     : return  ">"  ;
+            case e_and    : return "and" ;
+            case e_or     : return "or"  ;
+            case e_xor    : return "xor" ;
+            case e_nand   : return "nand";
+            case e_nor    : return "nor" ;
+            case e_xnor   : return "xnor";
+            default       : return "N/A" ;
          }
       }
 
@@ -4547,8 +4743,8 @@
 
          struct details
          {
-            details(const std::size_t& vsize,
-                    const unsigned int loop_batch_size = global_loop_batch_size)
+            explicit details(const std::size_t& vsize,
+                             const unsigned int loop_batch_size = global_loop_batch_size)
             : batch_size(loop_batch_size   ),
               remainder (vsize % batch_size),
               upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
@@ -4596,16 +4792,16 @@
             {}
 
             control_block(const std::size_t& dsize)
-            : ref_count(1),
+            : ref_count(1    ),
               size     (dsize),
-              data     (0),
-              destruct (true)
+              data     (0    ),
+              destruct (true )
             { create_data(); }
 
             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
-            : ref_count(1),
-              size     (dsize),
-              data     (dptr ),
+            : ref_count(1     ),
+              size     (dsize ),
+              data     (dptr  ),
               destruct (dstrct)
             {}
 
@@ -4662,7 +4858,7 @@
             {
                destruct = true;
                data     = new T[size];
-               std::fill_n(data,size,T(0));
+               std::fill_n(data, size, T(0));
                dump_ptr("control_block::create_data() - data",data,size);
             }
          };
@@ -4759,7 +4955,7 @@
 
          static inline void match_sizes(type& vds0, type& vds1)
          {
-            std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
+            const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
             vds0.control_block_->size = size;
             vds1.control_block_->size = size;
          }
@@ -4768,8 +4964,8 @@
 
          static inline std::size_t min_size(control_block* cb0, control_block* cb1)
          {
-            std::size_t size0 = cb0->size;
-            std::size_t size1 = cb1->size;
+            const std::size_t size0 = cb0->size;
+            const std::size_t size1 = cb1->size;
 
             if (size0 && size1)
                return std::min(size0,size1);
@@ -4856,19 +5052,19 @@
                   case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
-                  case e_and    : return and_opr<T> (arg0,arg1);
+                  case e_and    : return and_opr <T>(arg0,arg1);
                   case e_nand   : return nand_opr<T>(arg0,arg1);
-                  case e_or     : return or_opr<T>  (arg0,arg1);
-                  case e_nor    : return nor_opr<T> (arg0,arg1);
-                  case e_xor    : return xor_opr<T> (arg0,arg1);
+                  case e_or     : return or_opr  <T>(arg0,arg1);
+                  case e_nor    : return nor_opr <T>(arg0,arg1);
+                  case e_xor    : return xor_opr <T>(arg0,arg1);
                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
-                  case e_root   : return root<T>    (arg0,arg1);
-                  case e_roundn : return roundn<T>  (arg0,arg1);
+                  case e_root   : return root    <T>(arg0,arg1);
+                  case e_roundn : return roundn  <T>(arg0,arg1);
                   case e_equal  : return equal      (arg0,arg1);
                   case e_nequal : return nequal     (arg0,arg1);
-                  case e_hypot  : return hypot<T>   (arg0,arg1);
-                  case e_shr    : return shr<T>     (arg0,arg1);
-                  case e_shl    : return shl<T>     (arg0,arg1);
+                  case e_hypot  : return hypot   <T>(arg0,arg1);
+                  case e_shr    : return shr     <T>(arg0,arg1);
+                  case e_shl    : return shl     <T>(arg0,arg1);
 
                   default       : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
                                   return std::numeric_limits<T>::quiet_NaN();
@@ -4923,58 +5119,77 @@
          template <typename T>
          inline T process(const operator_type operation, const T arg0, const T arg1)
          {
-            return exprtk::details::numeric::details::process_impl(operation,arg0,arg1);
+            return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
          }
       }
 
+      template <typename Node>
+      struct node_collector_interface
+      {
+         typedef Node* node_ptr_t;
+         typedef Node** node_pp_t;
+         typedef std::vector<node_pp_t> noderef_list_t;
+
+         virtual ~node_collector_interface() {}
+
+         virtual void collect_nodes(noderef_list_t&) {}
+      };
+
+      template <typename Node>
+      struct node_depth_base;
+
       template <typename T>
-      class expression_node
+      class expression_node : public node_collector_interface<expression_node<T> >,
+                              public node_depth_base<expression_node<T> >
       {
       public:
 
          enum node_type
          {
-            e_none         , e_null         , e_constant     , e_unary        ,
-            e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,
-            e_vararg       , e_conditional  , e_while        , e_repeat       ,
-            e_for          , e_switch       , e_mswitch      , e_return       ,
-            e_retenv       , e_variable     , e_stringvar    , e_stringconst  ,
-            e_stringvarrng , e_cstringvarrng, e_strgenrange  , e_strconcat    ,
-            e_stringvarsize, e_strswap      , e_stringsize   , e_stringvararg ,
-            e_function     , e_vafunction   , e_genfunction  , e_strfunction  ,
-            e_strcondition , e_strccondition, e_add          , e_sub          ,
-            e_mul          , e_div          , e_mod          , e_pow          ,
-            e_lt           , e_lte          , e_gt           , e_gte          ,
-            e_eq           , e_ne           , e_and          , e_nand         ,
-            e_or           , e_nor          , e_xor          , e_xnor         ,
-            e_in           , e_like         , e_ilike        , e_inranges     ,
-            e_ipow         , e_ipowinv      , e_abs          , e_acos         ,
-            e_acosh        , e_asin         , e_asinh        , e_atan         ,
-            e_atanh        , e_ceil         , e_cos          , e_cosh         ,
-            e_exp          , e_expm1        , e_floor        , e_log          ,
-            e_log10        , e_log2         , e_log1p        , e_neg          ,
-            e_pos          , e_round        , e_sin          , e_sinc         ,
-            e_sinh         , e_sqrt         , e_tan          , e_tanh         ,
-            e_cot          , e_sec          , e_csc          , e_r2d          ,
-            e_d2r          , e_d2g          , e_g2d          , e_notl         ,
-            e_sgn          , e_erf          , e_erfc         , e_ncdf         ,
-            e_frac         , e_trunc        , e_uvouv        , e_vov          ,
-            e_cov          , e_voc          , e_vob          , e_bov          ,
-            e_cob          , e_boc          , e_vovov        , e_vovoc        ,
-            e_vocov        , e_covov        , e_covoc        , e_vovovov      ,
-            e_vovovoc      , e_vovocov      , e_vocovov      , e_covovov      ,
-            e_covocov      , e_vocovoc      , e_covovoc      , e_vococov      ,
-            e_sf3ext       , e_sf4ext       , e_nulleq       , e_strass       ,
-            e_vector       , e_vecelem      , e_rbvecelem    , e_rbveccelem   ,
-            e_vecdefass    , e_vecvalass    , e_vecvecass    , e_vecopvalass  ,
-            e_vecopvecass  , e_vecfunc      , e_vecvecswap   , e_vecvecineq   ,
-            e_vecvalineq   , e_valvecineq   , e_vecvecarith  , e_vecvalarith  ,
-            e_valvecarith  , e_vecunaryop   , e_break        , e_continue     ,
+            e_none          , e_null          , e_constant    , e_unary        ,
+            e_binary        , e_binary_ext    , e_trinary     , e_quaternary   ,
+            e_vararg        , e_conditional   , e_while       , e_repeat       ,
+            e_for           , e_switch        , e_mswitch     , e_return       ,
+            e_retenv        , e_variable      , e_stringvar   , e_stringconst  ,
+            e_stringvarrng  , e_cstringvarrng , e_strgenrange , e_strconcat    ,
+            e_stringvarsize , e_strswap       , e_stringsize  , e_stringvararg ,
+            e_function      , e_vafunction    , e_genfunction , e_strfunction  ,
+            e_strcondition  , e_strccondition , e_add         , e_sub          ,
+            e_mul           , e_div           , e_mod         , e_pow          ,
+            e_lt            , e_lte           , e_gt          , e_gte          ,
+            e_eq            , e_ne            , e_and         , e_nand         ,
+            e_or            , e_nor           , e_xor         , e_xnor         ,
+            e_in            , e_like          , e_ilike       , e_inranges     ,
+            e_ipow          , e_ipowinv       , e_abs         , e_acos         ,
+            e_acosh         , e_asin          , e_asinh       , e_atan         ,
+            e_atanh         , e_ceil          , e_cos         , e_cosh         ,
+            e_exp           , e_expm1         , e_floor       , e_log          ,
+            e_log10         , e_log2          , e_log1p       , e_neg          ,
+            e_pos           , e_round         , e_sin         , e_sinc         ,
+            e_sinh          , e_sqrt          , e_tan         , e_tanh         ,
+            e_cot           , e_sec           , e_csc         , e_r2d          ,
+            e_d2r           , e_d2g           , e_g2d         , e_notl         ,
+            e_sgn           , e_erf           , e_erfc        , e_ncdf         ,
+            e_frac          , e_trunc         , e_uvouv       , e_vov          ,
+            e_cov           , e_voc           , e_vob         , e_bov          ,
+            e_cob           , e_boc           , e_vovov       , e_vovoc        ,
+            e_vocov         , e_covov         , e_covoc       , e_vovovov      ,
+            e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
+            e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
+            e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
+            e_vector        , e_vecelem       , e_rbvecelem   , e_rbveccelem   ,
+            e_vecdefass     , e_vecvalass     , e_vecvecass   , e_vecopvalass  ,
+            e_vecopvecass   , e_vecfunc       , e_vecvecswap  , e_vecvecineq   ,
+            e_vecvalineq    , e_valvecineq    , e_vecvecarith , e_vecvalarith  ,
+            e_valvecarith   , e_vecunaryop    , e_break       , e_continue     ,
             e_swap
          };
 
          typedef T value_type;
          typedef expression_node<T>* expression_ptr;
+         typedef node_collector_interface<expression_node<T> > nci_t;
+         typedef typename nci_t::noderef_list_t noderef_list_t;
+         typedef node_depth_base<expression_node<T> > ndb_t;
 
          virtual ~expression_node()
          {}
@@ -5026,12 +5241,24 @@
       }
 
       template <typename T>
+      inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
+      {
+         return std::not_equal_to<T>()(T(0),node.first->value());
+      }
+
+      template <typename T>
       inline bool is_false(const expression_node<T>* node)
       {
          return std::equal_to<T>()(T(0),node->value());
       }
 
       template <typename T>
+      inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
+      {
+         return std::equal_to<T>()(T(0),node.first->value());
+      }
+
+      template <typename T>
       inline bool is_unary_node(const expression_node<T>* node)
       {
          return node && (details::expression_node<T>::e_unary == node->type());
@@ -5173,7 +5400,8 @@
       template <typename T>
       inline bool branch_deletable(expression_node<T>* node)
       {
-         return !is_variable_node(node) &&
+         return (0 != node)             &&
+                !is_variable_node(node) &&
                 !is_string_node  (node) ;
       }
 
@@ -5190,7 +5418,7 @@
 
       template <typename T,
                 typename Allocator,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
       {
          for (std::size_t i = 0; i < b.size(); ++i)
@@ -5217,7 +5445,7 @@
 
       template <typename T,
                 typename Allocator,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
       {
          for (std::size_t i = 0; i < b.size(); ++i)
@@ -5231,6 +5459,76 @@
          return true;
       }
 
+      template <typename Node>
+      class node_collection_destructor
+      {
+      public:
+
+         typedef node_collector_interface<Node> nci_t;
+
+         typedef typename nci_t::node_ptr_t     node_ptr_t;
+         typedef typename nci_t::node_pp_t      node_pp_t;
+         typedef typename nci_t::noderef_list_t noderef_list_t;
+
+         static void delete_nodes(node_ptr_t& root)
+         {
+            std::vector<node_pp_t> node_delete_list;
+            node_delete_list.reserve(1000);
+
+            collect_nodes(root, node_delete_list);
+
+            for (std::size_t i = 0; i < node_delete_list.size(); ++i)
+            {
+               node_ptr_t& node = *node_delete_list[i];
+               exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node)));
+               delete node;
+               node = reinterpret_cast<node_ptr_t>(0);
+            }
+         }
+
+      private:
+
+         static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
+         {
+            std::deque<node_ptr_t> node_list;
+            node_list.push_back(root);
+            node_delete_list.push_back(&root);
+
+            noderef_list_t child_node_delete_list;
+            child_node_delete_list.reserve(1000);
+
+            while (!node_list.empty())
+            {
+               node_list.front()->collect_nodes(child_node_delete_list);
+
+               if (!child_node_delete_list.empty())
+               {
+                  for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
+                  {
+                     node_pp_t& node = child_node_delete_list[i];
+
+                     if (0 == (*node))
+                     {
+                        exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
+                     }
+
+                     node_list.push_back(*node);
+                  }
+
+                  node_delete_list.insert(
+                     node_delete_list.end(),
+                     child_node_delete_list.begin(), child_node_delete_list.end());
+
+                  child_node_delete_list.clear();
+               }
+
+               node_list.pop_front();
+            }
+
+            std::reverse(node_delete_list.begin(), node_delete_list.end());
+         }
+      };
+
       template <typename NodeAllocator, typename T, std::size_t N>
       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
       {
@@ -5243,7 +5541,7 @@
       template <typename NodeAllocator,
                 typename T,
                 typename Allocator,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
       {
          for (std::size_t i = 0; i < b.size(); ++i)
@@ -5255,28 +5553,239 @@
       }
 
       template <typename NodeAllocator, typename T>
-      inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
+      inline void free_node(NodeAllocator&, expression_node<T>*& node)
       {
-         if (0 != node)
+         if ((0 == node) || is_variable_node(node) || is_string_node(node))
          {
-            if (
-                 (is_variable_node(node) || is_string_node(node)) ||
-                 force_delete
-               )
-               return;
-
-            node_allocator.free(node);
-            node = reinterpret_cast<expression_node<T>*>(0);
+            return;
          }
+
+         node_collection_destructor<expression_node<T> >
+            ::delete_nodes(node);
       }
 
       template <typename T>
       inline void destroy_node(expression_node<T>*& node)
       {
-         delete node;
-         node = reinterpret_cast<expression_node<T>*>(0);
+         if (0 != node)
+         {
+            node_collection_destructor<expression_node<T> >
+               ::delete_nodes(node);
+         }
       }
 
+      template <typename Node>
+      struct node_depth_base
+      {
+         node_depth_base()
+         : depth_set(false),
+           depth(0)
+         {}
+
+         virtual ~node_depth_base() {}
+
+         virtual std::size_t node_depth() const { return 1; }
+
+         std::size_t compute_node_depth(const Node* const& node) const
+         {
+            if (!depth_set)
+            {
+               depth = 1 + (node ? node->node_depth() : 0);
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const
+         {
+            if (!depth_set)
+            {
+               depth = 1 + (branch.first ? branch.first->node_depth() : 0);
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <std::size_t N>
+         std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const
+         {
+            if (!depth_set)
+            {
+               depth = 0;
+               for (std::size_t i = 0; i < N; ++i)
+               {
+                  if (branch[i].first)
+                  {
+                     depth = std::max(depth,branch[i].first->node_depth());
+                  }
+               }
+               depth += 1;
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <typename BranchType>
+         std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
+         {
+            if (!depth_set)
+            {
+               depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1));
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <typename BranchType>
+         std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
+                                        const BranchType& n2) const
+         {
+            if (!depth_set)
+            {
+               depth = 1 + std::max(
+                              std::max(compute_node_depth(n0), compute_node_depth(n1)),
+                              compute_node_depth(n2));
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <typename BranchType>
+         std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
+                                        const BranchType& n2, const BranchType& n3) const
+         {
+            if (!depth_set)
+            {
+               depth = 1 + std::max(
+                           std::max(compute_node_depth(n0), compute_node_depth(n1)),
+                           std::max(compute_node_depth(n2), compute_node_depth(n3)));
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence>
+         std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const
+         {
+            if (!depth_set)
+            {
+               for (std::size_t i = 0; i < branch_list.size(); ++i)
+               {
+                  if (branch_list[i])
+                  {
+                     depth = std::max(depth, compute_node_depth(branch_list[i]));
+                  }
+               }
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence>
+         std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const
+         {
+            if (!depth_set)
+            {
+               for (std::size_t i = 0; i < branch_list.size(); ++i)
+               {
+                  if (branch_list[i].first)
+                  {
+                     depth = std::max(depth, compute_node_depth(branch_list[i].first));
+                  }
+               }
+               depth_set = true;
+            }
+
+            return depth;
+         }
+
+         mutable bool depth_set;
+         mutable std::size_t depth;
+
+         template <typename NodeSequence>
+         void collect(Node*const& node,
+                      const bool deletable,
+                      NodeSequence& delete_node_list) const
+         {
+            if ((0 != node) && deletable)
+            {
+               delete_node_list.push_back(const_cast<Node**>(&node));
+            }
+         }
+
+         template <typename NodeSequence>
+         void collect(const std::pair<Node*, bool>& branch,
+                      NodeSequence& delete_node_list) const
+         {
+            collect(branch.first, branch.second, delete_node_list);
+         }
+
+         template <typename NodeSequence>
+         void collect(Node*& node,
+                      NodeSequence& delete_node_list) const
+         {
+            collect(node, branch_deletable(node), delete_node_list);
+         }
+
+         template <std::size_t N, typename NodeSequence>
+         void collect(const std::pair<Node*, bool>(&branch)[N],
+                      NodeSequence& delete_node_list) const
+         {
+            for (std::size_t i = 0; i < N; ++i)
+            {
+               collect(branch[i].first, branch[i].second, delete_node_list);
+            }
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence,
+                   typename NodeSequence>
+         void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch,
+                      NodeSequence& delete_node_list) const
+         {
+            for (std::size_t i = 0; i < branch.size(); ++i)
+            {
+               collect(branch[i].first, branch[i].second, delete_node_list);
+            }
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence,
+                   typename NodeSequence>
+         void collect(const Sequence<Node*, Allocator>& branch_list,
+                      NodeSequence& delete_node_list) const
+         {
+            for (std::size_t i = 0; i < branch_list.size(); ++i)
+            {
+               collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
+            }
+         }
+
+         template <typename Boolean,
+                   typename AllocatorT,
+                   typename AllocatorB,
+                   template <typename, typename> class Sequence,
+                   typename NodeSequence>
+         void collect(const Sequence<Node*, AllocatorT>& branch_list,
+                      const Sequence<Boolean, AllocatorB>& branch_deletable_list,
+                      NodeSequence& delete_node_list) const
+         {
+            for (std::size_t i = 0; i < branch_list.size(); ++i)
+            {
+               collect(branch_list[i], branch_deletable_list[i], delete_node_list);
+            }
+         }
+      };
+
       template <typename Type>
       class vector_holder
       {
@@ -5353,7 +5862,7 @@
          };
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          class sequence_vector_impl : public vector_holder_base
          {
          public:
@@ -5490,30 +5999,70 @@
          }
       };
 
+      template <typename T, std::size_t N>
+      inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
+                                        expression_node<T>* b,
+                                        const std::size_t& index)
+      {
+         if (b && (index < N))
+         {
+            branch[index] = std::make_pair(b,branch_deletable(b));
+         }
+      }
+
+      template <typename T>
+      inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
+      {
+         if (b)
+         {
+            branch = std::make_pair(b,branch_deletable(b));
+         }
+      }
+
+      template <std::size_t N, typename T>
+      inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
+                                expression_node<T>* b0,
+                                expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
+      {
+         construct_branch_pair(branch, b0, 0);
+         construct_branch_pair(branch, b1, 1);
+         construct_branch_pair(branch, b2, 2);
+         construct_branch_pair(branch, b3, 3);
+         construct_branch_pair(branch, b4, 4);
+         construct_branch_pair(branch, b5, 5);
+         construct_branch_pair(branch, b6, 6);
+         construct_branch_pair(branch, b7, 7);
+         construct_branch_pair(branch, b8, 8);
+         construct_branch_pair(branch, b9, 9);
+      }
+
       template <typename T>
       class null_eq_node : public expression_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         null_eq_node(expression_ptr brnch, const bool equality = true)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_)),
-           equality_(equality)
-         {}
-
-        ~null_eq_node()
+         explicit null_eq_node(expression_ptr branch, const bool equality = true)
+         : equality_(equality)
          {
-            if (branch_ && branch_deletable_)
-            {
-               destroy_node(branch_);
-            }
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            const T v = branch_->value();
+            assert(branch_.first);
+
+            const T v = branch_.first->value();
             const bool result = details::numeric::is_nan(v);
 
             if (result)
@@ -5534,14 +6083,23 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_;
+            return branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_,node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         expression_ptr branch_;
-         const bool branch_deletable_;
          bool equality_;
+         branch_t branch_;
       };
 
       template <typename T>
@@ -5610,7 +6168,7 @@
 
          virtual std::string str () const = 0;
 
-         virtual const char_t* base() const = 0;
+         virtual char_cptr   base() const = 0;
 
          virtual std::size_t size() const = 0;
       };
@@ -5653,7 +6211,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return value_.data();
          }
@@ -5689,25 +6247,19 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         unary_node(const operator_type& opr,
-                    expression_ptr brnch)
-         : operation_(opr),
-           branch_(brnch),
-           branch_deletable_(branch_deletable(branch_))
-         {}
-
-        ~unary_node()
+         unary_node(const operator_type& opr, expression_ptr branch)
+         : operation_(opr)
          {
-            if (branch_ && branch_deletable_)
-            {
-               destroy_node(branch_);
-            }
+            construct_branch_pair(branch_,branch);
          }
 
          inline T value() const
          {
-            const T arg = branch_->value();
+            assert(branch_.first);
+
+            const T arg = branch_.first->value();
 
             return numeric::process<T>(operation_,arg);
          }
@@ -5724,94 +6276,28 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_;
+            return branch_.first;
          }
 
          inline void release()
          {
-            branch_deletable_ = false;
+            branch_.second = false;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       protected:
 
          operator_type operation_;
-         expression_ptr branch_;
-         bool branch_deletable_;
-      };
-
-      template <typename T, std::size_t D, bool B>
-      struct construct_branch_pair
-      {
-         template <std::size_t N>
-         static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
-         {}
-      };
-
-      template <typename T, std::size_t D>
-      struct construct_branch_pair<T,D,true>
-      {
-         template <std::size_t N>
-         static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
-         {
-            if (b)
-            {
-               branch[D] = std::make_pair(b,branch_deletable(b));
-            }
-         }
-      };
-
-      template <std::size_t N, typename T>
-      inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
-                                expression_node<T>* b0,
-                                expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
-                                expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
-      {
-         construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
-         construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
-         construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
-         construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
-         construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
-         construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
-         construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
-         construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
-         construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
-         construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
-      }
-
-      struct cleanup_branches
-      {
-         template <typename T, std::size_t N>
-         static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
-         {
-            for (std::size_t i = 0; i < N; ++i)
-            {
-               if (branch[i].first && branch[i].second)
-               {
-                  destroy_node(branch[i].first);
-               }
-            }
-         }
-
-         template <typename T,
-                   typename Allocator,
-                   template <typename,typename> class Sequence>
-         static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
-         {
-            for (std::size_t i = 0; i < branch.size(); ++i)
-            {
-               if (branch[i].first && branch[i].second)
-               {
-                  destroy_node(branch[i].first);
-               }
-            }
-         }
+         branch_t branch_;
       };
 
       template <typename T>
@@ -5830,13 +6316,11 @@
             init_branches<2>(branch_, branch0, branch1);
          }
 
-        ~binary_node()
-         {
-            cleanup_branches::execute<T,2>(branch_);
-         }
-
          inline T value() const
          {
+            assert(branch_[0].first);
+            assert(branch_[1].first);
+
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
 
@@ -5863,6 +6347,16 @@
                return reinterpret_cast<expression_ptr>(0);
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
+         }
+
       protected:
 
          operator_type operation_;
@@ -5882,13 +6376,11 @@
             init_branches<2>(branch_, branch0, branch1);
          }
 
-        ~binary_ext_node()
-         {
-            cleanup_branches::execute<T,2>(branch_);
-         }
-
          inline T value() const
          {
+            assert(branch_[0].first);
+            assert(branch_[1].first);
+
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
 
@@ -5915,6 +6407,16 @@
                return reinterpret_cast<expression_ptr>(0);
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
+         }
+
       protected:
 
          branch_t branch_[2];
@@ -5937,13 +6439,12 @@
             init_branches<3>(branch_, branch0, branch1, branch2);
          }
 
-        ~trinary_node()
-         {
-            cleanup_branches::execute<T,3>(branch_);
-         }
-
          inline T value() const
          {
+            assert(branch_[0].first);
+            assert(branch_[1].first);
+            assert(branch_[2].first);
+
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
             const T arg2 = branch_[2].first->value();
@@ -5959,10 +6460,8 @@
                                 else
                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
 
-               default        : {
-                                   exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
-                                   return std::numeric_limits<T>::quiet_NaN();
-                                }
+               default        : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
+                                return std::numeric_limits<T>::quiet_NaN();
             }
          }
 
@@ -5971,6 +6470,16 @@
             return expression_node<T>::e_trinary;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
+         }
+
       protected:
 
          operator_type operation_;
@@ -5995,11 +6504,6 @@
             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
          }
 
-        ~quaternary_node()
-         {
-            cleanup_branches::execute<T,4>(branch_);
-         }
-
          inline T value() const
          {
             return std::numeric_limits<T>::quiet_NaN();
@@ -6010,6 +6514,16 @@
             return expression_node<T>::e_quaternary;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
+         }
+
       protected:
 
          operator_type operation_;
@@ -6022,42 +6536,27 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         conditional_node(expression_ptr test,
+         conditional_node(expression_ptr condition,
                           expression_ptr consequent,
                           expression_ptr alternative)
-         : test_(test),
-           consequent_(consequent),
-           alternative_(alternative),
-           test_deletable_(branch_deletable(test_)),
-           consequent_deletable_(branch_deletable(consequent_)),
-           alternative_deletable_(branch_deletable(alternative_))
-         {}
-
-        ~conditional_node()
          {
-            if (test_ && test_deletable_)
-            {
-               destroy_node(test_);
-            }
-
-            if (consequent_ && consequent_deletable_ )
-            {
-               destroy_node(consequent_);
-            }
-
-            if (alternative_ && alternative_deletable_)
-            {
-               destroy_node(alternative_);
-            }
+            construct_branch_pair(condition_  , condition  );
+            construct_branch_pair(consequent_ , consequent );
+            construct_branch_pair(alternative_, alternative);
          }
 
          inline T value() const
          {
-            if (is_true(test_))
-               return consequent_->value();
+            assert(condition_  .first);
+            assert(consequent_ .first);
+            assert(alternative_.first);
+
+            if (is_true(condition_))
+               return consequent_.first->value();
             else
-               return alternative_->value();
+               return alternative_.first->value();
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -6065,14 +6564,24 @@
             return expression_node<T>::e_conditional;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(alternative_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (condition_, consequent_, alternative_);
+         }
+
       private:
 
-         expression_ptr test_;
-         expression_ptr consequent_;
-         expression_ptr alternative_;
-         const bool test_deletable_;
-         const bool consequent_deletable_;
-         const bool alternative_deletable_;
+         branch_t condition_;
+         branch_t consequent_;
+         branch_t alternative_;
       };
 
       template <typename T>
@@ -6082,32 +6591,22 @@
 
          // Consequent only conditional statement node
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         cons_conditional_node(expression_ptr test,
+         cons_conditional_node(expression_ptr condition,
                                expression_ptr consequent)
-         : test_(test),
-           consequent_(consequent),
-           test_deletable_(branch_deletable(test_)),
-           consequent_deletable_(branch_deletable(consequent_))
-         {}
-
-        ~cons_conditional_node()
          {
-            if (test_ && test_deletable_)
-            {
-               destroy_node(test_);
-            }
-
-            if (consequent_ && consequent_deletable_)
-            {
-               destroy_node(consequent_);
-            }
+            construct_branch_pair(condition_ , condition );
+            construct_branch_pair(consequent_, consequent);
          }
 
          inline T value() const
          {
-            if (is_true(test_))
-               return consequent_->value();
+            assert(condition_ .first);
+            assert(consequent_.first);
+
+            if (is_true(condition_))
+               return consequent_.first->value();
             else
                return std::numeric_limits<T>::quiet_NaN();
          }
@@ -6117,12 +6616,22 @@
             return expression_node<T>::e_conditional;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(consequent_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::
+               compute_node_depth(condition_, consequent_);
+         }
+
       private:
 
-         expression_ptr test_;
-         expression_ptr consequent_;
-         const bool test_deletable_;
-         const bool consequent_deletable_;
+         branch_t condition_;
+         branch_t consequent_;
       };
 
       #ifndef exprtk_disable_break_continue
@@ -6147,23 +6656,16 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          break_node(expression_ptr ret = expression_ptr(0))
-         : return_(ret),
-           return_deletable_(branch_deletable(return_))
-         {}
-
-        ~break_node()
          {
-            if (return_deletable_)
-            {
-               destroy_node(return_);
-            }
+            construct_branch_pair(return_, ret);
          }
 
          inline T value() const
          {
-            throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
+            throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN());
             #ifndef _MSC_VER
             return std::numeric_limits<T>::quiet_NaN();
             #endif
@@ -6174,10 +6676,19 @@
             return expression_node<T>::e_break;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(return_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(return_);
+         }
+
       private:
 
-         expression_ptr return_;
-         const bool return_deletable_;
+         branch_t return_;
       };
 
       template <typename T>
@@ -6200,40 +6711,90 @@
       };
       #endif
 
+      #ifdef exprtk_enable_runtime_checks
+      struct loop_runtime_checker
+      {
+         loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0),
+                              loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
+         : iteration_count_(0),
+           loop_runtime_check_(loop_rt_chk),
+           loop_type(lp_typ)
+         {}
+
+         inline void reset(const _uint64_t initial_value = 0) const
+         {
+            iteration_count_ = initial_value;
+         }
+
+         inline bool check() const
+         {
+            if (
+                 (0 == loop_runtime_check_) ||
+                 (++iteration_count_ <= loop_runtime_check_->max_loop_iterations)
+               )
+            {
+               return true;
+            }
+
+            loop_runtime_check::violation_context ctxt;
+            ctxt.loop      = loop_type;
+            ctxt.violation = loop_runtime_check::e_iteration_count;
+
+            loop_runtime_check_->handle_runtime_violation(ctxt);
+
+            return false;
+         }
+
+         mutable _uint64_t iteration_count_;
+         mutable loop_runtime_check_ptr loop_runtime_check_;
+         loop_runtime_check::loop_types loop_type;
+      };
+      #else
+      struct loop_runtime_checker
+      {
+         loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types)
+         {}
+
+         inline void reset(const _uint64_t = 0) const
+         {}
+
+         inline bool check() const
+         {
+            return true;
+         }
+      };
+      #endif
+
       template <typename T>
-      class while_loop_node : public expression_node<T>
+      class while_loop_node : public expression_node<T>,
+                              public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         while_loop_node(expression_ptr condition, expression_ptr loop_body)
-         : condition_(condition),
-           loop_body_(loop_body),
-           condition_deletable_(branch_deletable(condition_)),
-           loop_body_deletable_(branch_deletable(loop_body_))
-         {}
-
-        ~while_loop_node()
+         while_loop_node(expression_ptr condition,
+                         expression_ptr loop_body,
+                         loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop)
          {
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(condition_, condition);
+            construct_branch_pair(loop_body_, loop_body);
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
-            while (is_true(condition_))
+            loop_runtime_checker::reset();
+
+            while (is_true(condition_) && loop_runtime_checker::check())
             {
-               result = loop_body_->value();
+               result = loop_body_.first->value();
             }
 
             return result;
@@ -6244,50 +6805,55 @@
             return expression_node<T>::e_while;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+         }
+
       private:
 
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         const bool condition_deletable_;
-         const bool loop_body_deletable_;
+         branch_t condition_;
+         branch_t loop_body_;
       };
 
       template <typename T>
-      class repeat_until_loop_node : public expression_node<T>
+      class repeat_until_loop_node : public expression_node<T>,
+                                     public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
-         : condition_(condition),
-           loop_body_(loop_body),
-           condition_deletable_(branch_deletable(condition_)),
-           loop_body_deletable_(branch_deletable(loop_body_))
-         {}
-
-        ~repeat_until_loop_node()
+         repeat_until_loop_node(expression_ptr condition,
+                                expression_ptr loop_body,
+                                loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
          {
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(condition_, condition);
+            construct_branch_pair(loop_body_, loop_body);
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
+            loop_runtime_checker::reset(1);
+
             do
             {
-               result = loop_body_->value();
+               result = loop_body_.first->value();
             }
-            while (is_false(condition_));
+            while (is_false(condition_.first) && loop_runtime_checker::check());
 
             return result;
          }
@@ -6297,78 +6863,70 @@
             return expression_node<T>::e_repeat;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+         }
+
       private:
 
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         const bool condition_deletable_;
-         const bool loop_body_deletable_;
+         branch_t condition_;
+         branch_t loop_body_;
       };
 
       template <typename T>
-      class for_loop_node : public expression_node<T>
+      class for_loop_node : public expression_node<T>,
+                            public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          for_loop_node(expression_ptr initialiser,
                        expression_ptr condition,
                        expression_ptr incrementor,
-                       expression_ptr loop_body)
-         : initialiser_(initialiser),
-           condition_  (condition  ),
-           incrementor_(incrementor),
-           loop_body_  (loop_body  ),
-           initialiser_deletable_(branch_deletable(initialiser_)),
-           condition_deletable_  (branch_deletable(condition_  )),
-           incrementor_deletable_(branch_deletable(incrementor_)),
-           loop_body_deletable_  (branch_deletable(loop_body_  ))
-         {}
-
-        ~for_loop_node()
+                       expression_ptr loop_body,
+                       loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
          {
-            if (initialiser_ && initialiser_deletable_)
-            {
-               destroy_node(initialiser_);
-            }
-
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (incrementor_ && incrementor_deletable_)
-            {
-               destroy_node(incrementor_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(initialiser_, initialiser);
+            construct_branch_pair(condition_  , condition  );
+            construct_branch_pair(incrementor_, incrementor);
+            construct_branch_pair(loop_body_  , loop_body  );
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
-            if (initialiser_)
-               initialiser_->value();
+            loop_runtime_checker::reset();
 
-            if (incrementor_)
+            if (initialiser_.first)
+               initialiser_.first->value();
+
+            if (incrementor_.first)
             {
-               while (is_true(condition_))
+               while (is_true(condition_) && loop_runtime_checker::check())
                {
-                  result = loop_body_->value();
-                  incrementor_->value();
+                  result = loop_body_.first->value();
+                  incrementor_.first->value();
                }
             }
             else
             {
-               while (is_true(condition_))
+               while (is_true(condition_) && loop_runtime_checker::check())
                {
-                  result = loop_body_->value();
+                  result = loop_body_.first->value();
                }
             }
 
@@ -6380,55 +6938,61 @@
             return expression_node<T>::e_for;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
+            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (initialiser_, condition_, incrementor_, loop_body_);
+         }
+
       private:
 
-         expression_ptr initialiser_      ;
-         expression_ptr condition_        ;
-         expression_ptr incrementor_      ;
-         expression_ptr loop_body_        ;
-         const bool initialiser_deletable_;
-         const bool condition_deletable_  ;
-         const bool incrementor_deletable_;
-         const bool loop_body_deletable_  ;
+         branch_t initialiser_;
+         branch_t condition_  ;
+         branch_t incrementor_;
+         branch_t loop_body_  ;
       };
 
       #ifndef exprtk_disable_break_continue
       template <typename T>
-      class while_loop_bc_node : public expression_node<T>
+      class while_loop_bc_node : public expression_node<T>,
+                                 public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
-         : condition_(condition),
-           loop_body_(loop_body),
-           condition_deletable_(branch_deletable(condition_)),
-           loop_body_deletable_(branch_deletable(loop_body_))
-         {}
-
-        ~while_loop_bc_node()
+         while_loop_bc_node(expression_ptr condition,
+                            expression_ptr loop_body,
+                            loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
          {
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(condition_, condition);
+            construct_branch_pair(loop_body_, loop_body);
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
-            while (is_true(condition_))
+            loop_runtime_checker::reset();
+
+            while (is_true(condition_) && loop_runtime_checker::check())
             {
                try
                {
-                  result = loop_body_->value();
+                  result = loop_body_.first->value();
                }
                catch(const break_exception<T>& e)
                {
@@ -6446,50 +7010,55 @@
             return expression_node<T>::e_while;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+         }
+
       private:
 
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         const bool condition_deletable_;
-         const bool loop_body_deletable_;
+         branch_t condition_;
+         branch_t loop_body_;
       };
 
       template <typename T>
-      class repeat_until_loop_bc_node : public expression_node<T>
+      class repeat_until_loop_bc_node : public expression_node<T>,
+                                        public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
-         : condition_(condition),
-           loop_body_(loop_body),
-           condition_deletable_(branch_deletable(condition_)),
-           loop_body_deletable_(branch_deletable(loop_body_))
-         {}
-
-        ~repeat_until_loop_bc_node()
+         repeat_until_loop_bc_node(expression_ptr condition,
+                                   expression_ptr loop_body,
+                                   loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
          {
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(condition_, condition);
+            construct_branch_pair(loop_body_, loop_body);
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
+            loop_runtime_checker::reset();
+
             do
             {
                try
                {
-                  result = loop_body_->value();
+                  result = loop_body_.first->value();
                }
                catch(const break_exception<T>& e)
                {
@@ -6498,7 +7067,7 @@
                catch(const continue_exception&)
                {}
             }
-            while (is_false(condition_));
+            while (is_false(condition_.first) && loop_runtime_checker::check());
 
             return result;
          }
@@ -6508,72 +7077,64 @@
             return expression_node<T>::e_repeat;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+         }
+
       private:
 
-         expression_ptr condition_;
-         expression_ptr loop_body_;
-         const bool condition_deletable_;
-         const bool loop_body_deletable_;
+         branch_t condition_;
+         branch_t loop_body_;
       };
 
       template <typename T>
-      class for_loop_bc_node : public expression_node<T>
+      class for_loop_bc_node : public expression_node<T>,
+                               public loop_runtime_checker
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          for_loop_bc_node(expression_ptr initialiser,
-                       expression_ptr condition,
-                       expression_ptr incrementor,
-                       expression_ptr loop_body)
-         : initialiser_(initialiser),
-           condition_  (condition  ),
-           incrementor_(incrementor),
-           loop_body_  (loop_body  ),
-           initialiser_deletable_(branch_deletable(initialiser_)),
-           condition_deletable_  (branch_deletable(condition_  )),
-           incrementor_deletable_(branch_deletable(incrementor_)),
-           loop_body_deletable_  (branch_deletable(loop_body_  ))
-         {}
-
-        ~for_loop_bc_node()
+                          expression_ptr condition,
+                          expression_ptr incrementor,
+                          expression_ptr loop_body,
+                          loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
+         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
          {
-            if (initialiser_ && initialiser_deletable_)
-            {
-               destroy_node(initialiser_);
-            }
-
-            if (condition_ && condition_deletable_)
-            {
-               destroy_node(condition_);
-            }
-
-            if (incrementor_ && incrementor_deletable_)
-            {
-               destroy_node(incrementor_);
-            }
-
-            if (loop_body_ && loop_body_deletable_)
-            {
-               destroy_node(loop_body_);
-            }
+            construct_branch_pair(initialiser_, initialiser);
+            construct_branch_pair(condition_  , condition  );
+            construct_branch_pair(incrementor_, incrementor);
+            construct_branch_pair(loop_body_  , loop_body  );
          }
 
          inline T value() const
          {
+            assert(condition_.first);
+            assert(loop_body_.first);
+
             T result = T(0);
 
-            if (initialiser_)
-               initialiser_->value();
+            loop_runtime_checker::reset();
 
-            if (incrementor_)
+            if (initialiser_.first)
+               initialiser_.first->value();
+
+            if (incrementor_.first)
             {
-               while (is_true(condition_))
+               while (is_true(condition_) && loop_runtime_checker::check())
                {
                   try
                   {
-                     result = loop_body_->value();
+                     result = loop_body_.first->value();
                   }
                   catch(const break_exception<T>& e)
                   {
@@ -6582,16 +7143,16 @@
                   catch(const continue_exception&)
                   {}
 
-                  incrementor_->value();
+                  incrementor_.first->value();
                }
             }
             else
             {
-               while (is_true(condition_))
+               while (is_true(condition_) && loop_runtime_checker::check())
                {
                   try
                   {
-                     result = loop_body_->value();
+                     result = loop_body_.first->value();
                   }
                   catch(const break_exception<T>& e)
                   {
@@ -6610,16 +7171,26 @@
             return expression_node<T>::e_for;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
+            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (initialiser_, condition_, incrementor_, loop_body_);
+         }
+
       private:
 
-         expression_ptr initialiser_;
-         expression_ptr condition_  ;
-         expression_ptr incrementor_;
-         expression_ptr loop_body_  ;
-         const bool initialiser_deletable_;
-         const bool condition_deletable_  ;
-         const bool incrementor_deletable_;
-         const bool loop_body_deletable_  ;
+         branch_t initialiser_;
+         branch_t condition_  ;
+         branch_t incrementor_;
+         branch_t loop_body_  ;
       };
       #endif
 
@@ -6629,44 +7200,31 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
          {
             if (1 != (arg_list.size() & 1))
                return;
 
             arg_list_.resize(arg_list.size());
-            delete_branch_.resize(arg_list.size());
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
                if (arg_list[i])
                {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+                  construct_branch_pair(arg_list_[i], arg_list[i]);
                }
                else
                {
                   arg_list_.clear();
-                  delete_branch_.clear();
                   return;
                }
             }
          }
 
-        ~switch_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
-            {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  destroy_node(arg_list_[i]);
-               }
-            }
-         }
-
          inline T value() const
          {
             if (!arg_list_.empty())
@@ -6675,8 +7233,8 @@
 
                for (std::size_t i = 0; i < upper_bound; i += 2)
                {
-                  expression_ptr condition  = arg_list_[i    ];
-                  expression_ptr consequent = arg_list_[i + 1];
+                  expression_ptr condition  = arg_list_[i    ].first;
+                  expression_ptr consequent = arg_list_[i + 1].first;
 
                   if (is_true(condition))
                   {
@@ -6684,7 +7242,7 @@
                   }
                }
 
-               return arg_list_[upper_bound]->value();
+               return arg_list_[upper_bound].first->value();
             }
             else
                return std::numeric_limits<T>::quiet_NaN();
@@ -6695,10 +7253,19 @@
             return expression_node<T>::e_switch;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
+         }
+
       protected:
 
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
+         std::vector<branch_t> arg_list_;
       };
 
       template <typename T, typename Switch_N>
@@ -6709,8 +7276,8 @@
          typedef expression_node<T>* expression_ptr;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
          : switch_node<T>(arg_list)
          {}
 
@@ -6726,44 +7293,31 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
          {
             if (0 != (arg_list.size() & 1))
                return;
 
             arg_list_.resize(arg_list.size());
-            delete_branch_.resize(arg_list.size());
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
                if (arg_list[i])
                {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+                  construct_branch_pair(arg_list_[i], arg_list[i]);
                }
                else
                {
                   arg_list_.clear();
-                  delete_branch_.clear();
                   return;
                }
             }
          }
 
-        ~multi_switch_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
-            {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  destroy_node(arg_list_[i]);
-               }
-            }
-         }
-
          inline T value() const
          {
             T result = T(0);
@@ -6777,8 +7331,8 @@
 
             for (std::size_t i = 0; i < upper_bound; i += 2)
             {
-               expression_ptr condition  = arg_list_[i    ];
-               expression_ptr consequent = arg_list_[i + 1];
+               expression_ptr condition  = arg_list_[i    ].first;
+               expression_ptr consequent = arg_list_[i + 1].first;
 
                if (is_true(condition))
                {
@@ -6794,10 +7348,19 @@
             return expression_node<T>::e_mswitch;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
+         }
+
       private:
 
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
+         std::vector<branch_t> arg_list_;
       };
 
       template <typename T>
@@ -6824,7 +7387,7 @@
          : value_(&null_value)
          {}
 
-         variable_node(T& v)
+         explicit variable_node(T& v)
          : value_(&v)
          {}
 
@@ -6913,30 +7476,26 @@
             }
          }
 
-         bool const_range()
+         bool const_range() const
          {
            return ( n0_c.first &&  n1_c.first) &&
                   (!n0_e.first && !n1_e.first);
          }
 
-         bool var_range()
+         bool var_range() const
          {
            return ( n0_e.first &&  n1_e.first) &&
                   (!n0_c.first && !n1_c.first);
          }
 
-         bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
+         bool operator() (std::size_t& r0, std::size_t& r1,
+                          const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
          {
             if (n0_c.first)
                r0 = n0_c.second;
             else if (n0_e.first)
             {
-               T r0_value = n0_e.second->value();
-
-               if (r0_value < 0)
-                  return false;
-               else
-                  r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
+               r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
             }
             else
                return false;
@@ -6945,12 +7504,7 @@
                r1 = n1_c.second;
             else if (n1_e.first)
             {
-               T r1_value = n1_e.second->value();
-
-               if (r1_value < 0)
-                  return false;
-               else
-                  r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
+               r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
             }
             else
                return false;
@@ -6966,7 +7520,11 @@
             cache.first  = r0;
             cache.second = r1;
 
+            #ifndef exprtk_enable_runtime_checks
             return (r0 <= r1);
+            #else
+            return range_runtime_check(r0, r1, size);
+            #endif
          }
 
          inline std::size_t const_size() const
@@ -6984,6 +7542,27 @@
          std::pair<bool,std::size_t        > n0_c;
          std::pair<bool,std::size_t        > n1_c;
          mutable cached_range_t             cache;
+
+         #ifdef exprtk_enable_runtime_checks
+         bool range_runtime_check(const std::size_t r0,
+                                  const std::size_t r1,
+                                  const std::size_t size) const
+         {
+            if ((r0 < 0) || (r0 >= size))
+            {
+               throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)");
+               return false;
+            }
+
+            if ((r1 < 0) || (r1 >= size))
+            {
+               throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)");
+               return false;
+            }
+
+            return (r0 <= r1);
+         }
+         #endif
       };
 
       template <typename T>
@@ -7047,7 +7626,7 @@
          typedef vector_node<T>*     vector_node_ptr;
          typedef vec_data_store<T>             vds_t;
 
-         vector_node(vector_holder_t* vh)
+         explicit vector_node(vector_holder_t* vh)
          : vector_holder_(vh),
            vds_((*vector_holder_).size(),(*vector_holder_)[0])
          {
@@ -7111,38 +7690,31 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_holder<T>    vector_holder_t;
-         typedef vector_holder_t*    vector_holder_ptr;
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
-         : index_(index),
-           vec_holder_(vec_holder),
-           vector_base_((*vec_holder)[0]),
-           index_deletable_(branch_deletable(index_))
-         {}
-
-        ~vector_elem_node()
+         : vec_holder_(vec_holder),
+           vector_base_((*vec_holder)[0])
          {
-            if (index_ && index_deletable_)
-            {
-               destroy_node(index_);
-            }
+            construct_branch_pair(index_, index);
          }
 
          inline T value() const
          {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline T& ref()
          {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline const T& ref() const
          {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -7155,12 +7727,21 @@
             return (*vec_holder_);
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(index_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(index_);
+         }
+
       private:
 
-         expression_ptr index_;
          vector_holder_ptr vec_holder_;
          T* vector_base_;
-         const bool index_deletable_;
+         branch_t index_;
       };
 
       template <typename T>
@@ -7169,41 +7750,33 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_holder<T>    vector_holder_t;
-         typedef vector_holder_t*    vector_holder_ptr;
-         typedef vec_data_store<T>   vds_t;
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef vec_data_store<T>              vds_t;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
-         : index_(index),
-           index_deletable_(branch_deletable(index_)),
-           vector_holder_(vec_holder),
+         : vector_holder_(vec_holder),
            vds_((*vector_holder_).size(),(*vector_holder_)[0])
          {
             vector_holder_->set_ref(&vds_.ref());
-         }
-
-        ~rebasevector_elem_node()
-         {
-            if (index_ && index_deletable_)
-            {
-               destroy_node(index_);
-            }
+            construct_branch_pair(index_, index);
          }
 
          inline T value() const
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline T& ref()
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline const T& ref() const
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -7216,12 +7789,21 @@
             return (*vector_holder_);
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(index_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(index_);
+         }
+
       private:
 
-         expression_ptr index_;
-         const bool index_deletable_;
          vector_holder_ptr vector_holder_;
          vds_t             vds_;
+         branch_t          index_;
       };
 
       template <typename T>
@@ -7292,17 +7874,6 @@
            single_value_initialse_(single_value_initialse)
          {}
 
-        ~vector_assignment_node()
-         {
-            for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
-            {
-               if (branch_deletable(initialiser_list_[i]))
-               {
-                  destroy_node(initialiser_list_[i]);
-               }
-            }
-         }
-
          inline T value() const
          {
             if (single_value_initialse_)
@@ -7338,6 +7909,16 @@
             return expression_node<T>::e_vecdefass;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
       private:
 
          vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
@@ -7459,6 +8040,9 @@
 
          inline T value() const
          {
+            assert(binary_node<T>::branch_[0].first);
+            assert(binary_node<T>::branch_[1].first);
+
             if (initialised_)
             {
                binary_node<T>::branch_[0].first->value();
@@ -7560,7 +8144,7 @@
             return ref();
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &(*value_)[0];
          }
@@ -7640,7 +8224,7 @@
             return (*value_);
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &(*value_)[0];
          }
@@ -7718,7 +8302,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return value_.data();
          }
@@ -7763,18 +8347,18 @@
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
-         typedef stringvar_node  <T>* strvar_node_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef expression_node <T>*      expression_ptr;
+         typedef stringvar_node  <T>*     strvar_node_ptr;
+         typedef string_base_node<T>*        str_base_ptr;
+         typedef range_pack      <T>              range_t;
+         typedef range_t*                       range_ptr;
+         typedef range_interface<T>              irange_t;
+         typedef irange_t*                     irange_ptr;
+         typedef std::pair<expression_ptr,bool>  branch_t;
+
 
          generic_string_range_node(expression_ptr str_branch, const range_t& brange)
          : initialised_(false),
-           branch_(str_branch),
-           branch_deletable_(branch_deletable(branch_)),
            str_base_ptr_ (0),
            str_range_ptr_(0),
            base_range_(brange)
@@ -7784,14 +8368,16 @@
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
 
-            if (is_generally_string_node(branch_))
+            construct_branch_pair(branch_, str_branch);
+
+            if (is_generally_string_node(branch_.first))
             {
-               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
 
                if (0 == str_base_ptr_)
                   return;
 
-               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
+               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
 
                if (0 == str_range_ptr_)
                   return;
@@ -7803,18 +8389,15 @@
         ~generic_string_range_node()
          {
             base_range_.free();
-
-            if (branch_ && branch_deletable_)
-            {
-               destroy_node(branch_);
-            }
          }
 
          inline T value() const
          {
             if (initialised_)
             {
-               branch_->value();
+               assert(branch_.first);
+
+               branch_.first->value();
 
                std::size_t str_r0 = 0;
                std::size_t str_r1 = 0;
@@ -7822,13 +8405,13 @@
                std::size_t r0 = 0;
                std::size_t r1 = 0;
 
-               range_t& range = str_range_ptr_->range_ref();
+               const range_t& range = str_range_ptr_->range_ref();
 
                const std::size_t base_str_size = str_base_ptr_->size();
 
                if (
-                    range      (str_r0,str_r1,base_str_size) &&
-                    base_range_(    r0,    r1,base_str_size)
+                    range      (str_r0, str_r1, base_str_size) &&
+                    base_range_(    r0,     r1, base_str_size)
                   )
                {
                   const std::size_t size = (r1 - r0) + 1;
@@ -7848,7 +8431,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &value_[0];
          }
@@ -7873,11 +8456,20 @@
             return expression_node<T>::e_strgenrange;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
+         }
+
       private:
 
          bool                initialised_;
-         expression_ptr           branch_;
-         const bool     branch_deletable_;
+         branch_t                 branch_;
          str_base_ptr       str_base_ptr_;
          irange_ptr        str_range_ptr_;
          mutable range_t      base_range_;
@@ -7951,6 +8543,9 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
@@ -7960,12 +8555,12 @@
                std::size_t str1_r0 = 0;
                std::size_t str1_r1 = 0;
 
-               range_t& range0 = str0_range_ptr_->range_ref();
-               range_t& range1 = str1_range_ptr_->range_ref();
+               const range_t& range0 = str0_range_ptr_->range_ref();
+               const range_t& range1 = str1_range_ptr_->range_ref();
 
                if (
-                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
-                    range1(str1_r0,str1_r1,str1_base_ptr_->size())
+                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
+                    range1(str1_r0, str1_r1, str1_base_ptr_->size())
                   )
                {
                   const std::size_t size0 = (str0_r1 - str0_r0) + 1;
@@ -7987,7 +8582,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &value_[0];
          }
@@ -8061,10 +8656,13 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
-               std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());
+               std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
             }
 
             return std::numeric_limits<T>::quiet_NaN();
@@ -8075,7 +8673,7 @@
             return str0_node_ptr_->str();
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
            return str0_node_ptr_->base();
          }
@@ -8135,12 +8733,12 @@
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str0_range_ptr_ = &(range_ptr->range_ref());
+               str0_range_ptr_ = &(range->range_ref());
             }
 
             if (is_generally_string_node(binary_node<T>::branch_[1].first))
@@ -8150,12 +8748,12 @@
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str1_range_ptr_ = &(range_ptr->range_ref());
+               str1_range_ptr_ = &(range->range_ref());
             }
 
             initialised_ = str0_base_ptr_  &&
@@ -8168,6 +8766,9 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
@@ -8177,23 +8778,23 @@
                std::size_t str1_r0 = 0;
                std::size_t str1_r1 = 0;
 
-               range_t& range0 = (*str0_range_ptr_);
-               range_t& range1 = (*str1_range_ptr_);
+               const range_t& range0 = (*str0_range_ptr_);
+               const range_t& range1 = (*str1_range_ptr_);
 
                if (
-                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
-                    range1(str1_r0,str1_r1,str1_base_ptr_->size())
+                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
+                    range1(str1_r0, str1_r1, str1_base_ptr_->size())
                   )
                {
                   const std::size_t size0    = range0.cache_size();
                   const std::size_t size1    = range1.cache_size();
                   const std::size_t max_size = std::min(size0,size1);
 
-                  char_t* s0 = const_cast<char_t*>(str0_base_ptr_->base() + str0_r0);
-                  char_t* s1 = const_cast<char_t*>(str1_base_ptr_->base() + str1_r0);
+                  char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
+                  char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
 
                   loop_unroll::details lud(max_size);
-                  const char_t* upper_bound = s0 + lud.upper_bound;
+                  char_cptr upper_bound = s0 + lud.upper_bound;
 
                   while (s0 < upper_bound)
                   {
@@ -8220,8 +8821,8 @@
                   exprtk_disable_fallthrough_begin
                   switch (lud.remainder)
                   {
-                     #define case_stmt(N)                      \
-                     case N : { std::swap(s0[i],s1[i]); ++i; } \
+                     #define case_stmt(N)                       \
+                     case N : { std::swap(s0[i], s1[i]); ++i; } \
 
                      #ifndef exprtk_disable_superscalar_unroll
                      case_stmt(15) case_stmt(14)
@@ -8299,38 +8900,32 @@
       {
       public:
 
-         typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
+         typedef expression_node <T>*      expression_ptr;
+         typedef string_base_node<T>*        str_base_ptr;
+         typedef std::pair<expression_ptr,bool>  branch_t;
 
-         string_size_node(expression_ptr brnch)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_)),
-           str_base_ptr_(0)
+
+         explicit string_size_node(expression_ptr branch)
+         : str_base_ptr_(0)
          {
-            if (is_generally_string_node(branch_))
+            construct_branch_pair(branch_, branch);
+
+            if (is_generally_string_node(branch_.first))
             {
-               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
 
                if (0 == str_base_ptr_)
                   return;
             }
          }
 
-        ~string_size_node()
-         {
-            if (branch_ && branch_deletable_)
-            {
-               destroy_node(branch_);
-            }
-         }
-
          inline T value() const
          {
             T result = std::numeric_limits<T>::quiet_NaN();
 
             if (str_base_ptr_)
             {
-               branch_->value();
+               branch_.first->value();
                result = T(str_base_ptr_->size());
             }
 
@@ -8342,22 +8937,31 @@
             return expression_node<T>::e_stringsize;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
+         }
+
       private:
 
-         expression_ptr           branch_;
-         const bool     branch_deletable_;
-         str_base_ptr       str_base_ptr_;
+         branch_t           branch_;
+         str_base_ptr str_base_ptr_;
       };
 
       struct asn_assignment
       {
-         static inline void execute(std::string& s, const char_t* data, const std::size_t size)
+         static inline void execute(std::string& s, char_cptr data, const std::size_t size)
          { s.assign(data,size); }
       };
 
       struct asn_addassignment
       {
-         static inline void execute(std::string& s, const char_t* data, const std::size_t size)
+         static inline void execute(std::string& s, char_cptr data, const std::size_t size)
          { s.append(data,size); }
       };
 
@@ -8400,12 +9004,12 @@
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str1_range_ptr_ = &(range_ptr->range_ref());
+               str1_range_ptr_ = &(range->range_ref());
             }
 
             initialised_ = str0_base_ptr_  &&
@@ -8418,12 +9022,15 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[1].first->value();
 
                std::size_t r0 = 0;
                std::size_t r1 = 0;
 
-               range_t& range = (*str1_range_ptr_);
+               const range_t& range = (*str1_range_ptr_);
 
                if (range(r0, r1, str1_base_ptr_->size()))
                {
@@ -8443,7 +9050,7 @@
             return str0_node_ptr_->str();
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
            return str0_node_ptr_->base();
          }
@@ -8484,37 +9091,38 @@
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
-         typedef stringvar_node  <T>* strvar_node_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef expression_node  <T>*   expression_ptr;
+         typedef stringvar_node   <T>*  strvar_node_ptr;
+         typedef string_range_node<T>* str_rng_node_ptr;
+         typedef string_base_node <T>*     str_base_ptr;
+         typedef range_pack       <T>           range_t;
+         typedef range_t*                     range_ptr;
+         typedef range_interface<T>            irange_t;
+         typedef irange_t*                   irange_ptr;
 
          assignment_string_range_node(const operator_type& opr,
                                       expression_ptr branch0,
                                       expression_ptr branch1)
          : binary_node<T>(opr, branch0, branch1),
            initialised_(false),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_node_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0)
+           str0_base_ptr_     (0),
+           str1_base_ptr_     (0),
+           str0_rng_node_ptr_ (0),
+           str0_range_ptr_    (0),
+           str1_range_ptr_    (0)
          {
             if (is_string_range_node(binary_node<T>::branch_[0].first))
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+               str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first);
 
                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str0_range_ptr_ = &(range_ptr->range_ref());
+               str0_range_ptr_ = &(range->range_ref());
             }
 
             if (is_generally_string_node(binary_node<T>::branch_[1].first))
@@ -8524,25 +9132,28 @@
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str1_range_ptr_ = &(range_ptr->range_ref());
+               str1_range_ptr_ = &(range->range_ref());
             }
 
-            initialised_ = str0_base_ptr_  &&
-                           str1_base_ptr_  &&
-                           str0_node_ptr_  &&
-                           str0_range_ptr_ &&
-                           str1_range_ptr_ ;
+            initialised_ = str0_base_ptr_     &&
+                           str1_base_ptr_     &&
+                           str0_rng_node_ptr_ &&
+                           str0_range_ptr_    &&
+                           str1_range_ptr_    ;
          }
 
          inline T value() const
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
@@ -8552,19 +9163,19 @@
                std::size_t s1_r0 = 0;
                std::size_t s1_r1 = 0;
 
-               range_t& range0 = (*str0_range_ptr_);
-               range_t& range1 = (*str1_range_ptr_);
+               const range_t& range0 = (*str0_range_ptr_);
+               const range_t& range1 = (*str1_range_ptr_);
 
                if (
                     range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
                     range1(s1_r0, s1_r1, str1_base_ptr_->size())
                   )
                {
-                  std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;
+                  const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
 
                   std::copy(str1_base_ptr_->base() + s1_r0,
                             str1_base_ptr_->base() + s1_r0 + size,
-                            const_cast<char_t*>(base() + s0_r0));
+                            const_cast<char_ptr>(base() + s0_r0));
                }
             }
 
@@ -8573,27 +9184,27 @@
 
          std::string str() const
          {
-            return str0_node_ptr_->str();
+            return str0_base_ptr_->str();
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
-           return str0_node_ptr_->base();
+            return str0_base_ptr_->base();
          }
 
          std::size_t size() const
          {
-            return str0_node_ptr_->size();
+            return str0_base_ptr_->size();
          }
 
          range_t& range_ref()
          {
-            return str0_node_ptr_->range_ref();
+            return str0_rng_node_ptr_->range_ref();
          }
 
          const range_t& range_ref() const
          {
-            return str0_node_ptr_->range_ref();
+            return str0_rng_node_ptr_->range_ref();
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -8603,12 +9214,12 @@
 
       private:
 
-         bool            initialised_;
-         str_base_ptr    str0_base_ptr_;
-         str_base_ptr    str1_base_ptr_;
-         strvar_node_ptr str0_node_ptr_;
-         range_ptr       str0_range_ptr_;
-         range_ptr       str1_range_ptr_;
+         bool             initialised_;
+         str_base_ptr     str0_base_ptr_;
+         str_base_ptr     str1_base_ptr_;
+         str_rng_node_ptr str0_rng_node_ptr_;
+         range_ptr        str0_range_ptr_;
+         range_ptr        str1_range_ptr_;
       };
 
       template <typename T>
@@ -8625,16 +9236,16 @@
          typedef range_interface<T>         irange_t;
          typedef irange_t*                irange_ptr;
 
-         conditional_string_node(expression_ptr test,
+         conditional_string_node(expression_ptr condition,
                                  expression_ptr consequent,
                                  expression_ptr alternative)
-         : trinary_node<T>(details::e_default,consequent,alternative,test),
+         : trinary_node<T>(details::e_default,consequent,alternative,condition),
            initialised_(false),
            str0_base_ptr_ (0),
            str1_base_ptr_ (0),
            str0_range_ptr_(0),
            str1_range_ptr_(0),
-           test_              (test),
+           condition_    (condition),
            consequent_  (consequent),
            alternative_(alternative)
          {
@@ -8681,16 +9292,20 @@
          {
             if (initialised_)
             {
+               assert(condition_  );
+               assert(consequent_ );
+               assert(alternative_);
+
                std::size_t r0 = 0;
                std::size_t r1 = 0;
 
-               if (is_true(test_))
+               if (is_true(condition_))
                {
                   consequent_->value();
 
-                  range_t& range = str0_range_ptr_->range_ref();
+                  const range_t& range = str0_range_ptr_->range_ref();
 
-                  if (range(r0,r1,str0_base_ptr_->size()))
+                  if (range(r0, r1, str0_base_ptr_->size()))
                   {
                      const std::size_t size = (r1 - r0) + 1;
 
@@ -8706,9 +9321,9 @@
                {
                   alternative_->value();
 
-                  range_t& range = str1_range_ptr_->range_ref();
+                  const range_t& range = str1_range_ptr_->range_ref();
 
-                  if (range(r0,r1,str1_base_ptr_->size()))
+                  if (range(r0, r1, str1_base_ptr_->size()))
                   {
                      const std::size_t size = (r1 - r0) + 1;
 
@@ -8730,7 +9345,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &value_[0];
          }
@@ -8765,7 +9380,7 @@
          mutable range_t     range_;
          mutable std::string value_;
 
-         expression_ptr test_;
+         expression_ptr condition_;
          expression_ptr consequent_;
          expression_ptr alternative_;
       };
@@ -8784,13 +9399,13 @@
          typedef range_interface<T>         irange_t;
          typedef irange_t*                irange_ptr;
 
-         cons_conditional_str_node(expression_ptr test,
+         cons_conditional_str_node(expression_ptr condition,
                                    expression_ptr consequent)
-         : binary_node<T>(details::e_default, consequent, test),
+         : binary_node<T>(details::e_default, consequent, condition),
            initialised_(false),
            str0_base_ptr_ (0),
            str0_range_ptr_(0),
-           test_      (test),
+           condition_ (condition),
            consequent_(consequent)
          {
             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
@@ -8819,16 +9434,19 @@
          {
             if (initialised_)
             {
-               if (is_true(test_))
+               assert(condition_ );
+               assert(consequent_);
+
+               if (is_true(condition_))
                {
                   consequent_->value();
 
-                  range_t& range = str0_range_ptr_->range_ref();
+                  const range_t& range = str0_range_ptr_->range_ref();
 
                   std::size_t r0 = 0;
                   std::size_t r1 = 0;
 
-                  if (range(r0,r1,str0_base_ptr_->size()))
+                  if (range(r0, r1, str0_base_ptr_->size()))
                   {
                      const std::size_t size = (r1 - r0) + 1;
 
@@ -8850,7 +9468,7 @@
             return value_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return &value_[0];
          }
@@ -8883,7 +9501,7 @@
          mutable range_t     range_;
          mutable std::string value_;
 
-         expression_ptr test_;
+         expression_ptr condition_;
          expression_ptr consequent_;
       };
 
@@ -8894,33 +9512,34 @@
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef expression_node <T>*     expression_ptr;
+         typedef string_base_node<T>*       str_base_ptr;
+         typedef range_pack      <T>             range_t;
+         typedef range_t*                      range_ptr;
+         typedef range_interface<T>             irange_t;
+         typedef irange_t*                    irange_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
-         : final_node_(arg_list.back()),
-           final_deletable_(branch_deletable(final_node_)),
-           initialised_(false),
+                   template <typename, typename> class Sequence>
+         explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         : initialised_(false),
            str_base_ptr_ (0),
            str_range_ptr_(0)
          {
-            if (0 == final_node_)
+            construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
+
+            if (0 == final_node_.first)
                return;
-            else if (!is_generally_string_node(final_node_))
+            else if (!is_generally_string_node(final_node_.first))
                return;
 
-            str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
+            str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
 
             if (0 == str_base_ptr_)
                return;
 
-            str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
+            str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
 
             if (0 == str_range_ptr_)
                return;
@@ -8932,41 +9551,22 @@
                const std::size_t arg_list_size = arg_list.size() - 1;
 
                arg_list_.resize(arg_list_size);
-               delete_branch_.resize(arg_list_size);
 
                for (std::size_t i = 0; i < arg_list_size; ++i)
                {
                   if (arg_list[i])
                   {
-                          arg_list_[i] = arg_list[i];
-                     delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+                     construct_branch_pair(arg_list_[i], arg_list[i]);
                   }
                   else
                   {
                      arg_list_.clear();
-                     delete_branch_.clear();
                      return;
                   }
                }
             }
          }
 
-        ~str_vararg_node()
-         {
-            if (final_node_ && final_deletable_)
-            {
-               destroy_node(final_node_);
-            }
-
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
-            {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  destroy_node(arg_list_[i]);
-               }
-            }
-         }
-
          inline T value() const
          {
             if (!arg_list_.empty())
@@ -8974,7 +9574,7 @@
                VarArgFunction::process(arg_list_);
             }
 
-            final_node_->value();
+            final_node_.first->value();
 
             return std::numeric_limits<T>::quiet_NaN();
          }
@@ -8984,7 +9584,7 @@
             return str_base_ptr_->str();
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
             return str_base_ptr_->base();
          }
@@ -9009,15 +9609,26 @@
             return expression_node<T>::e_stringvararg;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(final_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(arg_list_  , node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return std::max(
+               expression_node<T>::ndb_t::compute_node_depth(final_node_),
+               expression_node<T>::ndb_t::compute_node_depth(arg_list_  ));
+         }
+
       private:
 
-         expression_ptr final_node_;
-         bool           final_deletable_;
-         bool           initialised_;
-         str_base_ptr   str_base_ptr_;
-         irange_ptr     str_range_ptr_;
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
+         bool                  initialised_;
+         branch_t              final_node_;
+         str_base_ptr          str_base_ptr_;
+         irange_ptr            str_range_ptr_;
+         std::vector<branch_t> arg_list_;
       };
       #endif
 
@@ -9050,14 +9661,14 @@
       template <typename T>                              \
       struct sf##NN##_op : public sf_base<T>             \
       {                                                  \
-         typedef typename sf_base<T>::Type Type;         \
+         typedef typename sf_base<T>::Type const Type;   \
          static inline T process(Type x, Type y, Type z) \
          {                                               \
             return (OP0);                                \
          }                                               \
          static inline std::string id()                  \
          {                                               \
-            return OP1;                                  \
+            return (OP1);                                \
          }                                               \
       };                                                 \
 
@@ -9114,12 +9725,15 @@
       template <typename T>                                      \
       struct sf##NN##_op : public sf_base<T>                     \
       {                                                          \
-         typedef typename sf_base<T>::Type Type;                 \
+         typedef typename sf_base<T>::Type const Type;           \
          static inline T process(Type x, Type y, Type z, Type w) \
          {                                                       \
             return (OP0);                                        \
          }                                                       \
-         static inline std::string id() { return OP1; }          \
+         static inline std::string id()                          \
+         {                                                       \
+            return (OP1);                                        \
+         }                                                       \
       };                                                         \
 
       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
@@ -9258,6 +9872,10 @@
 
          inline T value() const
          {
+            assert(trinary_node<T>::branch_[0].first);
+            assert(trinary_node<T>::branch_[1].first);
+            assert(trinary_node<T>::branch_[2].first);
+
             const T x = trinary_node<T>::branch_[0].first->value();
             const T y = trinary_node<T>::branch_[1].first->value();
             const T z = trinary_node<T>::branch_[2].first->value();
@@ -9283,6 +9901,11 @@
 
          inline T value() const
          {
+            assert(quaternary_node<T>::branch_[0].first);
+            assert(quaternary_node<T>::branch_[1].first);
+            assert(quaternary_node<T>::branch_[2].first);
+            assert(quaternary_node<T>::branch_[3].first);
+
             const T x = quaternary_node<T>::branch_[0].first->value();
             const T y = quaternary_node<T>::branch_[1].first->value();
             const T z = quaternary_node<T>::branch_[2].first->value();
@@ -9366,47 +9989,31 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
          {
-            arg_list_     .resize(arg_list.size());
-            delete_branch_.resize(arg_list.size());
+            arg_list_.resize(arg_list.size());
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
                if (arg_list[i])
                {
-                       arg_list_[i] = arg_list[i];
-                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+                  construct_branch_pair(arg_list_[i],arg_list[i]);
                }
                else
                {
                   arg_list_.clear();
-                  delete_branch_.clear();
                   return;
                }
             }
          }
 
-        ~vararg_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
-            {
-               if (arg_list_[i] && delete_branch_[i])
-               {
-                  destroy_node(arg_list_[i]);
-               }
-            }
-         }
-
          inline T value() const
          {
-            if (!arg_list_.empty())
-               return VarArgFunction::process(arg_list_);
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return VarArgFunction::process(arg_list_);
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -9414,10 +10021,19 @@
             return expression_node<T>::e_vararg;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
+         }
+
       private:
 
-         std::vector<expression_ptr> arg_list_;
-         std::vector<unsigned char> delete_branch_;
+         std::vector<branch_t> arg_list_;
       };
 
       template <typename T, typename VarArgFunction>
@@ -9428,8 +10044,8 @@
          typedef expression_node<T>* expression_ptr;
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
          {
             arg_list_.resize(arg_list.size());
 
@@ -9472,33 +10088,29 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         vectorize_node(const expression_ptr v)
-         : ivec_ptr_(0),
-           v_(v),
-           v_deletable_(branch_deletable(v_))
+         explicit vectorize_node(const expression_ptr v)
+         : ivec_ptr_(0)
          {
-            if (is_ivector_node(v))
+            construct_branch_pair(v_, v);
+
+            if (is_ivector_node(v_.first))
             {
-               ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
+               ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
             }
             else
                ivec_ptr_ = 0;
          }
 
-        ~vectorize_node()
-         {
-            if (v_ && v_deletable_)
-            {
-               destroy_node(v_);
-            }
-         }
-
          inline T value() const
          {
             if (ivec_ptr_)
             {
-               v_->value();
+               assert(v_.first);
+
+               v_.first->value();
+
                return VecFunction::process(ivec_ptr_);
             }
             else
@@ -9510,11 +10122,20 @@
             return expression_node<T>::e_vecfunc;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(v_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(v_);
+         }
+
       private:
 
          vector_interface<T>* ivec_ptr_;
-         expression_ptr              v_;
-         const bool        v_deletable_;
+         branch_t                    v_;
       };
 
       template <typename T>
@@ -9540,6 +10161,8 @@
          {
             if (var_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& result = var_node_ptr_->ref();
 
                result = binary_node<T>::branch_[1].first->value();
@@ -9578,6 +10201,8 @@
          {
             if (vec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& result = vec_node_ptr_->ref();
 
                result = binary_node<T>::branch_[1].first->value();
@@ -9616,6 +10241,8 @@
          {
             if (rbvec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& result = rbvec_node_ptr_->ref();
 
                result = binary_node<T>::branch_[1].first->value();
@@ -9654,6 +10281,8 @@
          {
             if (rbvec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& result = rbvec_node_ptr_->ref();
 
                result = binary_node<T>::branch_[1].first->value();
@@ -9696,6 +10325,8 @@
          {
             if (vec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                const T v = binary_node<T>::branch_[1].first->value();
 
                T* vec = vds().data();
@@ -9705,8 +10336,8 @@
 
                while (vec < upper_bound)
                {
-                 #define exprtk_loop(N) \
-                  vec[N] = v;           \
+                  #define exprtk_loop(N) \
+                  vec[N] = v;            \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -9841,6 +10472,8 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[1].first->value();
 
                if (src_is_ivec_)
@@ -9962,6 +10595,8 @@
          {
             if (var_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& v = var_node_ptr_->ref();
                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
 
@@ -9999,6 +10634,8 @@
          {
             if (vec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& v = vec_node_ptr_->ref();
                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
 
@@ -10036,6 +10673,8 @@
          {
             if (rbvec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& v = rbvec_node_ptr_->ref();
                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
 
@@ -10073,6 +10712,8 @@
          {
             if (rbvec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                T& v = rbvec_node_ptr_->ref();
                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
 
@@ -10114,6 +10755,8 @@
          {
             if (vec_node_ptr_)
             {
+               assert(binary_node<T>::branch_[1].first);
+
                const T v = binary_node<T>::branch_[1].first->value();
 
                T* vec = vds().data();
@@ -10259,19 +10902,22 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vec1_node_ptr_->vds().data();
+                     T* vec0 = vec0_node_ptr_->vds().data();
+               const T* vec1 = vec1_node_ptr_->vds().data();
 
                loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
                {
-                  #define exprtk_loop(N)                         \
-                  vec0[N] = Operation::process(vec0[N],vec1[N]); \
+                  #define exprtk_loop(N)                          \
+                  vec0[N] = Operation::process(vec0[N], vec1[N]); \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -10293,8 +10939,8 @@
                exprtk_disable_fallthrough_begin
                switch (lud.remainder)
                {
-                  #define case_stmt(N)                                             \
-                  case N : { vec0[i] = Operation::process(vec0[i],vec1[i]); ++i; } \
+                  #define case_stmt(N)                                              \
+                  case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
 
                   #ifndef exprtk_disable_superscalar_unroll
                   case_stmt(15) case_stmt(14)
@@ -10444,20 +11090,23 @@
          {
             if (initialised_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                binary_node<T>::branch_[0].first->value();
                binary_node<T>::branch_[1].first->value();
 
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vec1_node_ptr_->vds().data();
-               T* vec2 = vds().data();
+               const T* vec0 = vec0_node_ptr_->vds().data();
+               const T* vec1 = vec1_node_ptr_->vds().data();
+                     T* vec2 = vds().data();
 
                loop_unroll::details lud(size());
                const T* upper_bound = vec2 + lud.upper_bound;
 
                while (vec2 < upper_bound)
                {
-                  #define exprtk_loop(N)                         \
-                  vec2[N] = Operation::process(vec0[N],vec1[N]); \
+                  #define exprtk_loop(N)                          \
+                  vec2[N] = Operation::process(vec0[N], vec1[N]); \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -10480,8 +11129,8 @@
                exprtk_disable_fallthrough_begin
                switch (lud.remainder)
                {
-                  #define case_stmt(N)                                             \
-                  case N : { vec2[i] = Operation::process(vec0[i],vec1[i]); ++i; } \
+                  #define case_stmt(N)                                              \
+                  case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
 
                   #ifndef exprtk_disable_superscalar_unroll
                   case_stmt(15) case_stmt(14)
@@ -10603,19 +11252,22 @@
          {
             if (vec0_node_ptr_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                            binary_node<T>::branch_[0].first->value();
                const T v = binary_node<T>::branch_[1].first->value();
 
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vds().data();
+               const T* vec0 = vec0_node_ptr_->vds().data();
+                     T* vec1 = vds().data();
 
                loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
                {
-                  #define exprtk_loop(N)                   \
-                  vec1[N] = Operation::process(vec0[N],v); \
+                  #define exprtk_loop(N)                    \
+                  vec1[N] = Operation::process(vec0[N], v); \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -10637,8 +11289,8 @@
                exprtk_disable_fallthrough_begin
                switch (lud.remainder)
                {
-                  #define case_stmt(N)                                       \
-                  case N : { vec1[i] = Operation::process(vec0[i],v); ++i; } \
+                  #define case_stmt(N)                                        \
+                  case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
 
                   #ifndef exprtk_disable_superscalar_unroll
                   case_stmt(15) case_stmt(14)
@@ -10758,19 +11410,22 @@
          {
             if (vec1_node_ptr_)
             {
+               assert(binary_node<T>::branch_[0].first);
+               assert(binary_node<T>::branch_[1].first);
+
                const T v = binary_node<T>::branch_[0].first->value();
                            binary_node<T>::branch_[1].first->value();
 
-               T* vec0 = vds().data();
-               T* vec1 = vec1_node_ptr_->vds().data();
+                     T* vec0 = vds().data();
+               const T* vec1 = vec1_node_ptr_->vds().data();
 
                loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
                {
-                  #define exprtk_loop(N)                   \
-                  vec0[N] = Operation::process(v,vec1[N]); \
+                  #define exprtk_loop(N)                    \
+                  vec0[N] = Operation::process(v, vec1[N]); \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -10792,8 +11447,8 @@
                exprtk_disable_fallthrough_begin
                switch (lud.remainder)
                {
-                  #define case_stmt(N)                                       \
-                  case N : { vec0[i] = Operation::process(v,vec1[i]); ++i; } \
+                  #define case_stmt(N)                                        \
+                  case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
 
                   #ifndef exprtk_disable_superscalar_unroll
                   case_stmt(15) case_stmt(14)
@@ -10874,15 +11529,15 @@
          {
             bool vec0_is_ivec = false;
 
-            if (is_vector_node(unary_node<T>::branch_))
+            if (is_vector_node(unary_node<T>::branch_.first))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first);
             }
-            else if (is_ivector_node(unary_node<T>::branch_))
+            else if (is_ivector_node(unary_node<T>::branch_.first))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first)))
                {
                   vec0_node_ptr_ = vi->vec();
                   vec0_is_ivec   = true;
@@ -10909,12 +11564,14 @@
 
          inline T value() const
          {
-            unary_node<T>::branch_->value();
+            assert(unary_node<T>::branch_.first);
+
+            unary_node<T>::branch_.first->value();
 
             if (vec0_node_ptr_)
             {
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vds().data();
+               const T* vec0 = vec0_node_ptr_->vds().data();
+                     T* vec1 = vds().data();
 
                loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
@@ -11022,6 +11679,9 @@
 
          inline T value() const
          {
+            assert(binary_node<T>::branch_[0].first);
+            assert(binary_node<T>::branch_[1].first);
+
             return (
                      std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[0].first->value()) &&
@@ -11046,6 +11706,9 @@
 
          inline T value() const
          {
+            assert(binary_node<T>::branch_[0].first);
+            assert(binary_node<T>::branch_[1].first);
+
             return (
                      std::not_equal_to<T>()
                         (T(0),binary_node<T>::branch_[0].first->value()) ||
@@ -11065,16 +11728,11 @@
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef IFunction ifunction;
 
-         function_N_node(ifunction* func)
+         explicit function_N_node(ifunction* func)
          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
            parameter_count_(func->param_count)
          {}
 
-        ~function_N_node()
-         {
-            cleanup_branches::execute<T,N>(branch_);
-         }
-
          template <std::size_t NumBranches>
          bool init_branches(expression_ptr (&b)[NumBranches])
          {
@@ -11341,6 +11999,16 @@
             return expression_node<T>::e_function;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
+         }
+
       private:
 
          ifunction*  function_;
@@ -11356,7 +12024,7 @@
          typedef expression_node<T>* expression_ptr;
          typedef IFunction ifunction;
 
-         function_N_node(ifunction* func)
+         explicit function_N_node(ifunction* func)
          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
          {}
 
@@ -11398,17 +12066,6 @@
             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
          }
 
-        ~vararg_function_node()
-         {
-            for (std::size_t i = 0; i < arg_list_.size(); ++i)
-            {
-               if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
-               {
-                  destroy_node(arg_list_[i]);
-               }
-            }
-         }
-
          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
          {
             return this < (&fn);
@@ -11430,6 +12087,22 @@
             return expression_node<T>::e_vafunction;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
+               {
+                  node_delete_list.push_back(&arg_list_[i]);
+               }
+            }
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
+         }
+
       private:
 
          inline void populate_value_list() const
@@ -11465,15 +12138,23 @@
          typedef std::vector<type_store_t>         typestore_list_t;
          typedef std::vector<range_data_type_t>        range_list_t;
 
-         generic_function_node(const std::vector<expression_ptr>& arg_list,
-                               GenericFunction* func = (GenericFunction*)(0))
+         explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
+                                        GenericFunction* func = (GenericFunction*)(0))
          : function_(func),
            arg_list_(arg_list)
          {}
 
          virtual ~generic_function_node()
+         {}
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
          {
-            cleanup_branches::execute(branch_);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
          virtual bool init_branches()
@@ -11499,6 +12180,7 @@
                   ts.size = vi->size();
                   ts.data = vi->vds().data();
                   ts.type = type_store_t::e_vector;
+                  vi->vec()->vec_holder().set_ref(&ts.vec_data);
                }
                #ifndef exprtk_disable_string_capabilities
                else if (is_generally_string_node(arg_list_[i]))
@@ -11509,7 +12191,7 @@
                      return false;
 
                   ts.size = sbn->size();
-                  ts.data = reinterpret_cast<void*>(const_cast<char_t*>(sbn->base()));
+                  ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
                   ts.type = type_store_t::e_string;
 
                   range_list_[i].data      = ts.data;
@@ -11522,7 +12204,7 @@
                   if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
                      return false;
 
-                  range_t& rp = ri->range_ref();
+                  const range_t& rp = ri->range_ref();
 
                   if (
                        rp.const_range() &&
@@ -11530,7 +12212,7 @@
                      )
                   {
                      ts.size = rp.const_size();
-                     ts.data = static_cast<char_t*>(ts.data) + rp.n0_c.second;
+                     ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
                      range_list_[i].range = reinterpret_cast<range_t*>(0);
                   }
                   else
@@ -11601,21 +12283,21 @@
 
                if (rdt.range)
                {
-                  range_t&    rp = (*rdt.range);
-                  std::size_t r0 = 0;
-                  std::size_t r1 = 0;
+                  const range_t& rp = (*rdt.range);
+                  std::size_t r0    = 0;
+                  std::size_t r1    = 0;
 
-                  if (rp(r0,r1,rdt.size))
+                  if (rp(r0, r1, rdt.size))
                   {
                      type_store_t& ts = typestore_list_[i];
 
                      ts.size = rp.cache_size();
                      #ifndef exprtk_disable_string_capabilities
                      if (ts.type == type_store_t::e_string)
-                        ts.data = const_cast<char_t*>(rdt.str_node->base()) + rp.cache.first;
+                        ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
                      else
                      #endif
-                        ts.data = static_cast<char_t*>(rdt.data) + (rp.cache.first * rdt.type_size);
+                        ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
                   }
                   else
                      return false;
@@ -11664,16 +12346,17 @@
 
          inline T value() const
          {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
             if (gen_function_t::function_)
             {
                if (gen_function_t::populate_value_list())
                {
                   typedef typename StringFunction::parameter_list_t parameter_list_t;
 
-                  result = (*gen_function_t::function_)(ret_string_,
-                                                        parameter_list_t(gen_function_t::typestore_list_));
+                  const T result = (*gen_function_t::function_)
+                                      (
+                                        ret_string_,
+                                        parameter_list_t(gen_function_t::typestore_list_)
+                                      );
 
                   range_.n1_c.second  = ret_string_.size() - 1;
                   range_.cache.second = range_.n1_c.second;
@@ -11682,7 +12365,7 @@
                }
             }
 
-            return result;
+            return std::numeric_limits<T>::quiet_NaN();
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -11695,7 +12378,7 @@
             return ret_string_;
          }
 
-         const char_t* base() const
+         char_cptr base() const
          {
            return &ret_string_[0];
          }
@@ -11739,20 +12422,21 @@
 
          inline T value() const
          {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
             if (gen_function_t::function_)
             {
                if (gen_function_t::populate_value_list())
                {
                   typedef typename GenericFunction::parameter_list_t parameter_list_t;
 
-                  return (*gen_function_t::function_)(param_seq_index_,
-                                                      parameter_list_t(gen_function_t::typestore_list_));
+                  return (*gen_function_t::function_)
+                            (
+                              param_seq_index_,
+                              parameter_list_t(gen_function_t::typestore_list_)
+                            );
                }
             }
 
-            return result;
+            return std::numeric_limits<T>::quiet_NaN();
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -11783,17 +12467,18 @@
 
          inline T value() const
          {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
             if (str_function_t::function_)
             {
                if (str_function_t::populate_value_list())
                {
                   typedef typename StringFunction::parameter_list_t parameter_list_t;
 
-                  result = (*str_function_t::function_)(param_seq_index_,
-                                                        str_function_t::ret_string_,
-                                                        parameter_list_t(str_function_t::typestore_list_));
+                  const T result = (*str_function_t::function_)
+                                      (
+                                        param_seq_index_,
+                                        str_function_t::ret_string_,
+                                        parameter_list_t(str_function_t::typestore_list_)
+                                      );
 
                   str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;
                   str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
@@ -11802,7 +12487,7 @@
                }
             }
 
-            return result;
+            return std::numeric_limits<T>::quiet_NaN();
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -11888,30 +12573,25 @@
 
          typedef expression_node<T>* expression_ptr;
          typedef results_context<T>  results_context_t;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
          return_envelope_node(expression_ptr body, results_context_t& rc)
          : results_context_(&rc  ),
-           return_invoked_ (false),
-           body_           (body ),
-           body_deletable_ (branch_deletable(body_))
-         {}
-
-        ~return_envelope_node()
+           return_invoked_ (false)
          {
-            if (body_ && body_deletable_)
-            {
-               destroy_node(body_);
-            }
+            construct_branch_pair(body_, body);
          }
 
          inline T value() const
          {
+            assert(body_.first);
+
             try
             {
                return_invoked_ = false;
                results_context_->clear();
 
-               return body_->value();
+               return body_.first->value();
             }
             catch(const return_exception&)
             {
@@ -11930,12 +12610,21 @@
             return &return_invoked_;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(body_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(body_);
+         }
+
       private:
 
          results_context_t* results_context_;
-         mutable bool       return_invoked_;
-         expression_ptr     body_;
-         const bool         body_deletable_;
+         mutable bool        return_invoked_;
+         branch_t                      body_;
       };
       #endif
 
@@ -12007,20 +12696,21 @@
       template <typename T>
       struct opr_base
       {
-         typedef typename details::functor_t<T>::Type Type;
+         typedef typename details::functor_t<T>::Type    Type;
          typedef typename details::functor_t<T>::RefType RefType;
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::qfunc_t quaternary_functor_t;
-         typedef typename functor_t::tfunc_t    trinary_functor_t;
-         typedef typename functor_t::bfunc_t     binary_functor_t;
-         typedef typename functor_t::ufunc_t      unary_functor_t;
+         typedef typename details::functor_t<T>          functor_t;
+         typedef typename functor_t::qfunc_t  quaternary_functor_t;
+         typedef typename functor_t::tfunc_t     trinary_functor_t;
+         typedef typename functor_t::bfunc_t      binary_functor_t;
+         typedef typename functor_t::ufunc_t       unary_functor_t;
       };
 
       template <typename T>
       struct add_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return t1 + t2; }
          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
          static inline void assign(RefType t1, Type t2) { t1 += t2; }
@@ -12031,8 +12721,9 @@
       template <typename T>
       struct mul_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return t1 * t2; }
          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
          static inline void assign(RefType t1, Type t2) { t1 *= t2; }
@@ -12043,8 +12734,9 @@
       template <typename T>
       struct sub_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return t1 - t2; }
          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
          static inline void assign(RefType t1, Type t2) { t1 -= t2; }
@@ -12055,8 +12747,9 @@
       template <typename T>
       struct div_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return t1 / t2; }
          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
          static inline void assign(RefType t1, Type t2) { t1 /= t2; }
@@ -12067,8 +12760,9 @@
       template <typename T>
       struct mod_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
          static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
@@ -12078,8 +12772,9 @@
       template <typename T>
       struct pow_op : public opr_base<T>
       {
-         typedef typename opr_base<T>::Type Type;
+         typedef typename opr_base<T>::Type    Type;
          typedef typename opr_base<T>::RefType RefType;
+
          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
          static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
@@ -12090,6 +12785,7 @@
       struct lt_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
@@ -12100,6 +12796,7 @@
       struct lte_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
@@ -12110,6 +12807,7 @@
       struct gt_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
@@ -12120,6 +12818,7 @@
       struct gte_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
@@ -12140,6 +12839,7 @@
       struct equal_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
@@ -12150,6 +12850,7 @@
       struct ne_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
@@ -12160,6 +12861,7 @@
       struct and_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
          static inline details::operator_type operation() { return details::e_and; }
@@ -12169,6 +12871,7 @@
       struct nand_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
          static inline details::operator_type operation() { return details::e_nand; }
@@ -12178,6 +12881,7 @@
       struct or_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
          static inline details::operator_type operation() { return details::e_or; }
@@ -12187,6 +12891,7 @@
       struct nor_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
          static inline details::operator_type operation() { return details::e_nor; }
@@ -12196,6 +12901,7 @@
       struct xor_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
          static inline details::operator_type operation() { return details::e_xor; }
@@ -12205,6 +12911,7 @@
       struct xnor_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
          static inline details::operator_type operation() { return details::e_xnor; }
@@ -12214,6 +12921,7 @@
       struct in_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
@@ -12224,6 +12932,7 @@
       struct like_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
@@ -12234,6 +12943,7 @@
       struct ilike_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
@@ -12244,6 +12954,7 @@
       struct inrange_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
+
          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
          {
@@ -12260,19 +12971,31 @@
       }
 
       template <typename T>
-      inline T value(T* t)
+      inline T value(std::pair<details::expression_node<T>*,bool> n)
+      {
+         return n.first->value();
+      }
+
+      template <typename T>
+      inline T value(const T* t)
       {
          return (*t);
       }
 
       template <typename T>
+      inline T value(const T& t)
+      {
+         return t;
+      }
+
+      template <typename T>
       struct vararg_add_op : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12313,14 +13036,14 @@
          static inline T process_3(const Sequence& arg_list)
          {
             return value(arg_list[0]) + value(arg_list[1]) +
-                   value(arg_list[2]);
+                   value(arg_list[2]) ;
          }
 
          template <typename Sequence>
          static inline T process_4(const Sequence& arg_list)
          {
             return value(arg_list[0]) + value(arg_list[1]) +
-                   value(arg_list[2]) + value(arg_list[3]);
+                   value(arg_list[2]) + value(arg_list[3]) ;
          }
 
          template <typename Sequence>
@@ -12328,7 +13051,7 @@
          {
             return value(arg_list[0]) + value(arg_list[1]) +
                    value(arg_list[2]) + value(arg_list[3]) +
-                   value(arg_list[4]);
+                   value(arg_list[4]) ;
          }
       };
 
@@ -12339,7 +13062,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12380,14 +13103,14 @@
          static inline T process_3(const Sequence& arg_list)
          {
             return value(arg_list[0]) * value(arg_list[1]) *
-                   value(arg_list[2]);
+                   value(arg_list[2]) ;
          }
 
          template <typename Sequence>
          static inline T process_4(const Sequence& arg_list)
          {
             return value(arg_list[0]) * value(arg_list[1]) *
-                   value(arg_list[2]) * value(arg_list[3]);
+                   value(arg_list[2]) * value(arg_list[3]) ;
          }
 
          template <typename Sequence>
@@ -12395,7 +13118,7 @@
          {
             return value(arg_list[0]) * value(arg_list[1]) *
                    value(arg_list[2]) * value(arg_list[3]) *
-                   value(arg_list[4]);
+                   value(arg_list[4]) ;
          }
       };
 
@@ -12406,7 +13129,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12462,7 +13185,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12512,16 +13235,16 @@
          static inline T process_4(const Sequence& arg_list)
          {
             return std::min<T>(
-                        std::min<T>(value(arg_list[0]),value(arg_list[1])),
-                        std::min<T>(value(arg_list[2]),value(arg_list[3])));
+                        std::min<T>(value(arg_list[0]), value(arg_list[1])),
+                        std::min<T>(value(arg_list[2]), value(arg_list[3])));
          }
 
          template <typename Sequence>
          static inline T process_5(const Sequence& arg_list)
          {
             return std::min<T>(
-                   std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),
-                               std::min<T>(value(arg_list[2]),value(arg_list[3]))),
+                   std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
+                               std::min<T>(value(arg_list[2]), value(arg_list[3]))),
                                value(arg_list[4]));
          }
       };
@@ -12533,7 +13256,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12583,16 +13306,16 @@
          static inline T process_4(const Sequence& arg_list)
          {
             return std::max<T>(
-                        std::max<T>(value(arg_list[0]),value(arg_list[1])),
-                        std::max<T>(value(arg_list[2]),value(arg_list[3])));
+                        std::max<T>(value(arg_list[0]), value(arg_list[1])),
+                        std::max<T>(value(arg_list[2]), value(arg_list[3])));
          }
 
          template <typename Sequence>
          static inline T process_5(const Sequence& arg_list)
          {
             return std::max<T>(
-                   std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),
-                               std::max<T>(value(arg_list[2]),value(arg_list[3]))),
+                   std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
+                               std::max<T>(value(arg_list[2]), value(arg_list[3]))),
                                value(arg_list[4]));
          }
       };
@@ -12604,7 +13327,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12618,7 +13341,7 @@
                          {
                             for (std::size_t i = 0; i < arg_list.size(); ++i)
                             {
-                               if (std::equal_to<T>()(T(0),value(arg_list[i])))
+                               if (std::equal_to<T>()(T(0), value(arg_list[i])))
                                   return T(0);
                             }
 
@@ -12631,15 +13354,15 @@
          static inline T process_1(const Sequence& arg_list)
          {
             return std::not_equal_to<T>()
-                      (T(0),value(arg_list[0])) ? T(1) : T(0);
+                      (T(0), value(arg_list[0])) ? T(1) : T(0);
          }
 
          template <typename Sequence>
          static inline T process_2(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[1]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[1]))
                    ) ? T(1) : T(0);
          }
 
@@ -12647,9 +13370,9 @@
          static inline T process_3(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[2]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[2]))
                    ) ? T(1) : T(0);
          }
 
@@ -12657,10 +13380,10 @@
          static inline T process_4(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[3]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[3]))
                    ) ? T(1) : T(0);
          }
 
@@ -12668,11 +13391,11 @@
          static inline T process_5(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[3])) &&
-                     std::not_equal_to<T>()(T(0),value(arg_list[4]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
+                     std::not_equal_to<T>()(T(0), value(arg_list[4]))
                    ) ? T(1) : T(0);
          }
       };
@@ -12684,7 +13407,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -12698,7 +13421,7 @@
                          {
                             for (std::size_t i = 0; i < arg_list.size(); ++i)
                             {
-                               if (std::not_equal_to<T>()(T(0),value(arg_list[i])))
+                               if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
                                   return T(1);
                             }
 
@@ -12711,15 +13434,15 @@
          static inline T process_1(const Sequence& arg_list)
          {
             return std::not_equal_to<T>()
-                      (T(0),value(arg_list[0])) ? T(1) : T(0);
+                      (T(0), value(arg_list[0])) ? T(1) : T(0);
          }
 
          template <typename Sequence>
          static inline T process_2(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[1]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[1]))
                    ) ? T(1) : T(0);
          }
 
@@ -12727,9 +13450,9 @@
          static inline T process_3(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[2]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[2]))
                    ) ? T(1) : T(0);
          }
 
@@ -12737,10 +13460,10 @@
          static inline T process_4(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[3]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[3]))
                    ) ? T(1) : T(0);
          }
 
@@ -12748,11 +13471,11 @@
          static inline T process_5(const Sequence& arg_list)
          {
             return (
-                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[3])) ||
-                     std::not_equal_to<T>()(T(0),value(arg_list[4]))
+                     std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
+                     std::not_equal_to<T>()(T(0), value(arg_list[4]))
                    ) ? T(1) : T(0);
          }
       };
@@ -12764,7 +13487,7 @@
 
          template <typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          static inline T process(const Sequence<Type,Allocator>& arg_list)
          {
             switch (arg_list.size())
@@ -13096,7 +13819,7 @@
 
             for (std::size_t i = 1; i < vec_size; ++i)
             {
-               T v_i = vec[i];
+               const T v_i = vec[i];
 
                if (v_i < result)
                   result = v_i;
@@ -13120,7 +13843,7 @@
 
             for (std::size_t i = 1; i < vec_size; ++i)
             {
-               T v_i = vec[i];
+               const T v_i = vec[i];
 
                if (v_i > result)
                   result = v_i;
@@ -13211,8 +13934,8 @@
       {
       public:
 
-       virtual ~cob_base_node()
-       {}
+         virtual ~cob_base_node()
+         {}
 
          inline virtual operator_type operation() const
          {
@@ -13431,24 +14154,17 @@
       public:
 
          typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
          typedef Operation operation_t;
 
-         explicit unary_branch_node(expression_ptr brnch)
-         : branch_(brnch),
-           branch_deletable_(branch_deletable(branch_))
-         {}
-
-        ~unary_branch_node()
+         explicit unary_branch_node(expression_ptr branch)
          {
-            if (branch_ && branch_deletable_)
-            {
-               destroy_node(branch_);
-            }
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return Operation::process(branch_->value());
+            return Operation::process(branch_.first->value());
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -13463,12 +14179,22 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_;
+            return branch_.first;
          }
 
          inline void release()
          {
-            branch_deletable_ = false;
+            branch_.second = false;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
@@ -13476,8 +14202,7 @@
          unary_branch_node(unary_branch_node<T,Operation>&);
          unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
 
-         expression_ptr branch_;
-         bool           branch_deletable_;
+         branch_t branch_;
       };
 
       template <typename T> struct is_const                { enum {result = 0}; };
@@ -13664,15 +14389,15 @@
       template <typename T, typename T0, typename T1>                                                           \
       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
 
-      synthesis_node_type_define(const T0&,const T1&, e_vov)
-      synthesis_node_type_define(const T0&,const T1 , e_voc)
-      synthesis_node_type_define(const T0 ,const T1&, e_cov)
-      synthesis_node_type_define(      T0&,      T1&,e_none)
-      synthesis_node_type_define(const T0 ,const T1 ,e_none)
-      synthesis_node_type_define(      T0&,const T1 ,e_none)
-      synthesis_node_type_define(const T0 ,      T1&,e_none)
-      synthesis_node_type_define(const T0&,      T1&,e_none)
-      synthesis_node_type_define(      T0&,const T1&,e_none)
+      synthesis_node_type_define(const T0&, const T1&,  e_vov)
+      synthesis_node_type_define(const T0&, const T1 ,  e_voc)
+      synthesis_node_type_define(const T0 , const T1&,  e_cov)
+      synthesis_node_type_define(      T0&,       T1&, e_none)
+      synthesis_node_type_define(const T0 , const T1 , e_none)
+      synthesis_node_type_define(      T0&, const T1 , e_none)
+      synthesis_node_type_define(const T0 ,       T1&, e_none)
+      synthesis_node_type_define(const T0&,       T1&, e_none)
+      synthesis_node_type_define(      T0&, const T1&, e_none)
       #undef synthesis_node_type_define
 
       template <typename T, typename T0, typename T1, typename T2>
@@ -13686,15 +14411,15 @@
       template <typename T, typename T0, typename T1, typename T2>                                                     \
       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
 
-      synthesis_node_type_define(const T0&,const T1&,const T2&, e_vovov)
-      synthesis_node_type_define(const T0&,const T1&,const T2 , e_vovoc)
-      synthesis_node_type_define(const T0&,const T1 ,const T2&, e_vocov)
-      synthesis_node_type_define(const T0 ,const T1&,const T2&, e_covov)
-      synthesis_node_type_define(const T0 ,const T1&,const T2 , e_covoc)
-      synthesis_node_type_define(const T0 ,const T1 ,const T2 , e_none )
-      synthesis_node_type_define(const T0 ,const T1 ,const T2&, e_none )
-      synthesis_node_type_define(const T0&,const T1 ,const T2 , e_none )
-      synthesis_node_type_define(      T0&,      T1&,      T2&, e_none )
+      synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
+      synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
+      synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
+      synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
+      synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
+      synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
+      synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
+      synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
+      synthesis_node_type_define(      T0&,       T1&,       T2&, e_none )
       #undef synthesis_node_type_define
 
       template <typename T, typename T0, typename T1, typename T2, typename T3>
@@ -13708,22 +14433,22 @@
       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
 
-      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)
-      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)
-      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)
-      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)
-      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)
-      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)
-      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)
-      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)
-      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)
-      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none   )
-      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none   )
-      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none   )
-      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none   )
-      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none   )
-      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none   )
-      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3 ,e_none   )
+      synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
+      synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
+      synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
+      synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
+      synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
+      synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
+      synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
+      synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
+      synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
+      synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none   )
+      synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none   )
+      synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none   )
+      synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none   )
+      synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none   )
+      synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none   )
+      synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none   )
       #undef synthesis_node_type_define
 
       template <typename T, typename T0, typename T1>
@@ -13779,7 +14504,7 @@
                                                     bfunc_t p2)
          {
             return allocator
-                     .template allocate_type<node_type,T0,T1,bfunc_t&>
+                     .template allocate_type<node_type, T0, T1, bfunc_t&>
                         (p0, p1, p2);
          }
 
@@ -13825,7 +14550,7 @@
 
          inline T value() const
          {
-            return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
+            return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
          }
 
          inline T0 t0() const
@@ -13867,7 +14592,7 @@
          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
          {
             return allocator
-                      .template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>
+                      .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
                          (p0, p1, p2, p3, p4);
          }
 
@@ -13955,7 +14680,7 @@
 
          static inline std::string id()
          {
-            return process_mode_t::template id<T0,T1,T2,T3>();
+            return process_mode_t::template id<T0, T1, T2, T3>();
          }
 
          template <typename Allocator>
@@ -13964,7 +14689,7 @@
                                                     bfunc_t p4, bfunc_t p5, bfunc_t p6)
          {
             return allocator
-                      .template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>
+                      .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
                          (p0, p1, p2, p3, p4, p5, p6);
          }
 
@@ -14049,7 +14774,7 @@
          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
          {
             return allocator
-                     .template allocate_type<node_type,T0,T1,T2,tfunc_t>
+                     .template allocate_type<node_type, T0, T1, T2, tfunc_t>
                         (p0, p1, p2, p3);
          }
 
@@ -14140,7 +14865,7 @@
          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
          {
             return allocator
-                     .template allocate_type<node_type,T0,T1,T2>
+                     .template allocate_type<node_type, T0, T1, T2>
                         (p0, p1, p2);
          }
 
@@ -14241,7 +14966,7 @@
          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
          {
             return allocator
-                     .template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>
+                     .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
                         (p0, p1, p2, p3, p4);
          }
 
@@ -14307,7 +15032,7 @@
 
          inline T3 t3() const
          {
-            return t2_;
+            return t3_;
          }
 
          std::string type_id() const
@@ -14324,7 +15049,7 @@
          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
          {
             return allocator
-                     .template allocate_type<node_type,T0,T1,T2,T3>
+                     .template allocate_type<node_type, T0, T1, T2, T3>
                         (p0, p1, p2, p3);
          }
 
@@ -14360,27 +15085,27 @@
       template <typename T, typename T0, typename T1>
       struct T0oT1_define
       {
-         typedef details::T0oT1<T,T0,T1> type0;
+         typedef details::T0oT1<T, T0, T1> type0;
       };
 
       template <typename T, typename T0, typename T1, typename T2>
       struct T0oT1oT2_define
       {
-         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;
-         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;
-         typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;
-         typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;
+         typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
+         typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
+         typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
+         typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
       };
 
       template <typename T, typename T0, typename T1, typename T2, typename T3>
       struct T0oT1oT2oT3_define
       {
-         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;
-         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;
-         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;
-         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;
-         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;
-         typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;
+         typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
+         typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
+         typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
+         typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
+         typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
+         typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
       };
 
       template <typename T, typename Operation>
@@ -14538,20 +15263,16 @@
          typedef Operation operation_t;
 
          // variable op constant node
-         explicit vob_node(const T& var, const expression_ptr brnch)
+         explicit vob_node(const T& var, const expression_ptr branch)
          : v_(var)
          {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~vob_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return Operation::process(v_,branch_[0].first->value());
+            assert(branch_.first);
+            return Operation::process(v_,branch_.first->value());
          }
 
          inline operator_type operation() const
@@ -14566,7 +15287,17 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_[0].first;
+            return branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
@@ -14575,7 +15306,7 @@
          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
 
          const T& v_;
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       template <typename T, typename Operation>
@@ -14588,20 +15319,16 @@
          typedef Operation operation_t;
 
          // variable op constant node
-         explicit bov_node(const expression_ptr brnch, const T& var)
+         explicit bov_node(const expression_ptr branch, const T& var)
          : v_(var)
          {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~bov_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return Operation::process(branch_[0].first->value(),v_);
+            assert(branch_.first);
+            return Operation::process(branch_.first->value(),v_);
          }
 
          inline operator_type operation() const
@@ -14616,7 +15343,17 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_[0].first;
+            return branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
@@ -14625,7 +15362,7 @@
          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
 
          const T& v_;
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       template <typename T, typename Operation>
@@ -14638,20 +15375,16 @@
          typedef Operation operation_t;
 
          // variable op constant node
-         explicit cob_node(const T const_var, const expression_ptr brnch)
+         explicit cob_node(const T const_var, const expression_ptr branch)
          : c_(const_var)
          {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~cob_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return Operation::process(c_,branch_[0].first->value());
+            assert(branch_.first);
+            return Operation::process(c_,branch_.first->value());
          }
 
          inline operator_type operation() const
@@ -14671,13 +15404,23 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_[0].first;
+            return branch_.first;
          }
 
          inline expression_node<T>* move_branch(const std::size_t&)
          {
-            branch_[0].second = false;
-            return branch_[0].first;
+            branch_.second = false;
+            return branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
@@ -14686,7 +15429,7 @@
          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
 
          const T  c_;
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       template <typename T, typename Operation>
@@ -14699,20 +15442,16 @@
          typedef Operation operation_t;
 
          // variable op constant node
-         explicit boc_node(const expression_ptr brnch, const T const_var)
+         explicit boc_node(const expression_ptr branch, const T const_var)
          : c_(const_var)
          {
-            init_branches<1>(branch_,brnch);
-         }
-
-        ~boc_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return Operation::process(branch_[0].first->value(),c_);
+            assert(branch_.first);
+            return Operation::process(branch_.first->value(),c_);
          }
 
          inline operator_type operation() const
@@ -14732,13 +15471,23 @@
 
          inline expression_node<T>* branch(const std::size_t&) const
          {
-            return branch_[0].first;
+            return branch_.first;
          }
 
          inline expression_node<T>* move_branch(const std::size_t&)
          {
-            branch_[0].second = false;
-            return branch_[0].first;
+            branch_.second = false;
+            return branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
@@ -14747,7 +15496,7 @@
          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
 
          const T  c_;
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       #ifndef exprtk_disable_string_capabilities
@@ -15031,12 +15780,12 @@
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str0_range_ptr_ = &(range_ptr->range_ref());
+               str0_range_ptr_ = &(range->range_ref());
             }
 
             if (is_generally_string_node(binary_node<T>::branch_[1].first))
@@ -15046,12 +15795,12 @@
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
 
-               if (0 == range_ptr)
+               if (0 == range)
                   return;
 
-               str1_range_ptr_ = &(range_ptr->range_ref());
+               str1_range_ptr_ = &(range->range_ref());
             }
          }
 
@@ -15073,8 +15822,8 @@
                std::size_t str1_r0 = 0;
                std::size_t str1_r1 = 0;
 
-               range_t& range0 = (*str0_range_ptr_);
-               range_t& range1 = (*str1_range_ptr_);
+               const range_t& range0 = (*str0_range_ptr_);
+               const range_t& range1 = (*str1_range_ptr_);
 
                if (
                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
@@ -15209,19 +15958,15 @@
          typedef std::pair<expression_ptr, bool> branch_t;
          typedef PowOp operation_t;
 
-         explicit bipow_node(expression_ptr brnch)
+         explicit bipow_node(expression_ptr branch)
          {
-            init_branches<1>(branch_, brnch);
-         }
-
-        ~bipow_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return PowOp::result(branch_[0].first->value());
+            assert(branch_.first);
+            return PowOp::result(branch_.first->value());
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -15229,12 +15974,22 @@
             return expression_node<T>::e_ipow;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
+         }
+
       private:
 
          bipow_node(const bipow_node<T,PowOp>&);
          bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
 
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       template <typename T, typename PowOp>
@@ -15276,19 +16031,15 @@
          typedef std::pair<expression_ptr, bool> branch_t;
          typedef PowOp operation_t;
 
-         explicit bipowninv_node(expression_ptr brnch)
+         explicit bipowninv_node(expression_ptr branch)
          {
-            init_branches<1>(branch_, brnch);
-         }
-
-        ~bipowninv_node()
-         {
-            cleanup_branches::execute<T,1>(branch_);
+            construct_branch_pair(branch_, branch);
          }
 
          inline T value() const
          {
-            return (T(1) / PowOp::result(branch_[0].first->value()));
+            assert(branch_.first);
+            return (T(1) / PowOp::result(branch_.first->value()));
          }
 
          inline typename expression_node<T>::node_type type() const
@@ -15296,12 +16047,22 @@
             return expression_node<T>::e_ipowinv;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         {
+            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
+         }
+
       private:
 
          bipowninv_node(const bipowninv_node<T,PowOp>&);
          bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
 
-         branch_t branch_[1];
+         branch_t branch_;
       };
 
       template <typename T>
@@ -15450,37 +16211,55 @@
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
          {
-            return allocate<ResultNode>(operation,branch[0]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0]);
+            result->node_depth();
+            return result;
          }
 
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
          {
-            return allocate<ResultNode>(operation,branch[0],branch[1]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0], branch[1]);
+            result->node_depth();
+            return result;
          }
 
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
          {
-            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
+            result->node_depth();
+            return result;
          }
 
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
          {
-            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
+            result->node_depth();
+            return result;
          }
 
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
          {
-            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
+            result->node_depth();
+            return result;
          }
 
          template <typename ResultNode, typename OpType, typename ExprNode>
          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
          {
-            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
+            expression_node<typename ResultNode::value_type>* result =
+               allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type>
@@ -15492,92 +16271,131 @@
          template <typename node_type,
                    typename Type,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
          {
-            return (new node_type(seq));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(seq));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type, typename T1>
          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
          {
-            return (new node_type(t1));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type, typename T1>
          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
          {
-            return (new node_type(t1));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2>
          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
          {
-            return (new node_type(t1,t2));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2>
          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
          {
-            return (new node_type(t1,t2));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2>
          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
          {
-            return (new node_type(t1,t2));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2>
          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
          {
-            return (new node_type(t1,t2));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2>
          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
          {
-            return (new node_type(t1,t2));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3>
          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
          {
-            return (new node_type(t1,t2,t3));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3, typename T4>
          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
          {
-            return (new node_type(t1,t2,t3,t4));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3>
          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
          {
-            return (new node_type(t1,t2,t3));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3, typename T4>
          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
          {
-            return (new node_type(t1,t2,t3,t4));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3, typename T4, typename T5>
          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
          {
-            return (new node_type(t1,t2,t3,t4,t5));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15585,7 +16403,10 @@
          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
                                                                           const T3& t3) const
          {
-            return (new node_type(t1,t2,t3));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15594,7 +16415,10 @@
          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
                                                                           const T3& t3, const T4& t4) const
          {
-            return (new node_type(t1,t2,t3,t4));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15604,7 +16428,10 @@
                                                                           const T3& t3, const T4& t4,
                                                                           const T5& t5) const
          {
-            return (new node_type(t1,t2,t3,t4,t5));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15614,7 +16441,10 @@
                                                                           const T3& t3, const T4& t4,
                                                                           const T5& t5, const T6& t6) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15626,7 +16456,10 @@
                                                                           const T5& t5, const T6& t6,
                                                                           const T7& t7) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6,t7));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15639,7 +16472,10 @@
                                                                           const T5& t5, const T6& t6,
                                                                           const T7& t7, const T8& t8) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15653,7 +16489,10 @@
                                                                           const T7& t7, const T8& t8,
                                                                           const T9& t9) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15668,14 +16507,20 @@
                                                                           const T7& t7, const  T8&  t8,
                                                                           const T9& t9, const T10& t10) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
                    typename T1, typename T2, typename T3>
          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
          {
-            return (new node_type(t1,t2,t3));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15684,7 +16529,10 @@
          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
                                                                                T3 t3, T4 t4) const
          {
-            return (new node_type(t1,t2,t3,t4));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15695,7 +16543,10 @@
                                                                                T3 t3, T4 t4,
                                                                                T5 t5) const
          {
-            return (new node_type(t1,t2,t3,t4,t5));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15706,7 +16557,10 @@
                                                                                T3 t3, T4 t4,
                                                                                T5 t5, T6 t6) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6));
+            result->node_depth();
+            return result;
          }
 
          template <typename node_type,
@@ -15718,12 +16572,19 @@
                                                                                T5 t5, T6 t6,
                                                                                T7 t7) const
          {
-            return (new node_type(t1,t2,t3,t4,t5,t6,t7));
+            expression_node<typename node_type::value_type>*
+            result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
+            result->node_depth();
+            return result;
          }
 
          template <typename T>
          void inline free(expression_node<T>*& e) const
          {
+            exprtk_debug(("node_allocator::free() - deleting expression_node "
+                          "type: %03d addr: %p\n",
+                          static_cast<int>(e->type()),
+                          reinterpret_cast<void*>(e)));
             delete e;
             e = 0;
          }
@@ -15886,83 +16747,84 @@
       virtual ~ifunction()
       {}
 
-      #define empty_method_body                      \
+      #define empty_method_body(N)                   \
       {                                              \
+         exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
          return std::numeric_limits<T>::quiet_NaN(); \
       }                                              \
 
       inline virtual T operator() ()
-      empty_method_body
+      empty_method_body(0)
 
-       inline virtual T operator() (const T&)
-      empty_method_body
+      inline virtual T operator() (const T&)
+      empty_method_body(1)
 
-       inline virtual T operator() (const T&,const T&)
-      empty_method_body
+      inline virtual T operator() (const T&,const T&)
+      empty_method_body(2)
 
-       inline virtual T operator() (const T&, const T&, const T&)
-      empty_method_body
+      inline virtual T operator() (const T&, const T&, const T&)
+      empty_method_body(3)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(4)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(5)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(6)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(7)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(8)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(9)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(10)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
-                                  const T&)
-      empty_method_body
+                                   const T&)
+      empty_method_body(11)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&)
-      empty_method_body
+      empty_method_body(12)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(13)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(14)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(15)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(16)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(17)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(18)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(19)
 
       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      empty_method_body
+      empty_method_body(20)
 
       #undef empty_method_body
 
@@ -15979,7 +16841,7 @@
 
       inline virtual T operator() (const std::vector<T>&)
       {
-         exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
+         exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
          return std::numeric_limits<T>::quiet_NaN();
       }
    };
@@ -15991,8 +16853,9 @@
 
       enum return_type
       {
-         e_rtrn_scalar = 0,
-         e_rtrn_string = 1
+         e_rtrn_scalar   = 0,
+         e_rtrn_string   = 1,
+         e_rtrn_overload = 2
       };
 
       typedef T type;
@@ -16009,7 +16872,7 @@
 
       #define igeneric_function_empty_body(N)        \
       {                                              \
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
+         exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
          return std::numeric_limits<T>::quiet_NaN(); \
       }                                              \
 
@@ -16043,20 +16906,20 @@
 
       typedef T (*ff00_functor)();
       typedef T (*ff01_functor)(T);
-      typedef T (*ff02_functor)(T,T);
-      typedef T (*ff03_functor)(T,T,T);
-      typedef T (*ff04_functor)(T,T,T,T);
-      typedef T (*ff05_functor)(T,T,T,T,T);
-      typedef T (*ff06_functor)(T,T,T,T,T,T);
-      typedef T (*ff07_functor)(T,T,T,T,T,T,T);
-      typedef T (*ff08_functor)(T,T,T,T,T,T,T,T);
-      typedef T (*ff09_functor)(T,T,T,T,T,T,T,T,T);
-      typedef T (*ff10_functor)(T,T,T,T,T,T,T,T,T,T);
-      typedef T (*ff11_functor)(T,T,T,T,T,T,T,T,T,T,T);
-      typedef T (*ff12_functor)(T,T,T,T,T,T,T,T,T,T,T,T);
-      typedef T (*ff13_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T);
-      typedef T (*ff14_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T);
-      typedef T (*ff15_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T,T);
+      typedef T (*ff02_functor)(T, T);
+      typedef T (*ff03_functor)(T, T, T);
+      typedef T (*ff04_functor)(T, T, T, T);
+      typedef T (*ff05_functor)(T, T, T, T, T);
+      typedef T (*ff06_functor)(T, T, T, T, T, T);
+      typedef T (*ff07_functor)(T, T, T, T, T, T, T);
+      typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
+      typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
+      typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
+      typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
+      typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
+      typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
+      typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
+      typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
 
    protected:
 
@@ -16064,7 +16927,7 @@
        {
           using exprtk::ifunction<T>::operator();
 
-          freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
+          explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
           inline T operator() ()
           { return f(); }
           ff00_functor f;
@@ -16074,7 +16937,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
+         explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
          inline T operator() (const T& v0)
          { return f(v0); }
          ff01_functor f;
@@ -16084,7 +16947,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
+         explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
          inline T operator() (const T& v0, const T& v1)
          { return f(v0, v1); }
          ff02_functor f;
@@ -16094,7 +16957,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
+         explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2)
          { return f(v0, v1, v2); }
          ff03_functor f;
@@ -16104,7 +16967,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
+         explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
          { return f(v0, v1, v2, v3); }
          ff04_functor f;
@@ -16114,7 +16977,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
+         explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
          { return f(v0, v1, v2, v3, v4); }
          ff05_functor f;
@@ -16124,7 +16987,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
+         explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
          { return f(v0, v1, v2, v3, v4, v5); }
          ff06_functor f;
@@ -16134,7 +16997,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
+         explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
                               const T& v5, const T& v6)
          { return f(v0, v1, v2, v3, v4, v5, v6); }
@@ -16145,7 +17008,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
+         explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
                               const T& v5, const T& v6, const T& v7)
          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
@@ -16156,7 +17019,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
+         explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
                               const T& v5, const T& v6, const T& v7, const T& v8)
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
@@ -16167,7 +17030,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
+         explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
@@ -16178,7 +17041,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
+         explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
@@ -16189,7 +17052,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
+         explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
                               const T& v10, const T& v11)
@@ -16201,7 +17064,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
+         explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
                               const T& v10, const T& v11, const T& v12)
@@ -16213,7 +17076,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
+         explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
                               const T& v10, const T& v11, const T& v12, const T& v13)
@@ -16225,7 +17088,7 @@
       {
          using exprtk::ifunction<T>::operator();
 
-         freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
+         explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
                               const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
@@ -16644,11 +17507,12 @@
             #ifndef exprtk_disable_string_capabilities
             type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
             #endif
-            type_store<ifunction<T>,ifunction<T> > function_store;
+            type_store<ifunction<T>,ifunction<T> >                 function_store;
             type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
             type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
             type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
-            type_store<vector_holder_t,vector_holder_t> vector_store;
+            type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store;
+            type_store<vector_holder_t,vector_holder_t>            vector_store;
 
             st_data()
             {
@@ -16698,7 +17562,7 @@
            data_(st_data::create())
          {}
 
-         control_block(st_data* data)
+         explicit control_block(st_data* data)
          : ref_count(1),
            data_(data)
          {}
@@ -16772,7 +17636,7 @@
          return (*this);
       }
 
-      inline bool operator==(const symbol_table<T>& st)
+      inline bool operator==(const symbol_table<T>& st) const
       {
          return (this == &st) || (control_block_ == st.control_block_);
       }
@@ -16919,6 +17783,16 @@
             return local_data().string_function_store.get(function_name);
       }
 
+      inline generic_function_ptr get_overload_function(const std::string& function_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<generic_function_ptr>(0);
+         else if (!valid_symbol(function_name))
+            return reinterpret_cast<generic_function_ptr>(0);
+         else
+            return local_data().overload_function_store.get(function_name);
+      }
+
       typedef vector_holder_t* vector_holder_ptr;
 
       inline vector_holder_ptr get_vector(const std::string& vector_name) const
@@ -17020,7 +17894,7 @@
          else if (symbol_exists(variable_name))
             return false;
          else
-            return local_data().variable_store.add(variable_name,t,is_constant);
+            return local_data().variable_store.add(variable_name, t, is_constant);
       }
 
       inline bool add_constant(const std::string& constant_name, const T& value)
@@ -17035,7 +17909,7 @@
          local_data().local_symbol_list_.push_back(value);
          T& t = local_data().local_symbol_list_.back();
 
-         return add_variable(constant_name,t,true);
+         return add_variable(constant_name, t, true);
       }
 
       #ifndef exprtk_disable_string_capabilities
@@ -17048,7 +17922,7 @@
          else if (symbol_exists(stringvar_name))
             return false;
          else
-            return local_data().stringvar_store.add(stringvar_name,s,is_constant);
+            return local_data().stringvar_store.add(stringvar_name, s, is_constant);
       }
       #endif
 
@@ -17084,14 +17958,33 @@
             return false;
          else if (symbol_exists(function_name))
             return false;
-         else if (std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|"))
+         else if (
+                   (
+                     (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
+                     (generic_function_t::e_rtrn_string == function.rtrn_type)
+                   ) &&
+                   std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
+                 )
             return false;
-         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)
-            return local_data().generic_function_store.add(function_name,function);
-         else if (generic_function_t::e_rtrn_string == function.rtrn_type)
-            return local_data().string_function_store.add(function_name, function);
-         else
+         else if (
+                   (generic_function_t::e_rtrn_overload  == function.rtrn_type) &&
+                   std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
+                 )
             return false;
+
+         switch (function.rtrn_type)
+         {
+            case generic_function_t::e_rtrn_scalar :
+               return local_data().generic_function_store.add(function_name,function);
+
+            case generic_function_t::e_rtrn_string :
+               return local_data().string_function_store.add(function_name,function);
+
+            case generic_function_t::e_rtrn_overload :
+               return local_data().overload_function_store.add(function_name,function);
+         }
+
+         return false;
       }
 
       #define exprtk_define_freefunction(NN)                                                \
@@ -17154,14 +18047,33 @@
             return false;
          else if (symbol_exists(function_name,false))
             return false;
-         else if (std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|"))
+         else if (
+                   (
+                     (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
+                     (generic_function_t::e_rtrn_string == function.rtrn_type)
+                   ) &&
+                   std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
+                 )
             return false;
-         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)
-            return local_data().generic_function_store.add(function_name,function);
-         else if (generic_function_t::e_rtrn_string == function.rtrn_type)
-            return local_data().string_function_store.add(function_name, function);
-         else
+         else if (
+                   generic_function_t::e_rtrn_overload &&
+                   std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
+                 )
             return false;
+
+         switch (function.rtrn_type)
+         {
+            case generic_function_t::e_rtrn_scalar :
+               return local_data().generic_function_store.add(function_name,function);
+
+            case generic_function_t::e_rtrn_string :
+               return local_data().string_function_store.add(function_name,function);
+
+            case generic_function_t::e_rtrn_overload :
+               return local_data().overload_function_store.add(function_name,function);
+         }
+
+         return false;
       }
 
       template <std::size_t N>
@@ -17188,7 +18100,7 @@
          else if (0 == v_size)
             return false;
          else
-            return local_data().vector_store.add(vector_name,v,v_size);
+            return local_data().vector_store.add(vector_name, v, v_size);
       }
 
       template <typename Allocator>
@@ -17350,8 +18262,8 @@
       {
          /*
             Function will return true if symbol_name exists as either a
-            reserved symbol, variable, stringvar or function name in any
-            of the type stores.
+            reserved symbol, variable, stringvar, vector or function name
+            in any of the type stores.
          */
          if (!valid())
             return false;
@@ -17361,6 +18273,8 @@
          else if (local_data().stringvar_store.symbol_exists(symbol_name))
             return true;
          #endif
+         else if (local_data().vector_store.symbol_exists(symbol_name))
+            return true;
          else if (local_data().function_store.symbol_exists(symbol_name))
             return true;
          else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
@@ -17515,6 +18429,21 @@
                }
             }
          }
+
+         {
+            std::vector<std::string> name_list;
+
+            st.local_data().overload_function_store.get_list(name_list);
+
+            if (!name_list.empty())
+            {
+               for (std::size_t i = 0; i < name_list.size(); ++i)
+               {
+                  exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
+                  add_function(name_list[i],ifunc);
+               }
+            }
+         }
       }
 
    private:
@@ -17534,7 +18463,7 @@
                     ('_' != symbol[i])
                   )
                {
-                  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
+                  if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
                      continue;
                   else
                      return false;
@@ -17560,7 +18489,7 @@
                     ('_' != symbol[i])
                   )
                {
-                  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
+                  if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
                      continue;
                   else
                      return false;
@@ -17620,7 +18549,7 @@
               size(0)
             {}
 
-            data_pack(void* ptr, data_type dt, std::size_t sz = 0)
+            data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
             : pointer(ptr),
               type(dt),
               size(sz)
@@ -17642,7 +18571,7 @@
            return_invoked(&retinv_null)
          {}
 
-         control_block(expression_ptr e)
+         explicit control_block(expression_ptr e)
          : ref_count(1),
            expr     (e),
            results  (0),
@@ -17735,6 +18664,13 @@
          control_block_->ref_count++;
       }
 
+      explicit expression(const symbol_table<T>& symbol_table)
+      : control_block_(0)
+      {
+         set_expression(new details::null_node<T>());
+         symbol_table_list_.push_back(symbol_table);
+      }
+
       inline expression<T>& operator=(const expression<T>& e)
       {
          if (this != &e)
@@ -17760,7 +18696,7 @@
          return *this;
       }
 
-      inline bool operator==(const expression<T>& e)
+      inline bool operator==(const expression<T>& e) const
       {
          return (this == &e);
       }
@@ -17787,6 +18723,9 @@
 
       inline T value() const
       {
+         assert(control_block_      );
+         assert(control_block_->expr);
+
          return control_block_->expr->value();
       }
 
@@ -17909,7 +18848,7 @@
                control_block_->
                   local_data_list.push_back(
                      typename expression<T>::control_block::
-                        data_pack(reinterpret_cast<void*>(data),dt,size));
+                        data_pack(reinterpret_cast<void*>(data), dt, size));
             }
          }
       }
@@ -17944,7 +18883,7 @@
       }
 
       control_block* control_block_;
-      symtab_list_t      symbol_table_list_;
+      symtab_list_t  symbol_table_list_;
 
       friend class parser<T>;
       friend class expression_helper<T>;
@@ -18003,7 +18942,8 @@
          e_numeric = 4,
          e_symtab  = 5,
          e_lexer   = 6,
-         e_helper  = 7
+         e_helper  = 7,
+         e_parser  = 8
       };
 
       struct type
@@ -18023,7 +18963,7 @@
          std::size_t column_no;
       };
 
-      inline type make_error(error_mode mode,
+      inline type make_error(const error_mode mode,
                              const std::string& diagnostic   = "",
                              const std::string& src_location = "")
       {
@@ -18036,7 +18976,7 @@
          return t;
       }
 
-      inline type make_error(error_mode mode,
+      inline type make_error(const error_mode mode,
                              const lexer::token& tk,
                              const std::string& diagnostic   = "",
                              const std::string& src_location = "")
@@ -18061,6 +19001,7 @@
             case e_symtab  : return std::string("Symbol Error" );
             case e_lexer   : return std::string("Lexer Error"  );
             case e_helper  : return std::string("Helper Error" );
+            case e_parser  : return std::string("Parser Error" );
             default        : return std::string("Unknown Error");
          }
       }
@@ -18207,11 +19148,11 @@
       typedef typename expression<T>::symtab_list_t     symbol_table_list_t;
       typedef details::vector_holder<T>*                  vector_holder_ptr;
 
-      typedef typename details::functor_t<T>         functor_t;
-      typedef typename functor_t::qfunc_t quaternary_functor_t;
-      typedef typename functor_t::tfunc_t    trinary_functor_t;
-      typedef typename functor_t::bfunc_t     binary_functor_t;
-      typedef typename functor_t::ufunc_t      unary_functor_t;
+      typedef typename details::functor_t<T>            functor_t;
+      typedef typename functor_t::qfunc_t    quaternary_functor_t;
+      typedef typename functor_t::tfunc_t       trinary_functor_t;
+      typedef typename functor_t::bfunc_t        binary_functor_t;
+      typedef typename functor_t::ufunc_t         unary_functor_t;
 
       typedef details::operator_type operator_t;
 
@@ -18349,7 +19290,7 @@
          typedef variable_node_t*     variable_node_ptr;
          typedef parser<T>                     parser_t;
 
-         scope_element_manager(parser<T>& p)
+         explicit scope_element_manager(parser<T>& p)
          : parser_(p),
            input_param_cnt_(0)
          {}
@@ -18460,6 +19401,10 @@
 
          inline void free_element(scope_element& se)
          {
+            #ifdef exprtk_enable_debugging
+            exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
+            #endif
+
             switch (se.type)
             {
                case scope_element::e_variable   : if (se.data    ) delete (T*) se.data;
@@ -18542,12 +19487,12 @@
 
          typedef parser<T> parser_t;
 
-         scope_handler(parser<T>& p)
+         explicit scope_handler(parser<T>& p)
          : parser_(p)
          {
             parser_.state_.scope_depth++;
             #ifdef exprtk_enable_debugging
-            std::string depth(2 * parser_.state_.scope_depth,'-');
+            const std::string depth(2 * parser_.state_.scope_depth,'-');
             exprtk_debug(("%s> Scope Depth: %02d\n",
                           depth.c_str(),
                           static_cast<int>(parser_.state_.scope_depth)));
@@ -18559,7 +19504,7 @@
             parser_.sem_.deactivate(parser_.state_.scope_depth);
             parser_.state_.scope_depth--;
             #ifdef exprtk_enable_debugging
-            std::string depth(2 * parser_.state_.scope_depth,'-');
+            const std::string depth(2 * parser_.state_.scope_depth,'-');
             exprtk_debug(("<%s Scope Depth: %02d\n",
                           depth.c_str(),
                           static_cast<int>(parser_.state_.scope_depth)));
@@ -18573,6 +19518,45 @@
          parser_t& parser_;
       };
 
+      class stack_limit_handler
+      {
+      public:
+
+         typedef parser<T> parser_t;
+
+         explicit stack_limit_handler(parser<T>& p)
+            : parser_(p),
+              limit_exceeded_(false)
+         {
+            if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
+            {
+               limit_exceeded_ = true;
+               parser_.set_error(
+                  make_error(parser_error::e_parser,
+                     "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
+                     " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
+                     exprtk_error_location));
+            }
+         }
+
+        ~stack_limit_handler()
+         {
+            parser_.state_.stack_depth--;
+         }
+
+         bool operator!()
+         {
+            return limit_exceeded_;
+         }
+
+      private:
+
+         stack_limit_handler& operator=(const stack_limit_handler&);
+
+         parser_t& parser_;
+         bool limit_exceeded_;
+      };
+
       struct symtab_store
       {
          symbol_table_list_t symtab_list_;
@@ -18773,6 +19757,27 @@
             return result;
          }
 
+         inline generic_function_ptr get_overload_function(const std::string& function_name) const
+         {
+            if (!valid_function_name(function_name))
+               return reinterpret_cast<generic_function_ptr>(0);
+
+            generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result =
+                     local_data(i).overload_function_store.get(function_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
          inline vector_holder_ptr get_vector(const std::string& vector_name) const
          {
             if (!valid_symbol(vector_name))
@@ -18995,11 +20000,13 @@
 
          void reset()
          {
-            parsing_return_stmt = false;
-            parsing_break_stmt  = false;
-            return_stmt_present = false;
-            side_effect_present = false;
-            scope_depth         = 0;
+            parsing_return_stmt     = false;
+            parsing_break_stmt      = false;
+            return_stmt_present     = false;
+            side_effect_present     = false;
+            scope_depth             = 0;
+            stack_depth             = 0;
+            parsing_loop_stmt_count = 0;
          }
 
          #ifndef exprtk_enable_debugging
@@ -19022,6 +20029,8 @@
          bool side_effect_present;
          bool type_check_enabled;
          std::size_t scope_depth;
+         std::size_t stack_depth;
+         std::size_t parsing_loop_stmt_count;
       };
 
    public:
@@ -19031,8 +20040,9 @@
 
          enum usr_symbol_type
          {
-            e_usr_variable_type = 0,
-            e_usr_constant_type = 1
+            e_usr_unknown_type  = 0,
+            e_usr_variable_type = 1,
+            e_usr_constant_type = 2
          };
 
          enum usr_mode
@@ -19111,7 +20121,7 @@
          {}
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
          {
             if (!collect_variables_ && !collect_functions_)
@@ -19134,7 +20144,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
          {
             if (!collect_assignments_)
@@ -19347,6 +20357,8 @@
                                                      e_strength_reduction;
 
          settings_store(const std::size_t compile_options = compile_all_opts)
+         : max_stack_depth_(400),
+           max_node_depth_(10000)
          {
            load_compile_options(compile_options);
          }
@@ -19467,7 +20479,7 @@
          bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
          bool zero_return_disabled       () const { return disable_zero_return_;       }
 
-         bool function_enabled(const std::string& function_name)
+         bool function_enabled(const std::string& function_name) const
          {
             if (disabled_func_set_.empty())
                return true;
@@ -19475,7 +20487,7 @@
                return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
          }
 
-         bool control_struct_enabled(const std::string& control_struct)
+         bool control_struct_enabled(const std::string& control_struct) const
          {
             if (disabled_ctrl_set_.empty())
                return true;
@@ -19483,7 +20495,7 @@
                return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
          }
 
-         bool logic_enabled(const std::string& logic_operation)
+         bool logic_enabled(const std::string& logic_operation) const
          {
             if (disabled_logic_set_.empty())
                return true;
@@ -19491,7 +20503,7 @@
                return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
          }
 
-         bool arithmetic_enabled(const details::operator_type& arithmetic_operation)
+         bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
          {
             if (disabled_logic_set_.empty())
                return true;
@@ -19500,7 +20512,7 @@
                                                             .find(arith_opr_to_string(arithmetic_operation));
          }
 
-         bool assignment_enabled(const details::operator_type& assignment)
+         bool assignment_enabled(const details::operator_type& assignment) const
          {
             if (disabled_assignment_set_.empty())
                return true;
@@ -19509,7 +20521,7 @@
                                                            .find(assign_opr_to_string(assignment));
          }
 
-         bool inequality_enabled(const details::operator_type& inequality)
+         bool inequality_enabled(const details::operator_type& inequality) const
          {
             if (disabled_inequality_set_.empty())
                return true;
@@ -19518,7 +20530,7 @@
                                                            .find(inequality_opr_to_string(inequality));
          }
 
-         bool function_disabled(const std::string& function_name)
+         bool function_disabled(const std::string& function_name) const
          {
             if (disabled_func_set_.empty())
                return false;
@@ -19526,7 +20538,7 @@
                return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
          }
 
-         bool control_struct_disabled(const std::string& control_struct)
+         bool control_struct_disabled(const std::string& control_struct) const
          {
             if (disabled_ctrl_set_.empty())
                return false;
@@ -19534,7 +20546,7 @@
                return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
          }
 
-         bool logic_disabled(const std::string& logic_operation)
+         bool logic_disabled(const std::string& logic_operation) const
          {
             if (disabled_logic_set_.empty())
                return false;
@@ -19542,7 +20554,7 @@
                return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
          }
 
-         bool assignment_disabled(const details::operator_type assignment_operation)
+         bool assignment_disabled(const details::operator_type assignment_operation) const
          {
             if (disabled_assignment_set_.empty())
                return false;
@@ -19551,7 +20563,16 @@
                                                            .find(assign_opr_to_string(assignment_operation));
          }
 
-         bool arithmetic_disabled(const details::operator_type arithmetic_operation)
+         bool logic_disabled(const details::operator_type logic_operation) const
+         {
+            if (disabled_logic_set_.empty())
+               return false;
+            else
+               return disabled_logic_set_.end() != disabled_logic_set_
+                                                           .find(logic_opr_to_string(logic_operation));
+         }
+
+         bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
          {
             if (disabled_arithmetic_set_.empty())
                return false;
@@ -19560,7 +20581,7 @@
                                                            .find(arith_opr_to_string(arithmetic_operation));
          }
 
-         bool inequality_disabled(const details::operator_type& inequality)
+         bool inequality_disabled(const details::operator_type& inequality) const
          {
             if (disabled_inequality_set_.empty())
                return false;
@@ -19755,6 +20776,16 @@
             return (*this);
          }
 
+         void set_max_stack_depth(const std::size_t mx_stack_depth)
+         {
+            max_stack_depth_ = mx_stack_depth;
+         }
+
+         void set_max_node_depth(const std::size_t max_node_depth)
+         {
+            max_node_depth_ = max_node_depth;
+         }
+
       private:
 
          void load_compile_options(const std::size_t compile_options)
@@ -19774,7 +20805,7 @@
             disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
          }
 
-         std::string assign_opr_to_string(details::operator_type opr)
+         std::string assign_opr_to_string(details::operator_type opr) const
          {
             switch (opr)
             {
@@ -19788,7 +20819,7 @@
             }
          }
 
-         std::string arith_opr_to_string(details::operator_type opr)
+         std::string arith_opr_to_string(details::operator_type opr) const
          {
             switch (opr)
             {
@@ -19801,7 +20832,7 @@
             }
          }
 
-         std::string inequality_opr_to_string(details::operator_type opr)
+         std::string inequality_opr_to_string(details::operator_type opr) const
          {
             switch (opr)
             {
@@ -19817,6 +20848,21 @@
             }
          }
 
+         std::string logic_opr_to_string(details::operator_type opr) const
+         {
+            switch (opr)
+            {
+               case details::e_and  : return "and" ;
+               case details::e_or   : return "or"  ;
+               case details::e_xor  : return "xor" ;
+               case details::e_nand : return "nand";
+               case details::e_nor  : return "nor" ;
+               case details::e_xnor : return "xnor";
+               case details::e_notl : return "not" ;
+               default              : return ""    ;
+            }
+         }
+
          bool enable_replacer_;
          bool enable_joiner_;
          bool enable_numeric_check_;
@@ -19838,6 +20884,9 @@
          disabled_entity_set_t disabled_assignment_set_;
          disabled_entity_set_t disabled_inequality_set_;
 
+         std::size_t max_stack_depth_;
+         std::size_t max_node_depth_;
+
          friend class parser<T>;
       };
 
@@ -19857,7 +20906,8 @@
         #pragma warning(pop)
         #endif
         operator_joiner_2_(2),
-        operator_joiner_3_(3)
+        operator_joiner_3_(3),
+        loop_runtime_check_(0)
       {
          init_precompilation();
 
@@ -19895,8 +20945,8 @@
          if (settings_.replacer_enabled())
          {
             symbol_replacer_.clear();
-            symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
-            symbol_replacer_.add_replace("false","0",lexer::token::e_number);
+            symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
+            symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
             helper_assembly_.token_modifier_list.clear();
             helper_assembly_.register_modifier(&symbol_replacer_);
          }
@@ -19939,7 +20989,8 @@
 
             if (settings_.sequence_check_enabled())
             {
-               helper_assembly_.register_scanner(&sequence_validator_);
+               helper_assembly_.register_scanner(&sequence_validator_      );
+               helper_assembly_.register_scanner(&sequence_validator_3tkns_);
             }
          }
       }
@@ -19960,7 +21011,7 @@
          {
             set_error(
                make_error(parser_error::e_syntax,
-                          "ERR000 - Empty expression!",
+                          "ERR001 - Empty expression!",
                           exprtk_error_location));
 
             return false;
@@ -19976,7 +21027,7 @@
          {
             set_error(
                make_error(parser_error::e_syntax,
-                          "ERR001 - Empty expression!",
+                          "ERR002 - Empty expression!",
                           exprtk_error_location));
 
             return false;
@@ -20005,7 +21056,7 @@
                dec_.return_present_ = true;
 
                e = expression_generator_
-                     .return_envelope(e,results_context_,retinvk_ptr);
+                     .return_envelope(e, results_context_, retinvk_ptr);
             }
 
             expr.set_expression(e);
@@ -20023,32 +21074,32 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR002 - Invalid expression encountered",
+                             "ERR003 - Invalid expression encountered",
                              exprtk_error_location));
             }
 
-            dec_.clear    ();
-            sem_.cleanup  ();
-            return_cleanup();
-
             if ((0 != e) && branch_deletable(e))
             {
                destroy_node(e);
             }
 
+            dec_.clear    ();
+            sem_.cleanup  ();
+            return_cleanup();
+
             return false;
          }
       }
 
       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
       {
-         expression_t expr;
+         expression_t expression;
 
-         expr.register_symbol_table(symtab);
+         expression.register_symbol_table(symtab);
 
-         compile(expression_string,expr);
+         compile(expression_string,expression);
 
-         return expr;
+         return expression;
       }
 
       void process_lexer_errors()
@@ -20057,7 +21108,7 @@
          {
             if (lexer()[i].is_error())
             {
-               std::string diagnostic = "ERR003 - ";
+               std::string diagnostic = "ERR004 - ";
 
                switch (lexer()[i].type)
                {
@@ -20115,16 +21166,17 @@
             {
                if (helper_assembly_.error_token_scanner)
                {
-                  lexer::helper::bracket_checker*    bracket_checker_ptr    = 0;
-                  lexer::helper::numeric_checker*    numeric_checker_ptr    = 0;
-                  lexer::helper::sequence_validator* sequence_validator_ptr = 0;
+                  lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
+                  lexer::helper::numeric_checker*            numeric_checker_ptr     = 0;
+                  lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
+                  lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
 
                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
                   {
                      set_error(
                         make_error(parser_error::e_token,
                                    bracket_checker_ptr->error_token(),
-                                   "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
+                                   "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
                                    exprtk_error_location));
                   }
                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
@@ -20136,7 +21188,7 @@
                         set_error(
                            make_error(parser_error::e_token,
                                       error_token,
-                                      "ERR005 - Invalid numeric token: '" + error_token.value + "'",
+                                      "ERR006 - Invalid numeric token: '" + error_token.value + "'",
                                       exprtk_error_location));
                      }
 
@@ -20154,7 +21206,7 @@
                         set_error(
                            make_error(parser_error::e_token,
                                       error_token.first,
-                                      "ERR006 - Invalid token sequence: '" +
+                                      "ERR007 - Invalid token sequence: '" +
                                       error_token.first.value  + "' and '" +
                                       error_token.second.value + "'",
                                       exprtk_error_location));
@@ -20165,6 +21217,26 @@
                         sequence_validator_ptr->clear_errors();
                      }
                   }
+                  else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
+                  {
+                     for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
+                     {
+                        std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
+
+                        set_error(
+                           make_error(parser_error::e_token,
+                                      error_token.first,
+                                      "ERR008 - Invalid token sequence: '" +
+                                      error_token.first.value  + "' and '" +
+                                      error_token.second.value + "'",
+                                      exprtk_error_location));
+                     }
+
+                     if (sequence_validator3_ptr->error_count())
+                     {
+                        sequence_validator3_ptr->clear_errors();
+                     }
+                  }
                }
 
                return false;
@@ -20179,7 +21251,7 @@
          return settings_;
       }
 
-      inline parser_error::type get_error(const std::size_t& index)
+      inline parser_error::type get_error(const std::size_t& index) const
       {
          if (index < error_list_.size())
             return error_list_[index];
@@ -20248,9 +21320,19 @@
          unknown_symbol_resolver_ = &default_usr_;
       }
 
+      inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
+      {
+         loop_runtime_check_ = &lrtchk;
+      }
+
+      inline void clear_loop_runtime_check()
+      {
+         loop_runtime_check_ = loop_runtime_check_ptr(0);
+      }
+
    private:
 
-      inline bool valid_base_operation(const std::string& symbol)
+      inline bool valid_base_operation(const std::string& symbol) const
       {
          const std::size_t length = symbol.size();
 
@@ -20264,7 +21346,7 @@
                    (base_ops_map_.end() != base_ops_map_.find(symbol));
       }
 
-      inline bool valid_vararg_operation(const std::string& symbol)
+      inline bool valid_vararg_operation(const std::string& symbol) const
       {
          static const std::string s_sum     = "sum" ;
          static const std::string s_mul     = "mul" ;
@@ -20291,17 +21373,22 @@
                settings_.function_enabled(symbol);
       }
 
-      bool is_invalid_arithmetic_operation(const details::operator_type operation)
+      bool is_invalid_logic_operation(const details::operator_type operation) const
+      {
+         return settings_.logic_disabled(operation);
+      }
+
+      bool is_invalid_arithmetic_operation(const details::operator_type operation) const
       {
          return settings_.arithmetic_disabled(operation);
       }
 
-      bool is_invalid_assignment_operation(const details::operator_type operation)
+      bool is_invalid_assignment_operation(const details::operator_type operation) const
       {
          return settings_.assignment_disabled(operation);
       }
 
-      bool is_invalid_inequality_operation(const details::operator_type operation)
+      bool is_invalid_inequality_operation(const details::operator_type operation) const
       {
          return settings_.inequality_disabled(operation);
       }
@@ -20309,14 +21396,18 @@
       #ifdef exprtk_enable_debugging
       inline void next_token()
       {
-         std::string ct_str = current_token().value;
+         const std::string ct_str = current_token().value;
+         const std::size_t ct_pos = current_token().position;
          parser_helper::next_token();
-         std::string depth(2 * state_.scope_depth,' ');
+         const std::string depth(2 * state_.scope_depth,' ');
          exprtk_debug(("%s"
-                       "prev[%s] --> curr[%s]\n",
+                       "prev[%s | %04d] --> curr[%s | %04d]  stack_level: %3d\n",
                        depth.c_str(),
                        ct_str.c_str(),
-                       current_token().value.c_str()));
+                       static_cast<unsigned int>(ct_pos),
+                       current_token().value.c_str(),
+                       static_cast<unsigned int>(current_token().position),
+                       static_cast<unsigned int>(state_.stack_depth)));
       }
       #endif
 
@@ -20325,8 +21416,6 @@
          std::vector<expression_node_ptr> arg_list;
          std::vector<bool> side_effect_list;
 
-         expression_node_ptr result = error_node();
-
          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
 
          lexer::token begin_token;
@@ -20347,7 +21436,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR007 - Invalid expression encountered",
+                                "ERR009 - Invalid expression encountered",
                                 exprtk_error_location));
                }
 
@@ -20361,7 +21450,7 @@
 
                end_token = current_token();
 
-               std::string sub_expr = construct_subexpr(begin_token,end_token);
+               const std::string sub_expr = construct_subexpr(begin_token, end_token);
 
                exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
                              static_cast<int>(arg_list.size() - 1),
@@ -20393,7 +21482,7 @@
             dec_.final_stmt_return_ = true;
          }
 
-         result = simplify(arg_list,side_effect_list);
+         const expression_node_ptr result = simplify(arg_list,side_effect_list);
 
          sdd.delete_ptr = (0 == result);
 
@@ -20439,6 +21528,13 @@
 
       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
       {
+         stack_limit_handler slh(*this);
+
+         if (!slh)
+         {
+            return error_node();
+         }
+
          expression_node_ptr expression = parse_branch(precedence);
 
          if (0 == expression)
@@ -20456,25 +21552,25 @@
 
             switch (current_token().type)
             {
-               case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
-               case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
-               case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
-               case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
-               case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
-               case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break;
-               case token_t::e_swap   : current_state.set(e_level00,e_level00,details::e_swap  ); break;
-               case token_t::e_lt     : current_state.set(e_level05,e_level06,details::    e_lt); break;
-               case token_t::e_lte    : current_state.set(e_level05,e_level06,details::   e_lte); break;
-               case token_t::e_eq     : current_state.set(e_level05,e_level06,details::    e_eq); break;
-               case token_t::e_ne     : current_state.set(e_level05,e_level06,details::    e_ne); break;
-               case token_t::e_gte    : current_state.set(e_level05,e_level06,details::   e_gte); break;
-               case token_t::e_gt     : current_state.set(e_level05,e_level06,details::    e_gt); break;
-               case token_t::e_add    : current_state.set(e_level07,e_level08,details::   e_add); break;
-               case token_t::e_sub    : current_state.set(e_level07,e_level08,details::   e_sub); break;
-               case token_t::e_div    : current_state.set(e_level10,e_level11,details::   e_div); break;
-               case token_t::e_mul    : current_state.set(e_level10,e_level11,details::   e_mul); break;
-               case token_t::e_mod    : current_state.set(e_level10,e_level11,details::   e_mod); break;
-               case token_t::e_pow    : current_state.set(e_level12,e_level12,details::   e_pow); break;
+               case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
+               case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
+               case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
+               case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
+               case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
+               case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
+               case token_t::e_swap   : current_state.set(e_level00,e_level00, details::e_swap  ); break;
+               case token_t::e_lt     : current_state.set(e_level05,e_level06, details::    e_lt); break;
+               case token_t::e_lte    : current_state.set(e_level05,e_level06, details::   e_lte); break;
+               case token_t::e_eq     : current_state.set(e_level05,e_level06, details::    e_eq); break;
+               case token_t::e_ne     : current_state.set(e_level05,e_level06, details::    e_ne); break;
+               case token_t::e_gte    : current_state.set(e_level05,e_level06, details::   e_gte); break;
+               case token_t::e_gt     : current_state.set(e_level05,e_level06, details::    e_gt); break;
+               case token_t::e_add    : current_state.set(e_level07,e_level08, details::   e_add); break;
+               case token_t::e_sub    : current_state.set(e_level07,e_level08, details::   e_sub); break;
+               case token_t::e_div    : current_state.set(e_level10,e_level11, details::   e_div); break;
+               case token_t::e_mul    : current_state.set(e_level10,e_level11, details::   e_mul); break;
+               case token_t::e_mod    : current_state.set(e_level10,e_level11, details::   e_mod); break;
+               case token_t::e_pow    : current_state.set(e_level12,e_level12, details::   e_pow); break;
                default                : if (token_t::e_symbol == current_token().type)
                                         {
                                            static const std::string s_and   =   "and";
@@ -20570,21 +21666,33 @@
             else if (current_state.left < precedence)
                break;
 
-            lexer::token prev_token = current_token();
+            const lexer::token prev_token = current_token();
 
             next_token();
 
             expression_node_ptr right_branch   = error_node();
             expression_node_ptr new_expression = error_node();
 
-            if (is_invalid_arithmetic_operation(current_state.operation))
+            if (is_invalid_logic_operation(current_state.operation))
             {
                free_node(node_allocator_,expression);
 
                set_error(
                   make_error(parser_error::e_syntax,
                              prev_token,
-                             "ERR008 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'",
+                             "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
+                             exprtk_error_location));
+
+               return error_node();
+            }
+            else if (is_invalid_arithmetic_operation(current_state.operation))
+            {
+               free_node(node_allocator_,expression);
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             prev_token,
+                             "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -20596,7 +21704,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              prev_token,
-                             "ERR009 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
+                             "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -20608,7 +21716,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              prev_token,
-                             "ERR010 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'",
+                             "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -20621,13 +21729,13 @@
                     details::is_return_node(right_branch)
                   )
                {
-                  free_node(node_allocator_,  expression);
-                  free_node(node_allocator_,right_branch);
+                  free_node(node_allocator_,   expression);
+                  free_node(node_allocator_, right_branch);
 
                   set_error(
                      make_error(parser_error::e_syntax,
                                 prev_token,
-                                "ERR011 - Return statements cannot be part of sub-expressions",
+                                "ERR014 - Return statements cannot be part of sub-expressions",
                                 exprtk_error_location));
 
                   return error_node();
@@ -20650,11 +21758,12 @@
                                 prev_token,
                                 !synthesis_error_.empty() ?
                                 synthesis_error_ :
-                                "ERR012 - General parsing error at token: '" + prev_token.value + "'",
+                                "ERR015 - General parsing error at token: '" + prev_token.value + "'",
                                 exprtk_error_location));
                }
 
-               free_node(node_allocator_,expression);
+               free_node(node_allocator_,   expression);
+               free_node(node_allocator_, right_branch);
 
                return error_node();
             }
@@ -20674,6 +21783,20 @@
             }
          }
 
+         if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                  current_token(),
+                  "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
+                  " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
+                  exprtk_error_location));
+
+            free_node(node_allocator_,expression);
+
+            return error_node();
+         }
+
          return expression;
       }
 
@@ -20719,7 +21842,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR013 - Failed to find variable node in symbol table",
+                                "ERR017 - Failed to find variable node in symbol table",
                                 exprtk_error_location));
 
                   free_node(node_allocator_,node);
@@ -20737,6 +21860,31 @@
          return reinterpret_cast<expression_node_ptr>(0);
       }
 
+      struct scoped_expression_delete
+      {
+         scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
+         : delete_ptr(true),
+           parser_(pr),
+           expression_(expression)
+         {}
+
+        ~scoped_expression_delete()
+         {
+            if (delete_ptr)
+            {
+               free_node(parser_.node_allocator_, expression_);
+            }
+         }
+
+         bool delete_ptr;
+         parser<T>& parser_;
+         expression_node_ptr& expression_;
+
+      private:
+
+         scoped_expression_delete& operator=(const scoped_expression_delete&);
+      };
+
       template <typename Type, std::size_t N>
       struct scoped_delete
       {
@@ -20760,7 +21908,7 @@
             {
                for (std::size_t i = 0; i < N; ++i)
                {
-                  free_node(parser_.node_allocator_,p_[i]);
+                  free_node(parser_.node_allocator_, p_[i]);
                }
             }
          }
@@ -20842,7 +21990,7 @@
 
       struct scoped_bool_negator
       {
-         scoped_bool_negator(bool& bb)
+         explicit scoped_bool_negator(bool& bb)
          : b(bb)
          { b = !b; }
 
@@ -20854,7 +22002,7 @@
 
       struct scoped_bool_or_restorer
       {
-         scoped_bool_or_restorer(bool& bb)
+         explicit scoped_bool_or_restorer(bool& bb)
          : b(bb),
            original_value_(bb)
          {}
@@ -20868,6 +22016,21 @@
          bool original_value_;
       };
 
+      struct scoped_inc_dec
+      {
+         explicit scoped_inc_dec(std::size_t& v)
+         : v_(v)
+         { ++v_; }
+
+        ~scoped_inc_dec()
+         {
+           assert(v_ > 0);
+           --v_;
+         }
+
+         std::size_t& v_;
+      };
+
       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
       {
          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
@@ -20899,7 +22062,7 @@
                          set_error(
                             make_error(parser_error::e_syntax,
                                        current_token(),
-                                       "ERR014 - Invalid number of parameters for function: '" + function_name + "'",
+                                       "ERR018 - Invalid number of parameters for function: '" + function_name + "'",
                                        exprtk_error_location));
 
                          return error_node();
@@ -20913,7 +22076,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR015 - Failed to generate call to function: '" + function_name + "'",
+                          "ERR019 - Failed to generate call to function: '" + function_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -20932,7 +22095,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR016 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
+                          "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
                           exprtk_error_location));
 
             return error_node();
@@ -20955,7 +22118,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR017 - Expecting argument list for function: '" + function_name + "'",
+                          "ERR021 - Expecting argument list for function: '" + function_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -20970,7 +22133,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR018 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
+                             "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -20982,7 +22145,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR019 - Invalid number of arguments for function: '" + function_name + "'",
+                                "ERR023 - Invalid number of arguments for function: '" + function_name + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -20995,7 +22158,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR020 - Invalid number of arguments for function: '" + function_name + "'",
+                          "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -21024,7 +22187,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR021 - Expecting '()' to proceed call to function: '" + function_name + "'",
+                          "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'",
                           exprtk_error_location));
 
             free_node(node_allocator_,result);
@@ -21049,7 +22212,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR022 - Expected a '(' at start of function call to '" + function_name  +
+                          "ERR026 - Expected a '(' at start of function call to '" + function_name  +
                           "', instead got: '" + current_token().value + "'",
                           exprtk_error_location));
 
@@ -21061,7 +22224,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR023 - Expected at least one input parameter for function call '" + function_name + "'",
+                          "ERR027 - Expected at least one input parameter for function call '" + function_name + "'",
                           exprtk_error_location));
 
             return 0;
@@ -21087,7 +22250,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR024 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
+                             "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
                              exprtk_error_location));
 
                return 0;
@@ -21099,7 +22262,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR025 - Invalid number of input parameters passed to function '" + function_name  + "'",
+                          "ERR029 - Invalid number of input parameters passed to function '" + function_name  + "'",
                           exprtk_error_location));
 
             return 0;
@@ -21122,7 +22285,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           diagnostic_token,
-                          "ERR026 - No entry found for base operation: " + operation_name,
+                          "ERR030 - No entry found for base operation: " + operation_name,
                           exprtk_error_location));
 
             return error_node();
@@ -21137,7 +22300,7 @@
          {
             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
             {
-               details::base_operation_t& operation = itr->second;
+               const details::base_operation_t& operation = itr->second;
 
                if (operation.num_params == parameter_count)
                {
@@ -21169,7 +22332,7 @@
          set_error(
             make_error(parser_error::e_syntax,
                        diagnostic_token,
-                       "ERR027 - Invalid number of input parameters for call to function: '" + operation_name + "'",
+                       "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'",
                        exprtk_error_location));
 
          return error_node();
@@ -21189,7 +22352,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR028 - Expected ',' between if-statement condition and consequent",
+                          "ERR032 - Expected ',' between if-statement condition and consequent",
                           exprtk_error_location));
             result = false;
          }
@@ -21198,7 +22361,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR029 - Failed to parse consequent for if-statement",
+                          "ERR033 - Failed to parse consequent for if-statement",
                           exprtk_error_location));
             result = false;
          }
@@ -21207,7 +22370,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR030 - Expected ',' between if-statement consequent and alternative",
+                          "ERR034 - Expected ',' between if-statement consequent and alternative",
                           exprtk_error_location));
             result = false;
          }
@@ -21216,7 +22379,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR031 - Failed to parse alternative for if-statement",
+                          "ERR035 - Failed to parse alternative for if-statement",
                           exprtk_error_location));
             result = false;
          }
@@ -21225,7 +22388,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR032 - Expected ')' at the end of if-statement",
+                          "ERR036 - Expected ')' at the end of if-statement",
                           exprtk_error_location));
             result = false;
          }
@@ -21241,13 +22404,13 @@
                if (consq_is_str && alter_is_str)
                {
                   return expression_generator_
-                           .conditional_string(condition,consequent,alternative);
+                           .conditional_string(condition, consequent, alternative);
                }
 
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR033 - Return types of ternary if-statement differ",
+                             "ERR037 - Return types of ternary if-statement differ",
                              exprtk_error_location));
 
                result = false;
@@ -21257,15 +22420,15 @@
 
          if (!result)
          {
-            free_node(node_allocator_,  condition);
-            free_node(node_allocator_, consequent);
-            free_node(node_allocator_,alternative);
+            free_node(node_allocator_, condition  );
+            free_node(node_allocator_, consequent );
+            free_node(node_allocator_, alternative);
 
             return error_node();
          }
          else
             return expression_generator_
-                      .conditional(condition,consequent,alternative);
+                      .conditional(condition, consequent, alternative);
       }
 
       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
@@ -21282,7 +22445,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR034 - Failed to parse body of consequent for if-statement",
+                             "ERR038 - Failed to parse body of consequent for if-statement",
                              exprtk_error_location));
 
                result = false;
@@ -21305,7 +22468,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR035 - Expected ';' at the end of the consequent for if-statement",
+                                "ERR039 - Expected ';' at the end of the consequent for if-statement",
                                 exprtk_error_location));
 
                   result = false;
@@ -21316,7 +22479,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR036 - Failed to parse body of consequent for if-statement",
+                             "ERR040 - Failed to parse body of consequent for if-statement",
                              exprtk_error_location));
 
                result = false;
@@ -21336,7 +22499,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR037 - Failed to parse body of the 'else' for if-statement",
+                                   "ERR041 - Failed to parse body of the 'else' for if-statement",
                                    exprtk_error_location));
 
                      result = false;
@@ -21349,7 +22512,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR038 - Failed to parse body of if-else statement",
+                                   "ERR042 - Failed to parse body of if-else statement",
                                    exprtk_error_location));
 
                      result = false;
@@ -21362,7 +22525,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR039 - Expected ';' at the end of the 'else-if' for the if-statement",
+                                   "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement",
                                    exprtk_error_location));
 
                      result = false;
@@ -21373,7 +22536,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR040 - Failed to parse body of the 'else' for if-statement",
+                                "ERR044 - Failed to parse body of the 'else' for if-statement",
                                 exprtk_error_location));
 
                   result = false;
@@ -21392,13 +22555,13 @@
                if (consq_is_str && alter_is_str)
                {
                   return expression_generator_
-                           .conditional_string(condition,consequent,alternative);
+                           .conditional_string(condition, consequent, alternative);
                }
 
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR041 - Return types of ternary if-statement differ",
+                             "ERR045 - Return types of ternary if-statement differ",
                              exprtk_error_location));
 
                result = false;
@@ -21408,15 +22571,15 @@
 
          if (!result)
          {
-            free_node(node_allocator_,  condition);
-            free_node(node_allocator_, consequent);
-            free_node(node_allocator_,alternative);
+            free_node(node_allocator_,   condition);
+            free_node(node_allocator_,  consequent);
+            free_node(node_allocator_, alternative);
 
             return error_node();
          }
          else
             return expression_generator_
-                      .conditional(condition,consequent,alternative);
+                      .conditional(condition, consequent, alternative);
       }
 
       inline expression_node_ptr parse_conditional_statement()
@@ -21430,7 +22593,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR042 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
+                          "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -21440,7 +22603,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR043 - Failed to parse condition for if-statement",
+                          "ERR047 - Failed to parse condition for if-statement",
                           exprtk_error_location));
 
             return error_node();
@@ -21472,7 +22635,7 @@
          set_error(
             make_error(parser_error::e_syntax,
                        current_token(),
-                       "ERR044 - Invalid if-statement",
+                       "ERR048 - Invalid if-statement",
                        exprtk_error_location));
 
          free_node(node_allocator_,condition);
@@ -21493,7 +22656,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR045 - Encountered invalid condition branch for ternary if-statement",
+                          "ERR049 - Encountered invalid condition branch for ternary if-statement",
                           exprtk_error_location));
 
             return error_node();
@@ -21503,7 +22666,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR046 - Expected '?' after condition of ternary if-statement",
+                          "ERR050 - Expected '?' after condition of ternary if-statement",
                           exprtk_error_location));
 
             result = false;
@@ -21513,7 +22676,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR047 - Failed to parse consequent for ternary if-statement",
+                          "ERR051 - Failed to parse consequent for ternary if-statement",
                           exprtk_error_location));
 
             result = false;
@@ -21523,7 +22686,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR048 - Expected ':' between ternary if-statement consequent and alternative",
+                          "ERR052 - Expected ':' between ternary if-statement consequent and alternative",
                           exprtk_error_location));
 
             result = false;
@@ -21533,7 +22696,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR049 - Failed to parse alternative for ternary if-statement",
+                          "ERR053 - Failed to parse alternative for ternary if-statement",
                           exprtk_error_location));
 
             result = false;
@@ -21556,7 +22719,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR050 - Return types of ternary if-statement differ",
+                             "ERR054 - Return types of ternary if-statement differ",
                              exprtk_error_location));
 
                result = false;
@@ -21577,6 +22740,22 @@
                       .conditional(condition, consequent, alternative);
       }
 
+      inline expression_node_ptr parse_not_statement()
+      {
+         if (settings_.logic_disabled("not"))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR055 - Invalid or disabled logic operation 'not'",
+                          exprtk_error_location));
+
+            return error_node();
+         }
+
+         return parse_base_operation();
+      }
+
       inline expression_node_ptr parse_while_loop()
       {
          // Parse: [while][(][test expr][)][{][expression][}]
@@ -21593,7 +22772,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR051 - Expected '(' at start of while-loop condition statement",
+                          "ERR056 - Expected '(' at start of while-loop condition statement",
                           exprtk_error_location));
 
             return error_node();
@@ -21603,7 +22782,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR052 - Failed to parse condition for while-loop",
+                          "ERR057 - Failed to parse condition for while-loop",
                           exprtk_error_location));
 
             return error_node();
@@ -21613,7 +22792,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR053 - Expected ')' at end of while-loop condition statement",
+                          "ERR058 - Expected ')' at end of while-loop condition statement",
                           exprtk_error_location));
 
             result = false;
@@ -21623,12 +22802,14 @@
 
          if (result)
          {
+            scoped_inc_dec sid(state_.parsing_loop_stmt_count);
+
             if (0 == (branch = parse_multi_sequence("while-loop")))
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR054 - Failed to parse body of while-loop"));
+                             "ERR059 - Failed to parse body of while-loop"));
                result = false;
             }
             else if (0 == (result_node = expression_generator_.while_loop(condition,
@@ -21638,7 +22819,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR055 - Failed to synthesize while-loop",
+                             "ERR060 - Failed to synthesize while-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21647,9 +22828,9 @@
 
          if (!result)
          {
-            free_node(node_allocator_,     branch);
-            free_node(node_allocator_,  condition);
-            free_node(node_allocator_,result_node);
+            free_node(node_allocator_,      branch);
+            free_node(node_allocator_,   condition);
+            free_node(node_allocator_, result_node);
 
             brkcnt_list_.pop_front();
 
@@ -21680,12 +22861,14 @@
          }
          else
          {
-            token_t::token_type seperator = token_t::e_eof;
+            const token_t::token_type seperator = token_t::e_eof;
 
             scope_handler sh(*this);
 
             scoped_bool_or_restorer sbr(state_.side_effect_present);
 
+            scoped_inc_dec sid(state_.parsing_loop_stmt_count);
+
             for ( ; ; )
             {
                state_.side_effect_present = false;
@@ -21706,15 +22889,15 @@
                   break;
                }
 
-               bool is_next_until = peek_token_is(token_t::e_symbol) &&
-                                    peek_token_is("until");
+               const bool is_next_until = peek_token_is(token_t::e_symbol) &&
+                                          peek_token_is("until");
 
                if (!token_is(seperator) && is_next_until)
                {
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR056 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
+                                "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
                                 exprtk_error_location));
 
                   return error_node();
@@ -21738,7 +22921,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR057 - Failed to parse body of repeat until loop",
+                             "ERR062 - Failed to parse body of repeat until loop",
                              exprtk_error_location));
 
                return error_node();
@@ -21752,7 +22935,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR058 - Expected '(' before condition statement of repeat until loop",
+                          "ERR063 - Expected '(' before condition statement of repeat until loop",
                           exprtk_error_location));
 
             free_node(node_allocator_,branch);
@@ -21766,7 +22949,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR059 - Failed to parse condition for repeat until loop",
+                          "ERR064 - Failed to parse condition for repeat until loop",
                           exprtk_error_location));
 
             free_node(node_allocator_,branch);
@@ -21778,7 +22961,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR060 - Expected ')' after condition of repeat until loop",
+                          "ERR065 - Expected ')' after condition of repeat until loop",
                           exprtk_error_location));
 
             free_node(node_allocator_,    branch);
@@ -21799,7 +22982,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR061 - Failed to synthesize repeat until loop",
+                          "ERR066 - Failed to synthesize repeat until loop",
                           exprtk_error_location));
 
             free_node(node_allocator_,condition);
@@ -21824,7 +23007,6 @@
 
          scope_element* se = 0;
          bool result       = true;
-         std::string loop_counter_symbol;
 
          next_token();
 
@@ -21835,7 +23017,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR062 - Expected '(' at start of for-loop",
+                          "ERR067 - Expected '(' at start of for-loop",
                           exprtk_error_location));
 
             return error_node();
@@ -21855,7 +23037,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR063 - Expected a variable at the start of initialiser section of for-loop",
+                                "ERR068 - Expected a variable at the start of initialiser section of for-loop",
                                 exprtk_error_location));
 
                   return error_node();
@@ -21865,13 +23047,13 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR064 - Expected variable assignment of initialiser section of for-loop",
+                                "ERR069 - Expected variable assignment of initialiser section of for-loop",
                                 exprtk_error_location));
 
                   return error_node();
                }
 
-               loop_counter_symbol = current_token().value;
+               const std::string loop_counter_symbol = current_token().value;
 
                se = &sem_.get_element(loop_counter_symbol);
 
@@ -21880,7 +23062,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR065 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
+                                "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
                                 exprtk_error_location));
 
                   return error_node();
@@ -21912,7 +23094,7 @@
                         set_error(
                            make_error(parser_error::e_syntax,
                                       current_token(),
-                                      "ERR066 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
+                                      "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
                                       exprtk_error_location));
 
                         sem_.free_element(nse);
@@ -21934,7 +23116,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR067 - Failed to parse initialiser of for-loop",
+                             "ERR072 - Failed to parse initialiser of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21944,7 +23126,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR068 - Expected ';' after initialiser of for-loop",
+                             "ERR073 - Expected ';' after initialiser of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21958,7 +23140,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR069 - Failed to parse condition of for-loop",
+                             "ERR074 - Failed to parse condition of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21968,7 +23150,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR070 - Expected ';' after condition section of for-loop",
+                             "ERR075 - Expected ';' after condition section of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21982,7 +23164,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR071 - Failed to parse incrementor of for-loop",
+                             "ERR076 - Failed to parse incrementor of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -21992,7 +23174,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR072 - Expected ')' after incrementor section of for-loop",
+                             "ERR077 - Expected ')' after incrementor section of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -22003,12 +23185,14 @@
          {
             brkcnt_list_.push_front(false);
 
+            scoped_inc_dec sid(state_.parsing_loop_stmt_count);
+
             if (0 == (loop_body = parse_multi_sequence("for-loop")))
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR073 - Failed to parse body of for-loop",
+                             "ERR078 - Failed to parse body of for-loop",
                              exprtk_error_location));
 
                result = false;
@@ -22022,8 +23206,6 @@
                se->ref_count--;
             }
 
-            sem_.cleanup();
-
             free_node(node_allocator_, initialiser);
             free_node(node_allocator_,   condition);
             free_node(node_allocator_, incrementor);
@@ -22060,7 +23242,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR074 - Expected keyword 'switch'",
+                          "ERR079 - Expected keyword 'switch'",
                           exprtk_error_location));
 
             return error_node();
@@ -22075,84 +23257,99 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR075 - Expected '{' for call to switch statement",
+                          "ERR080 - Expected '{' for call to switch statement",
                           exprtk_error_location));
 
             return error_node();
          }
 
+         expression_node_ptr default_statement = error_node();
+
+         scoped_expression_delete defstmt_delete((*this), default_statement);
+
          for ( ; ; )
          {
-            if (!details::imatch("case",current_token().value))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR076 - Expected either a 'case' or 'default' statement",
-                             exprtk_error_location));
-
-               return error_node();
-            }
-
-            next_token();
-
-            expression_node_ptr condition = parse_expression();
-
-            if (0 == condition)
-               return error_node();
-            else if (!token_is(token_t::e_colon))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR077 - Expected ':' for case of switch statement",
-                             exprtk_error_location));
-
-               return error_node();
-            }
-
-            expression_node_ptr consequent = parse_expression();
-
-            if (0 == consequent)
-               return error_node();
-            else if (!token_is(token_t::e_eof))
-            {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR078 - Expected ';' at end of case for switch statement",
-                             exprtk_error_location));
-
-               return error_node();
-            }
-
-            // Can we optimise away the case statement?
-            if (is_constant_node(condition) && is_false(condition))
-            {
-               free_node(node_allocator_,  condition);
-               free_node(node_allocator_, consequent);
-            }
-            else
-            {
-               arg_list.push_back( condition);
-               arg_list.push_back(consequent);
-            }
-
-            if (details::imatch("default",current_token().value))
+            if (details::imatch("case",current_token().value))
             {
                next_token();
-               if (!token_is(token_t::e_colon))
+
+               expression_node_ptr condition = parse_expression();
+
+               if (0 == condition)
+                  return error_node();
+               else if (!token_is(token_t::e_colon))
                {
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR079 - Expected ':' for default of switch statement",
+                                "ERR081 - Expected ':' for case of switch statement",
+                                exprtk_error_location));
+
+                  free_node(node_allocator_, condition);
+
+                  return error_node();
+               }
+
+               expression_node_ptr consequent = parse_expression();
+
+               if (0 == consequent)
+               {
+                  free_node(node_allocator_, condition);
+
+                  return error_node();
+               }
+               else if (!token_is(token_t::e_eof))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR082 - Expected ';' at end of case for switch statement",
+                                exprtk_error_location));
+
+                  free_node(node_allocator_,  condition);
+                  free_node(node_allocator_, consequent);
+
+                  return error_node();
+               }
+
+               // Can we optimise away the case statement?
+               if (is_constant_node(condition) && is_false(condition))
+               {
+                  free_node(node_allocator_,  condition);
+                  free_node(node_allocator_, consequent);
+               }
+               else
+               {
+                  arg_list.push_back( condition);
+                  arg_list.push_back(consequent);
+               }
+
+            }
+            else if (details::imatch("default",current_token().value))
+            {
+               if (0 != default_statement)
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR083 - Multiple default cases for switch statement",
                                 exprtk_error_location));
 
                   return error_node();
                }
 
-               expression_node_ptr default_statement = error_node();
+               next_token();
+
+               if (!token_is(token_t::e_colon))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR084 - Expected ':' for default of switch statement",
+                                exprtk_error_location));
+
+                  return error_node();
+               }
 
                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
                   default_statement = parse_multi_sequence("switch-default");
@@ -22163,36 +23360,40 @@
                   return error_node();
                else if (!token_is(token_t::e_eof))
                {
-                  free_node(node_allocator_,default_statement);
-
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR080 - Expected ';' at end of default for switch statement",
+                                "ERR085 - Expected ';' at end of default for switch statement",
                                 exprtk_error_location));
 
                   return error_node();
                }
-
-               arg_list.push_back(default_statement);
+            }
+            else if (token_is(token_t::e_rcrlbracket))
                break;
+            else
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR086 - Expected '}' at end of switch statement",
+                             exprtk_error_location));
+
+               return error_node();
             }
          }
 
-         if (!token_is(token_t::e_rcrlbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR081 - Expected '}' at end of switch statement",
-                          exprtk_error_location));
+         const bool default_statement_present = (0 != default_statement);
 
-            return error_node();
+         if (default_statement_present)
+         {
+            arg_list.push_back(default_statement);
          }
 
-         result = expression_generator_.switch_statement(arg_list);
+         result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
 
          svd.delete_ptr = (0 == result);
+         defstmt_delete.delete_ptr = (0 == result);
 
          return result;
       }
@@ -22200,14 +23401,13 @@
       inline expression_node_ptr parse_multi_switch_statement()
       {
          std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
 
          if (!details::imatch(current_token().value,"[*]"))
          {
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR082 - Expected token '[*]'",
+                          "ERR087 - Expected token '[*]'",
                           exprtk_error_location));
 
             return error_node();
@@ -22222,7 +23422,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR083 - Expected '{' for call to [*] statement",
+                          "ERR088 - Expected '{' for call to [*] statement",
                           exprtk_error_location));
 
             return error_node();
@@ -22235,7 +23435,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR084 - Expected a 'case' statement for multi-switch",
+                             "ERR089 - Expected a 'case' statement for multi-switch",
                              exprtk_error_location));
 
                return error_node();
@@ -22253,7 +23453,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR085 - Expected ':' for case of [*] statement",
+                             "ERR090 - Expected ':' for case of [*] statement",
                              exprtk_error_location));
 
                return error_node();
@@ -22269,7 +23469,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR086 - Expected ';' at end of case for [*] statement",
+                             "ERR091 - Expected ';' at end of case for [*] statement",
                              exprtk_error_location));
 
                return error_node();
@@ -22283,7 +23483,7 @@
             }
             else
             {
-               arg_list.push_back(condition);
+               arg_list.push_back( condition);
                arg_list.push_back(consequent);
             }
 
@@ -22298,13 +23498,13 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR087 - Expected '}' at end of [*] statement",
+                          "ERR092 - Expected '}' at end of [*] statement",
                           exprtk_error_location));
 
             return error_node();
          }
 
-         result = expression_generator_.multi_switch_statement(arg_list);
+         const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
 
          svd.delete_ptr = (0 == result);
 
@@ -22314,7 +23514,6 @@
       inline expression_node_ptr parse_vararg_function()
       {
          std::vector<expression_node_ptr> arg_list;
-         expression_node_ptr result = error_node();
 
          details::operator_type opt_type = details::e_default;
          const std::string symbol = current_token().value;
@@ -22328,19 +23527,19 @@
          {
             return parse_multi_switch_statement();
          }
-         else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg ;
-         else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
-         else if (details::imatch(symbol,"max" )) opt_type = details::e_max ;
-         else if (details::imatch(symbol,"min" )) opt_type = details::e_min ;
-         else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor ;
-         else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
-         else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum ;
+         else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
+         else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
+         else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
+         else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
+         else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
+         else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
+         else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
          else
          {
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR088 - Unsupported vararg function: " + symbol,
+                          "ERR093 - Unsupported vararg function: " + symbol,
                           exprtk_error_location));
 
             return error_node();
@@ -22348,7 +23547,7 @@
 
          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
 
-         lodge_symbol(symbol,e_st_function);
+         lodge_symbol(symbol, e_st_function);
 
          next_token();
 
@@ -22357,7 +23556,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR089 - Expected '(' for call to vararg function: " + symbol,
+                          "ERR094 - Expected '(' for call to vararg function: " + symbol,
                           exprtk_error_location));
 
             return error_node();
@@ -22379,14 +23578,14 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR090 - Expected ',' for call to vararg function: " + symbol,
+                             "ERR095 - Expected ',' for call to vararg function: " + symbol,
                              exprtk_error_location));
 
                return error_node();
             }
          }
 
-         result = expression_generator_.vararg_function(opt_type,arg_list);
+         const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
 
          sdd.delete_ptr = (0 == result);
          return result;
@@ -22400,7 +23599,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR091 - Expected '[' as start of string range definition",
+                          "ERR096 - Expected '[' as start of string range definition",
                           exprtk_error_location));
 
             free_node(node_allocator_,expression);
@@ -22428,7 +23627,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR092 - Failed to generate string range node",
+                          "ERR097 - Failed to generate string range node",
                           exprtk_error_location));
 
             free_node(node_allocator_,expression);
@@ -22467,7 +23666,7 @@
 
       template <typename Allocator1,
                 typename Allocator2,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
                                           Sequence<bool,Allocator2>& side_effect_list,
                                           const bool specialise_on_final_type = false)
@@ -22564,7 +23763,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR093 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
+                             "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
                              ((!source.empty()) ? std::string(" section of " + source): ""),
                              exprtk_error_location));
 
@@ -22604,14 +23803,14 @@
             if (token_is(close_bracket))
                break;
 
-            bool is_next_close = peek_token_is(close_bracket);
+            const bool is_next_close = peek_token_is(close_bracket);
 
             if (!token_is(seperator) && is_next_close)
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR094 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
+                             "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
                              exprtk_error_location));
 
                return error_node();
@@ -22645,7 +23844,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR095 - Expected '[' for start of range",
+                          "ERR100 - Expected '[' for start of range",
                           exprtk_error_location));
 
             return false;
@@ -22666,11 +23865,10 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR096 - Failed parse begin section of range",
+                             "ERR101 - Failed parse begin section of range",
                              exprtk_error_location));
 
                return false;
-
             }
             else if (is_constant_node(r0))
             {
@@ -22690,7 +23888,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR097 - Range lower bound less than zero! Constraint: r0 >= 0",
+                                "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0",
                                 exprtk_error_location));
 
                   return false;
@@ -22707,7 +23905,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR098 - Expected ':' for break  in range",
+                             "ERR103 - Expected ':' for break  in range",
                              exprtk_error_location));
 
                rp.free();
@@ -22730,13 +23928,12 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR099 - Failed parse end section of range",
+                             "ERR104 - Failed parse end section of range",
                              exprtk_error_location));
 
                rp.free();
 
                return false;
-
             }
             else if (is_constant_node(r1))
             {
@@ -22756,7 +23953,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR100 - Range upper bound less than zero! Constraint: r1 >= 0",
+                                "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0",
                                 exprtk_error_location));
 
                   return false;
@@ -22773,7 +23970,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR101 - Expected ']' for start of range",
+                             "ERR106 - Expected ']' for start of range",
                              exprtk_error_location));
 
                rp.free();
@@ -22787,14 +23984,21 @@
             std::size_t r0 = 0;
             std::size_t r1 = 0;
 
-            const bool rp_result = rp(r0,r1);
+            bool rp_result = false;
+
+            try
+            {
+               rp_result = rp(r0, r1);
+            }
+            catch (std::runtime_error&)
+            {}
 
             if (!rp_result || (r0 > r1))
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR102 - Invalid range, Constraint: r0 <= r1",
+                             "ERR107 - Invalid range, Constraint: r0 <= r1",
                              exprtk_error_location));
 
                return false;
@@ -22826,7 +24030,7 @@
          {
             se.active = true;
             result    = se.str_node;
-            lodge_symbol(symbol,e_st_local_string);
+            lodge_symbol(symbol, e_st_local_string);
          }
          else
          {
@@ -22835,7 +24039,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR103 - Unknown string symbol",
+                             "ERR108 - Unknown string symbol",
                              exprtk_error_location));
 
                return error_node();
@@ -22849,7 +24053,7 @@
                result = expression_generator_(const_str_node->str());
             }
 
-            lodge_symbol(symbol,e_st_string);
+            lodge_symbol(symbol, e_st_string);
          }
 
          if (peek_token_is(token_t::e_lsqrbracket))
@@ -22929,6 +24133,7 @@
             if (!parse_range(rp))
             {
                free_node(node_allocator_,result);
+               rp.free();
 
                return error_node();
             }
@@ -22949,11 +24154,13 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR104 - Overflow in range for string: '" + const_str + "'[" +
+                             "ERR109 - Overflow in range for string: '" + const_str + "'[" +
                              (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
                              (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
                              exprtk_error_location));
 
+               rp.free();
+
                return error_node();
             }
 
@@ -22993,7 +24200,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR105 - Symbol '" + symbol+ " not a vector",
+                             "ERR110 - Symbol '" + symbol+ " not a vector",
                              exprtk_error_location));
 
                return error_node();
@@ -23019,7 +24226,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR106 - Failed to parse index for vector: '" + symbol + "'",
+                          "ERR111 - Failed to parse index for vector: '" + symbol + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -23029,7 +24236,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR107 - Expected ']' for index of vector: '" + symbol + "'",
+                          "ERR112 - Expected ']' for index of vector: '" + symbol + "'",
                           exprtk_error_location));
 
             free_node(node_allocator_,index_expr);
@@ -23048,7 +24255,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR108 - Index of " + details::to_str(index) + " out of range for "
+                             "ERR113 - Index of " + details::to_str(index) + " out of range for "
                              "vector '" + symbol + "' of size " + details::to_str(vec_size),
                              exprtk_error_location));
 
@@ -23058,7 +24265,7 @@
             }
          }
 
-         return expression_generator_.vector_element(symbol,vec,index_expr);
+         return expression_generator_.vector_element(symbol, vec, index_expr);
       }
 
       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
@@ -23080,7 +24287,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR109 - Zero parameter call to vararg function: "
+                                "ERR114 - Zero parameter call to vararg function: "
                                 + vararg_function_name + " not allowed",
                                 exprtk_error_location));
 
@@ -23105,7 +24312,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR110 - Expected ',' for call to vararg function: "
+                                   "ERR115 - Expected ',' for call to vararg function: "
                                    + vararg_function_name,
                                    exprtk_error_location));
 
@@ -23119,7 +24326,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR111 - Zero parameter call to vararg function: "
+                          "ERR116 - Zero parameter call to vararg function: "
                           + vararg_function_name + " not allowed",
                           exprtk_error_location));
 
@@ -23131,7 +24338,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR112 - Invalid number of parameters to call to vararg function: "
+                          "ERR117 - Invalid number of parameters to call to vararg function: "
                           + vararg_function_name + ", require at least "
                           + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
                           exprtk_error_location));
@@ -23143,7 +24350,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR113 - Invalid number of parameters to call to vararg function: "
+                          "ERR118 - Invalid number of parameters to call to vararg function: "
                           + vararg_function_name + ", require no more than "
                           + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
                           exprtk_error_location));
@@ -23162,34 +24369,54 @@
       {
       public:
 
+         enum return_type_t
+         {
+            e_overload = ' ',
+            e_numeric  = 'T',
+            e_string   = 'S'
+         };
+
+         struct function_prototype_t
+         {
+             return_type_t return_type;
+             std::string   param_seq;
+         };
+
          typedef parser<T> parser_t;
-         typedef std::vector<std::string> param_seq_list_t;
+         typedef std::vector<function_prototype_t> function_definition_list_t;
 
          type_checker(parser_t& p,
                       const std::string& func_name,
-                      const std::string& param_seq)
+                      const std::string& func_prototypes,
+                      const return_type_t default_return_type)
          : invalid_state_(true),
            parser_(p),
-           function_name_(func_name)
+           function_name_(func_name),
+           default_return_type_(default_return_type)
          {
-            split(param_seq);
+            parse_function_prototypes(func_prototypes);
+         }
+
+         void set_default_return_type(const std::string& return_type)
+         {
+            default_return_type_ = return_type;
          }
 
          bool verify(const std::string& param_seq, std::size_t& pseq_index)
          {
-            if (param_seq_list_.empty())
+            if (function_definition_list_.empty())
                return true;
 
             std::vector<std::pair<std::size_t,char> > error_list;
 
-            for (std::size_t i = 0; i < param_seq_list_.size(); ++i)
+            for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
             {
                details::char_t diff_value = 0;
                std::size_t     diff_index = 0;
 
-               bool result = details::sequence_match(param_seq_list_[i],
-                                                     param_seq,
-                                                     diff_index,diff_value);
+               const bool result = details::sequence_match(function_definition_list_[i].param_seq,
+                                                           param_seq,
+                                                           diff_index, diff_value);
 
               if (result)
               {
@@ -23197,7 +24424,7 @@
                  return true;
               }
               else
-                 error_list.push_back(std::make_pair(diff_index,diff_value));
+                 error_list.push_back(std::make_pair(diff_index, diff_value));
             }
 
             if (1 == error_list.size())
@@ -23206,8 +24433,9 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 parser_.current_token(),
-                                "ERR114 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Expected '" + param_seq_list_[0] + "'  call set: '" + param_seq +"'",
+                                "ERR119 - Failed parameter type check for function '" + function_name_ + "', "
+                                "Expected '" + function_definition_list_[0].param_seq +
+                                "'  call set: '" + param_seq + "'",
                                 exprtk_error_location));
             }
             else
@@ -23227,8 +24455,9 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 parser_.current_token(),
-                                "ERR115 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Best match: '" + param_seq_list_[max_diff_index] + "'  call set: '" + param_seq +"'",
+                                "ERR120 - Failed parameter type check for function '" + function_name_ + "', "
+                                "Best match: '" + function_definition_list_[max_diff_index].param_seq +
+                                "'  call set: '" + param_seq + "'",
                                 exprtk_error_location));
             }
 
@@ -23237,12 +24466,17 @@
 
          std::size_t paramseq_count() const
          {
-            return param_seq_list_.size();
+            return function_definition_list_.size();
          }
 
          std::string paramseq(const std::size_t& index) const
          {
-            return param_seq_list_[index];
+            return function_definition_list_[index].param_seq;
+         }
+
+         return_type_t return_type(const std::size_t& index) const
+         {
+            return function_definition_list_[index].return_type;
          }
 
          bool invalid() const
@@ -23252,93 +24486,142 @@
 
          bool allow_zero_parameters() const
          {
-            return
-               param_seq_list_.end() != std::find(param_seq_list_.begin(),
-                                                  param_seq_list_.end(),
-                                                  "Z");
+
+            for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
+            {
+               if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
+               {
+                  return true;
+               }
+            }
+
+            return false;
          }
 
       private:
 
-         void split(const std::string& s)
+         std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
          {
-            if (s.empty())
-               return;
+             std::string::const_iterator current_begin = param_seq.begin();
+             std::string::const_iterator iter          = param_seq.begin();
 
-            std::size_t start = 0;
-            std::size_t end   = 0;
+             std::vector<std::string> result;
 
-            param_seq_list_t param_seq_list;
+             while (iter != param_seq.end())
+             {
+                 if (*iter == delimiter)
+                 {
+                     result.push_back(std::string(current_begin, iter));
+                     current_begin = ++iter;
+                 }
+                 else
+                     ++iter;
+             }
 
-            struct token_validator
+             if (current_begin != iter)
+             {
+                 result.push_back(std::string(current_begin, iter));
+             }
+
+             return result;
+         }
+
+         inline bool is_valid_token(std::string param_seq,
+                                    function_prototype_t& funcproto) const
+         {
+            // Determine return type
+            funcproto.return_type = default_return_type_;
+
+            if (param_seq.size() > 2)
             {
-               static inline bool process(const std::string& str,
-                                          std::size_t s, std::size_t e,
-                                          param_seq_list_t& psl)
+               if (':' == param_seq[1])
                {
-                  if (
-                       (e - s) &&
-                       (std::string::npos == str.find("?*")) &&
-                       (std::string::npos == str.find("**"))
-                     )
-                  {
-                     const std::string curr_str = str.substr(s, e - s);
+                  // Note: Only overloaded igeneric functions can have return
+                  // type definitions.
+                  if (type_checker::e_overload != default_return_type_)
+                     return false;
 
-                     if ("Z" == curr_str)
-                     {
-                        psl.push_back(curr_str);
-                        return true;
-                     }
-                     else if (std::string::npos == curr_str.find_first_not_of("STV*?|"))
-                     {
-                        psl.push_back(curr_str);
-                        return true;
-                     }
+                  switch (param_seq[0])
+                  {
+                     case 'T' : funcproto.return_type = type_checker::e_numeric;
+                                break;
+
+                     case 'S' : funcproto.return_type = type_checker::e_string;
+                                break;
+
+                     default  : return false;
                   }
 
-                  return false;
+                  param_seq.erase(0,2);
                }
-            };
+            }
 
-            while (std::string::npos != (end = s.find('|',start)))
+            if (
+                 (std::string::npos != param_seq.find("?*")) ||
+                 (std::string::npos != param_seq.find("**"))
+               )
             {
-               if (!token_validator::process(s, start, end, param_seq_list))
+               return false;
+            }
+            else if (
+                      (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
+                      ("Z" == param_seq)
+                    )
+            {
+               funcproto.param_seq = param_seq;
+               return true;
+            }
+
+            return false;
+         }
+
+         void parse_function_prototypes(const std::string& func_prototypes)
+         {
+            if (func_prototypes.empty())
+               return;
+
+            std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
+
+            typedef std::map<std::string,std::size_t> param_seq_map_t;
+            param_seq_map_t param_seq_map;
+
+            for (std::size_t i = 0; i < param_seq_list.size(); ++i)
+            {
+               function_prototype_t func_proto;
+
+               if (!is_valid_token(param_seq_list[i], func_proto))
                {
                   invalid_state_ = false;
 
-                  const std::string err_param_seq = s.substr(start, end - start);
-
                   parser_.
                      set_error(
                         make_error(parser_error::e_syntax,
                                    parser_.current_token(),
-                                   "ERR116 - Invalid parameter sequence of '" + err_param_seq +
-                                   "'  for function: " + function_name_,
+                                   "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] +
+                                   "' for function: " + function_name_,
                                    exprtk_error_location));
-
                   return;
                }
-               else
-                  start = end + 1;
-            }
 
-            if (start < s.size())
-            {
-               if (token_validator::process(s, start, s.size(), param_seq_list))
-                  param_seq_list_ = param_seq_list;
-               else
+               param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
+
+               if (param_seq_map.end() != seq_itr)
                {
-                  const std::string err_param_seq = s.substr(start, s.size() - start);
+                  invalid_state_ = false;
 
                   parser_.
                      set_error(
                         make_error(parser_error::e_syntax,
                                    parser_.current_token(),
-                                   "ERR117 - Invalid parameter sequence of '" + err_param_seq +
-                                   "'  for function: " + function_name_,
+                                   "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
+                                   "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
+                                   "pseq_idx[" + details::to_str(i) + "] " +
+                                   "param seq: " + param_seq_list[i],
                                    exprtk_error_location));
                   return;
                }
+
+               function_definition_list_.push_back(func_proto);
             }
          }
 
@@ -23348,7 +24631,8 @@
          bool invalid_state_;
          parser_t& parser_;
          std::string function_name_;
-         param_seq_list_t param_seq_list_;
+         const return_type_t default_return_type_;
+         function_definition_list_t function_definition_list_;
       };
 
       inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
@@ -23361,30 +24645,14 @@
 
          std::string param_type_list;
 
-         type_checker tc((*this), function_name, function->parameter_sequence);
+         type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
 
          if (tc.invalid())
          {
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR118 - Type checker instantiation failure for generic function: " + function_name,
-                          exprtk_error_location));
-
-            return error_node();
-         }
-
-         if (
-              !function->parameter_sequence.empty() &&
-              function->allow_zero_parameters    () &&
-              !tc      .allow_zero_parameters    ()
-            )
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR119 - Mismatch in zero parameter condition for generic function: "
-                          + function_name,
+                          "ERR123 - Type checker instantiation failure for generic function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -23402,7 +24670,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR120 - Zero parameter call to generic function: "
+                                "ERR124 - Zero parameter call to generic function: "
                                 + function_name + " not allowed",
                                 exprtk_error_location));
 
@@ -23434,7 +24702,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR121 - Expected ',' for call to generic function: " + function_name,
+                                   "ERR125 - Expected ',' for call to generic function: " + function_name,
                                    exprtk_error_location));
 
                      return error_node();
@@ -23451,7 +24719,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR122 - Zero parameter call to generic function: "
+                          "ERR126 - Zero parameter call to generic function: "
                           + function_name + " not allowed",
                           exprtk_error_location));
 
@@ -23468,7 +24736,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR123 - Expected ',' for call to generic function: " + function_name,
+                          "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -23488,37 +24756,39 @@
          return result;
       }
 
-      #ifndef exprtk_disable_string_capabilities
-      inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
+      inline bool parse_igeneric_function_params(std::string& param_type_list,
+                                                 std::vector<expression_node_ptr>& arg_list,
+                                                 const std::string& function_name,
+                                                 igeneric_function<T>* function,
+                                                 const type_checker& tc)
       {
-         std::vector<expression_node_ptr> arg_list;
-
-         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
-
-         next_token();
-
-         std::string param_type_list;
-
-         type_checker tc((*this), function_name, function->parameter_sequence);
-
-         if (
-              (!function->parameter_sequence.empty()) &&
-              (0 == tc.paramseq_count())
-            )
-         {
-            return error_node();
-         }
-
          if (token_is(token_t::e_lbracket))
          {
-            if (!token_is(token_t::e_rbracket))
+            if (token_is(token_t::e_rbracket))
+            {
+               if (
+                    !function->allow_zero_parameters() &&
+                    !tc       .allow_zero_parameters()
+                  )
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR128 - Zero parameter call to generic function: "
+                                + function_name + " not allowed",
+                                exprtk_error_location));
+
+                  return false;
+               }
+            }
+            else
             {
                for ( ; ; )
                {
                   expression_node_ptr arg = parse_expression();
 
                   if (0 == arg)
-                     return error_node();
+                     return false;
 
                   if (is_ivector_node(arg))
                      param_type_list += 'V';
@@ -23536,13 +24806,44 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR124 - Expected ',' for call to string function: " + function_name,
+                                   "ERR129 - Expected ',' for call to string function: " + function_name,
                                    exprtk_error_location));
 
-                     return error_node();
+                     return false;
                   }
                }
             }
+
+            return true;
+         }
+         else
+            return false;
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
+      {
+         // Move pass the function name
+         next_token();
+
+         std::string param_type_list;
+
+         type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
+
+         if (
+              (!function->parameter_sequence.empty()) &&
+              (0 == tc.paramseq_count())
+            )
+         {
+            return error_node();
+         }
+
+         std::vector<expression_node_ptr> arg_list;
+         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
+
+         if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
+         {
+            return error_node();
          }
 
          std::size_t param_seq_index = 0;
@@ -23552,7 +24853,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR125 - Expected ',' for call to string function: " + function_name,
+                          "ERR130 - Invalid input parameter sequence for call to string function: " + function_name,
                           exprtk_error_location));
 
             return error_node();
@@ -23571,17 +24872,88 @@
 
          return result;
       }
+
+      inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
+      {
+         // Move pass the function name
+         next_token();
+
+         std::string param_type_list;
+
+         type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
+
+         if (
+              (!function->parameter_sequence.empty()) &&
+              (0 == tc.paramseq_count())
+            )
+         {
+            return error_node();
+         }
+
+         std::vector<expression_node_ptr> arg_list;
+         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
+
+         if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
+         {
+            return error_node();
+         }
+
+         std::size_t param_seq_index = 0;
+
+         if (!tc.verify(param_type_list, param_seq_index))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name,
+                          exprtk_error_location));
+
+            return error_node();
+         }
+
+         expression_node_ptr result = error_node();
+
+         if (type_checker::e_numeric == tc.return_type(param_seq_index))
+         {
+            if (tc.paramseq_count() <= 1)
+               result = expression_generator_
+                          .generic_function_call(function, arg_list);
+            else
+               result = expression_generator_
+                          .generic_function_call(function, arg_list, param_seq_index);
+         }
+         else if (type_checker::e_string == tc.return_type(param_seq_index))
+         {
+            if (tc.paramseq_count() <= 1)
+               result = expression_generator_
+                          .string_function_call(function, arg_list);
+            else
+               result = expression_generator_
+                          .string_function_call(function, arg_list, param_seq_index);
+         }
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR132 - Invalid return type for call to overloaded function: " + function_name,
+                          exprtk_error_location));
+         }
+
+         sdd.delete_ptr = (0 == result);
+         return result;
+      }
       #endif
 
       template <typename Type, std::size_t NumberOfParameters>
       struct parse_special_function_impl
       {
-         static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)
+         static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
          {
             expression_node_ptr branch[NumberOfParameters];
-            expression_node_ptr result  = error_node();
+            expression_node_ptr result = error_node();
 
-            std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
+            std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
 
             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
 
@@ -23592,7 +24964,7 @@
                p.set_error(
                     make_error(parser_error::e_syntax,
                                p.current_token(),
-                               "ERR126 - Expected '(' for special function",
+                               "ERR133 - Expected '(' for special function '" + sf_name + "'",
                                exprtk_error_location));
 
                return error_node();
@@ -23613,7 +24985,7 @@
                      p.set_error(
                           make_error(parser_error::e_syntax,
                                      p.current_token(),
-                                     "ERR127 - Expected ',' before next parameter of special function",
+                                     "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'",
                                      exprtk_error_location));
 
                      return p.error_node();
@@ -23622,7 +24994,15 @@
             }
 
             if (!p.token_is(token_t::e_rbracket))
+            {
+               p.set_error(
+                    make_error(parser_error::e_syntax,
+                               p.current_token(),
+                               "ERR135 - Invalid number of parameters for special function '" + sf_name + "'",
+                               exprtk_error_location));
+
                return p.error_node();
+            }
             else
                result = p.expression_generator_.special_function(opt_type,branch);
 
@@ -23634,30 +25014,32 @@
 
       inline expression_node_ptr parse_special_function()
       {
+         const std::string sf_name = current_token().value;
+
          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
          if (
-              !details::is_digit(current_token().value[2]) ||
-              !details::is_digit(current_token().value[3])
+              !details::is_digit(sf_name[2]) ||
+              !details::is_digit(sf_name[3])
             )
          {
             set_error(
                make_error(parser_error::e_token,
                           current_token(),
-                          "ERR128 - Invalid special function[1]: " + current_token().value,
+                          "ERR136 - Invalid special function[1]: " + sf_name,
                           exprtk_error_location));
 
             return error_node();
          }
 
-         const int id = (current_token().value[2] - '0') * 10 +
-                        (current_token().value[3] - '0');
+         const int id = (sf_name[2] - '0') * 10 +
+                        (sf_name[3] - '0');
 
          if (id >= details::e_sffinal)
          {
             set_error(
                make_error(parser_error::e_token,
                           current_token(),
-                          "ERR129 - Invalid special function[2]: " + current_token().value,
+                          "ERR137 - Invalid special function[2]: " + sf_name,
                           exprtk_error_location));
 
             return error_node();
@@ -23669,8 +25051,8 @@
 
          switch (NumberOfParameters)
          {
-            case 3  : return parse_special_function_impl<T,3>::process((*this),opt_type);
-            case 4  : return parse_special_function_impl<T,4>::process((*this),opt_type);
+            case 3  : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
+            case 4  : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
             default : return error_node();
          }
       }
@@ -23689,7 +25071,17 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR130 - Break call within a break call is not allowed",
+                          "ERR138 - Invoking 'break' within a break call is not allowed",
+                          exprtk_error_location));
+
+            return error_node();
+         }
+         else if (0 == state_.parsing_loop_stmt_count)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
                           exprtk_error_location));
 
             return error_node();
@@ -23712,7 +25104,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR131 - Failed to parse return expression for 'break' statement",
+                                "ERR140 - Failed to parse return expression for 'break' statement",
                                 exprtk_error_location));
 
                   return error_node();
@@ -23722,7 +25114,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR132 - Expected ']' at the completion of break's return expression",
+                                "ERR141 - Expected ']' at the completion of break's return expression",
                                 exprtk_error_location));
 
                   free_node(node_allocator_,return_expr);
@@ -23740,7 +25132,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR133 - Invalid use of 'break', allowed only in the scope of a loop",
+                          "ERR142 - Invalid use of 'break', allowed only in the scope of a loop",
                           exprtk_error_location));
          }
 
@@ -23749,7 +25141,17 @@
 
       inline expression_node_ptr parse_continue_statement()
       {
-         if (!brkcnt_list_.empty())
+         if (0 == state_.parsing_loop_stmt_count)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop",
+                          exprtk_error_location));
+
+            return error_node();
+         }
+         else
          {
             next_token();
 
@@ -23758,16 +25160,6 @@
 
             return node_allocator_.allocate<details::continue_node<T> >();
          }
-         else
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR134 - Invalid use of 'continue', allowed only in the scope of a loop",
-                          exprtk_error_location));
-
-            return error_node();
-         }
       }
       #endif
 
@@ -23780,7 +25172,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR135 - Expected '[' as part of vector size definition",
+                          "ERR144 - Expected '[' as part of vector size definition",
                           exprtk_error_location));
 
             return error_node();
@@ -23790,7 +25182,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR136 - Failed to determine size of vector '" + vec_name + "'",
+                          "ERR145 - Failed to determine size of vector '" + vec_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -23802,26 +25194,29 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR137 - Expected a literal number as size of vector '" + vec_name + "'",
+                          "ERR146 - Expected a literal number as size of vector '" + vec_name + "'",
                           exprtk_error_location));
 
             return error_node();
          }
 
-         T vector_size = size_expr->value();
+         const T vector_size = size_expr->value();
 
          free_node(node_allocator_,size_expr);
 
+         const T max_vector_size = T(2000000000.0);
+
          if (
               (vector_size <= T(0)) ||
               std::not_equal_to<T>()
-              (T(0),vector_size - details::numeric::trunc(vector_size))
+              (T(0),vector_size - details::numeric::trunc(vector_size)) ||
+              (vector_size > max_vector_size)
             )
          {
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR138 - Invalid vector size. Must be an integer greater than zero, size: " +
+                          "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
                           details::to_str(details::numeric::to_int32(vector_size)),
                           exprtk_error_location));
 
@@ -23841,7 +25236,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR139 - Expected ']' as part of vector size definition",
+                          "ERR148 - Expected ']' as part of vector size definition",
                           exprtk_error_location));
 
             return error_node();
@@ -23853,7 +25248,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR140 - Expected ':=' as part of vector definition",
+                             "ERR149 - Expected ':=' as part of vector definition",
                              exprtk_error_location));
 
                return error_node();
@@ -23867,7 +25262,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR141 - Failed to parse single vector initialiser",
+                                "ERR150 - Failed to parse single vector initialiser",
                                 exprtk_error_location));
 
                   return error_node();
@@ -23880,7 +25275,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR142 - Expected ']' to close single value vector initialiser",
+                                "ERR151 - Expected ']' to close single value vector initialiser",
                                 exprtk_error_location));
 
                   return error_node();
@@ -23896,7 +25291,7 @@
                if (token_t::e_symbol == current_token().type)
                {
                   // Is it a locally defined vector?
-                  scope_element& se = sem_.get_active_element(current_token().value);
+                  const scope_element& se = sem_.get_active_element(current_token().value);
 
                   if (scope_element::e_vector == se.type)
                   {
@@ -23908,7 +25303,7 @@
                   // Are we dealing with a user defined vector?
                   else if (symtab_store_.is_vector(current_token().value))
                   {
-                     lodge_symbol(current_token().value,e_st_vector);
+                     lodge_symbol(current_token().value, e_st_vector);
 
                      if (0 != (initialiser = parse_expression()))
                         vec_initilizer_list.push_back(initialiser);
@@ -23927,7 +25322,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR143 - Expected '{' as part of vector initialiser list",
+                                   "ERR152 - Expected '{' as part of vector initialiser list",
                                    exprtk_error_location));
 
                      return error_node();
@@ -23947,7 +25342,7 @@
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR144 - Expected '{' as part of vector initialiser list",
+                                   "ERR153 - Expected '{' as part of vector initialiser list",
                                    exprtk_error_location));
 
                      return error_node();
@@ -23958,14 +25353,14 @@
                   if (token_is(token_t::e_rcrlbracket))
                      break;
 
-                  bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
+                  const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
 
                   if (!token_is(token_t::e_comma) && is_next_close)
                   {
                      set_error(
                         make_error(parser_error::e_syntax,
                                    current_token(),
-                                   "ERR145 - Expected ',' between vector initialisers",
+                                   "ERR154 - Expected ',' between vector initialisers",
                                    exprtk_error_location));
 
                      return error_node();
@@ -23977,9 +25372,9 @@
             }
 
             if (
-                 !token_is(token_t::e_rbracket   ,prsrhlpr_t::e_hold) &&
-                 !token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold) &&
-                 !token_is(token_t::e_rsqrbracket,prsrhlpr_t::e_hold)
+                 !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
+                 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
+                 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
                )
             {
                if (!token_is(token_t::e_eof))
@@ -23987,7 +25382,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR146 - Expected ';' at end of vector definition",
+                                "ERR155 - Expected ';' at end of vector definition",
                                 exprtk_error_location));
 
                   return error_node();
@@ -23999,7 +25394,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR147 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
+                             "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -24019,7 +25414,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR148 - Illegal redefinition of local vector: '" + vec_name + "'",
+                             "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -24053,7 +25448,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR149 - Failed to add new local vector '" + vec_name + "' to SEM",
+                             "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM",
                              exprtk_error_location));
 
                sem_.free_element(nse);
@@ -24070,17 +25465,21 @@
 
          state_.activate_side_effect("parse_define_vector_statement()");
 
-         lodge_symbol(vec_name,e_st_local_vector);
+         lodge_symbol(vec_name, e_st_local_vector);
 
          expression_node_ptr result = error_node();
 
          if (null_initialisation)
             result = expression_generator_(T(0.0));
          else if (vec_to_vec_initialiser)
+         {
+            expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
+
             result = expression_generator_(
                         details::e_assign,
-                        node_allocator_.allocate<vector_node_t>(vec_holder),
+                        vec_node,
                         vec_initilizer_list[0]);
+         }
          else
             result = node_allocator_
                         .allocate<details::vector_assignment_node<T> >(
@@ -24108,7 +25507,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR150 - Illegal redefinition of local variable: '" + str_name + "'",
+                             "ERR159 - Illegal redefinition of local variable: '" + str_name + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -24140,7 +25539,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR151 - Failed to add new local string variable '" + str_name + "' to SEM",
+                             "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -24155,7 +25554,7 @@
             exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
          }
 
-         lodge_symbol(str_name,e_st_local_string);
+         lodge_symbol(str_name, e_st_local_string);
 
          state_.activate_side_effect("parse_define_string_statement()");
 
@@ -24186,7 +25585,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR152 - Illegal variable definition",
+                          "ERR161 - Illegal variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -24207,7 +25606,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR153 - Expected a symbol for variable definition",
+                          "ERR162 - Expected a symbol for variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -24217,7 +25616,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR154 - Illegal redefinition of reserved keyword: '" + var_name + "'",
+                          "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -24227,7 +25626,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR155 - Illegal redefinition of variable '" + var_name + "'",
+                          "ERR164 - Illegal redefinition of variable '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -24237,7 +25636,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR156 - Illegal redefinition of local variable: '" + var_name + "'",
+                          "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
                           exprtk_error_location));
 
             return error_node();
@@ -24257,7 +25656,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR157 - Failed to parse initialisation expression",
+                             "ERR166 - Failed to parse initialisation expression",
                              exprtk_error_location));
 
                return error_node();
@@ -24265,9 +25664,9 @@
          }
 
          if (
-              !token_is(token_t::e_rbracket   ,prsrhlpr_t::e_hold) &&
-              !token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold) &&
-              !token_is(token_t::e_rsqrbracket,prsrhlpr_t::e_hold)
+              !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
+              !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
+              !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
             )
          {
             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
@@ -24275,7 +25674,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR158 - Expected ';' after variable definition",
+                             "ERR167 - Expected ';' after variable definition",
                              exprtk_error_location));
 
                free_node(node_allocator_,initialisation_expression);
@@ -24303,7 +25702,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR159 - Illegal redefinition of local variable: '" + var_name + "'",
+                             "ERR168 - Illegal redefinition of local variable: '" + var_name + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
@@ -24335,7 +25734,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR160 - Failed to add new local variable '" + var_name + "' to SEM",
+                             "ERR169 - Failed to add new local variable '" + var_name + "' to SEM",
                              exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
@@ -24352,7 +25751,7 @@
 
          state_.activate_side_effect("parse_define_var_statement()");
 
-         lodge_symbol(var_name,e_st_local_variable);
+         lodge_symbol(var_name, e_st_local_variable);
 
          expression_node_ptr branch[2] = {0};
 
@@ -24372,7 +25771,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR161 - Expected a '{}' for uninitialised var definition",
+                          "ERR170 - Expected a '{}' for uninitialised var definition",
                           exprtk_error_location));
 
             return error_node();
@@ -24382,7 +25781,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR162 - Expected ';' after uninitialised variable definition",
+                          "ERR171 - Expected ';' after uninitialised variable definition",
                           exprtk_error_location));
 
             return error_node();
@@ -24399,7 +25798,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR163 - Illegal redefinition of local variable: '" + var_name + "'",
+                             "ERR172 - Illegal redefinition of local variable: '" + var_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -24429,7 +25828,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR164 - Failed to add new local variable '" + var_name + "' to SEM",
+                             "ERR173 - Failed to add new local variable '" + var_name + "' to SEM",
                              exprtk_error_location));
 
                sem_.free_element(nse);
@@ -24441,7 +25840,7 @@
                           nse.name.c_str()));
          }
 
-         lodge_symbol(var_name,e_st_local_variable);
+         lodge_symbol(var_name, e_st_local_variable);
 
          state_.activate_side_effect("parse_uninitialised_var_statement()");
 
@@ -24462,7 +25861,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR165 - Expected '(' at start of swap statement",
+                          "ERR174 - Expected '(' at start of swap statement",
                           exprtk_error_location));
 
             return error_node();
@@ -24481,7 +25880,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR166 - Expected a symbol for variable or vector element definition",
+                          "ERR175 - Expected a symbol for variable or vector element definition",
                           exprtk_error_location));
 
             return error_node();
@@ -24493,7 +25892,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR167 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
+                             "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -24508,7 +25907,7 @@
                variable0 = symtab_store_.get_variable(var0_name);
             }
 
-            scope_element& se = sem_.get_element(var0_name);
+            const scope_element& se = sem_.get_element(var0_name);
 
             if (
                  (se.active)            &&
@@ -24519,14 +25918,14 @@
                variable0 = se.var_node;
             }
 
-            lodge_symbol(var0_name,e_st_variable);
+            lodge_symbol(var0_name, e_st_variable);
 
             if (0 == variable0)
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR168 - First parameter to swap is an invalid variable: '" + var0_name + "'",
+                             "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'",
                              exprtk_error_location));
 
                return error_node();
@@ -24540,7 +25939,7 @@
             set_error(
                 make_error(parser_error::e_syntax,
                            current_token(),
-                           "ERR169 - Expected ',' between parameters to swap",
+                           "ERR178 - Expected ',' between parameters to swap",
                            exprtk_error_location));
 
             if (variable0_generated)
@@ -24558,7 +25957,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR170 - Expected a symbol for variable or vector element definition",
+                          "ERR179 - Expected a symbol for variable or vector element definition",
                           exprtk_error_location));
 
             if (variable0_generated)
@@ -24575,7 +25974,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR171 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
+                             "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
                              exprtk_error_location));
 
                if (variable0_generated)
@@ -24595,7 +25994,7 @@
                variable1 = symtab_store_.get_variable(var1_name);
             }
 
-            scope_element& se = sem_.get_element(var1_name);
+            const scope_element& se = sem_.get_element(var1_name);
 
             if (
                  (se.active) &&
@@ -24606,14 +26005,14 @@
                variable1 = se.var_node;
             }
 
-            lodge_symbol(var1_name,e_st_variable);
+            lodge_symbol(var1_name, e_st_variable);
 
             if (0 == variable1)
             {
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR172 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
+                             "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
                              exprtk_error_location));
 
                if (variable0_generated)
@@ -24632,7 +26031,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR173 - Expected ')' at end of swap statement",
+                          "ERR182 - Expected ')' at end of swap statement",
                           exprtk_error_location));
 
             if (variable0_generated)
@@ -24689,7 +26088,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR174 - Return call within a return call is not allowed",
+                          "ERR183 - Return call within a return call is not allowed",
                           exprtk_error_location));
 
             return error_node();
@@ -24713,7 +26112,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR175 - Expected '[' at start of return statement",
+                          "ERR184 - Expected '[' at start of return statement",
                           exprtk_error_location));
 
             return error_node();
@@ -24736,7 +26135,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR176 - Expected ',' between values during call to return",
+                                "ERR185 - Expected ',' between values during call to return",
                                 exprtk_error_location));
 
                   return error_node();
@@ -24748,13 +26147,13 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR177 - Zero parameter return statement not allowed",
+                          "ERR186 - Zero parameter return statement not allowed",
                           exprtk_error_location));
 
             return error_node();
          }
 
-         lexer::token prev_token = current_token();
+         const lexer::token prev_token = current_token();
 
          if (token_is(token_t::e_rsqrbracket))
          {
@@ -24763,7 +26162,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              prev_token,
-                             "ERR178 - Invalid ']' found during return call",
+                             "ERR187 - Invalid ']' found during return call",
                              exprtk_error_location));
 
                return error_node();
@@ -24816,7 +26215,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR179 - Invalid sequence of variable '"+ symbol + "' and bracket",
+                             "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket",
                              exprtk_error_location));
 
                return false;
@@ -24864,7 +26263,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR180 - Invalid sequence of brackets",
+                             "ERR189 - Invalid sequence of brackets",
                              exprtk_error_location));
 
                return false;
@@ -24897,7 +26296,7 @@
             if (!post_variable_process(symbol))
                return error_node();
 
-            lodge_symbol(symbol,e_st_variable);
+            lodge_symbol(symbol, e_st_variable);
             next_token();
 
             return variable;
@@ -24913,7 +26312,7 @@
                if (scope_element::e_variable == se.type)
                {
                   se.active = true;
-                  lodge_symbol(symbol,e_st_local_variable);
+                  lodge_symbol(symbol, e_st_local_variable);
 
                   if (!post_variable_process(symbol))
                      return error_node();
@@ -24949,7 +26348,7 @@
 
             if (function)
             {
-               lodge_symbol(symbol,e_st_function);
+               lodge_symbol(symbol, e_st_function);
 
                expression_node_ptr func_node =
                                       parse_function_invocation(function,symbol);
@@ -24961,7 +26360,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR181 - Failed to generate node for function: '" + symbol + "'",
+                                "ERR190 - Failed to generate node for function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -24975,7 +26374,7 @@
 
             if (vararg_function)
             {
-               lodge_symbol(symbol,e_st_function);
+               lodge_symbol(symbol, e_st_function);
 
                expression_node_ptr vararg_func_node =
                                       parse_vararg_function_call(vararg_function, symbol);
@@ -24987,7 +26386,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR182 - Failed to generate node for vararg function: '" + symbol + "'",
+                                "ERR191 - Failed to generate node for vararg function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25001,7 +26400,7 @@
 
             if (generic_function)
             {
-               lodge_symbol(symbol,e_st_function);
+               lodge_symbol(symbol, e_st_function);
 
                expression_node_ptr genericfunc_node =
                                       parse_generic_function_call(generic_function, symbol);
@@ -25013,7 +26412,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR183 - Failed to generate node for generic function: '" + symbol + "'",
+                                "ERR192 - Failed to generate node for generic function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25028,7 +26427,7 @@
 
             if (string_function)
             {
-               lodge_symbol(symbol,e_st_function);
+               lodge_symbol(symbol, e_st_function);
 
                expression_node_ptr stringfunc_node =
                                       parse_string_function_call(string_function, symbol);
@@ -25040,7 +26439,33 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR184 - Failed to generate node for string function: '" + symbol + "'",
+                                "ERR193 - Failed to generate node for string function: '" + symbol + "'",
+                                exprtk_error_location));
+
+                  return error_node();
+               }
+            }
+         }
+
+         {
+            // Are we dealing with a vararg overloaded scalar/string returning function?
+            igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
+
+            if (overload_function)
+            {
+               lodge_symbol(symbol, e_st_function);
+
+               expression_node_ptr overloadfunc_node =
+                                      parse_overload_function_call(overload_function, symbol);
+
+               if (overloadfunc_node)
+                  return overloadfunc_node;
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR194 - Failed to generate node for overload function: '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25052,7 +26477,7 @@
          // Are we dealing with a vector?
          if (symtab_store_.is_vector(symbol))
          {
-            lodge_symbol(symbol,e_st_vector);
+            lodge_symbol(symbol, e_st_vector);
             return parse_vector();
          }
 
@@ -25066,7 +26491,7 @@
                   set_error(
                      make_error(parser_error::e_syntax,
                                 current_token(),
-                                "ERR185 - Invalid use of reserved symbol '" + symbol + "'",
+                                "ERR195 - Invalid use of reserved symbol '" + symbol + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25086,7 +26511,7 @@
                {
                   T default_value = T(0);
 
-                  typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
+                  typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
 
                   if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
                   {
@@ -25114,7 +26539,7 @@
                               var = expression_generator_(var->value());
                            }
 
-                           lodge_symbol(symbol,e_st_variable);
+                           lodge_symbol(symbol, e_st_variable);
 
                            if (!post_variable_process(symbol))
                               return error_node();
@@ -25129,7 +26554,7 @@
                   set_error(
                      make_error(parser_error::e_symtab,
                                 current_token(),
-                                "ERR186 - Failed to create variable: '" + symbol + "'" +
+                                "ERR196 - Failed to create variable: '" + symbol + "'" +
                                 (error_message.empty() ? "" : " - " + error_message),
                                 exprtk_error_location));
 
@@ -25149,7 +26574,7 @@
                   set_error(
                      make_error(parser_error::e_symtab,
                                 current_token(),
-                                "ERR187 - Failed to resolve symbol: '" + symbol + "'" +
+                                "ERR197 - Failed to resolve symbol: '" + symbol + "'" +
                                 (error_message.empty() ? "" : " - " + error_message),
                                 exprtk_error_location));
                }
@@ -25161,7 +26586,7 @@
          set_error(
             make_error(parser_error::e_syntax,
                        current_token(),
-                       "ERR188 - Undefined symbol: '" + symbol + "'",
+                       "ERR198 - Undefined symbol: '" + symbol + "'",
                        exprtk_error_location));
 
          return error_node();
@@ -25180,11 +26605,16 @@
          static const std::string symbol_var      = "var"     ;
          static const std::string symbol_swap     = "swap"    ;
          static const std::string symbol_return   = "return"  ;
+         static const std::string symbol_not      = "not"     ;
 
          if (valid_vararg_operation(current_token().value))
          {
             return parse_vararg_function();
          }
+         else if (details::imatch(current_token().value, symbol_not))
+         {
+            return parse_not_statement();
+         }
          else if (valid_base_operation(current_token().value))
          {
             return parse_base_operation();
@@ -25268,7 +26698,7 @@
             set_error(
                make_error(parser_error::e_symtab,
                           current_token(),
-                          "ERR189 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
+                          "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
                           exprtk_error_location));
 
             return error_node();
@@ -25277,6 +26707,13 @@
 
       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
       {
+         stack_limit_handler slh(*this);
+
+         if (!slh)
+         {
+            return error_node();
+         }
+
          expression_node_ptr branch = error_node();
 
          if (token_t::e_number == current_token().type)
@@ -25292,7 +26729,7 @@
                   set_error(
                      make_error(parser_error::e_numeric,
                                 current_token(),
-                                "ERR190 - Failed generate node for scalar: '" + current_token().value + "'",
+                                "ERR200 - Failed generate node for scalar: '" + current_token().value + "'",
                                 exprtk_error_location));
 
                   return error_node();
@@ -25306,7 +26743,7 @@
                set_error(
                   make_error(parser_error::e_numeric,
                              current_token(),
-                             "ERR191 - Failed to convert '" + current_token().value + "' to a number",
+                             "ERR201 - Failed to convert '" + current_token().value + "' to a number",
                              exprtk_error_location));
 
                return error_node();
@@ -25333,7 +26770,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR192 - Expected ')' instead of: '" + current_token().value + "'",
+                             "ERR202 - Expected ')' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_,branch);
@@ -25358,7 +26795,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR193 - Expected ']' instead of: '" + current_token().value + "'",
+                             "ERR203 - Expected ']' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_,branch);
@@ -25383,7 +26820,7 @@
                set_error(
                   make_error(parser_error::e_syntax,
                              current_token(),
-                             "ERR194 - Expected '}' instead of: '" + current_token().value + "'",
+                             "ERR204 - Expected '}' instead of: '" + current_token().value + "'",
                              exprtk_error_location));
 
                free_node(node_allocator_,branch);
@@ -25410,7 +26847,16 @@
                   )
                )
             {
-               branch = expression_generator_(details::e_neg,branch);
+               expression_node_ptr result = expression_generator_(details::e_neg,branch);
+
+               if (0 == result)
+               {
+                  free_node(node_allocator_,branch);
+
+                  return error_node();
+               }
+               else
+                  branch = result;
             }
          }
          else if (token_t::e_add == current_token().type)
@@ -25423,7 +26869,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR195 - Premature end of expression[1]",
+                          "ERR205 - Premature end of expression[1]",
                           exprtk_error_location));
 
             return error_node();
@@ -25433,7 +26879,7 @@
             set_error(
                make_error(parser_error::e_syntax,
                           current_token(),
-                          "ERR196 - Premature end of expression[2]",
+                          "ERR206 - Premature end of expression[2]",
                           exprtk_error_location));
 
             return error_node();
@@ -25607,7 +27053,7 @@
             return true;
          }
 
-         inline details::operator_type get_operator(const binary_functor_t& bop)
+         inline details::operator_type get_operator(const binary_functor_t& bop) const
          {
             return (*inv_binary_op_map_).find(bop)->second;
          }
@@ -25666,9 +27112,9 @@
                    (details::e_frac  == operation) || (details::e_trunc == operation) ;
          }
 
-         inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)
+         inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
          {
-            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+            typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
 
             if (sf3_map_->end() == itr)
                return false;
@@ -25678,9 +27124,9 @@
             return true;
          }
 
-         inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc)
+         inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
          {
-            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+            typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
 
             if (sf4_map_->end() == itr)
                return false;
@@ -25690,9 +27136,9 @@
             return true;
          }
 
-         inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation)
+         inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
          {
-            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+            typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
 
             if (sf3_map_->end() == itr)
                return false;
@@ -25702,9 +27148,9 @@
             return true;
          }
 
-         inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation)
+         inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
          {
-            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+            typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
 
             if (sf4_map_->end() == itr)
                return false;
@@ -25832,7 +27278,7 @@
                    (details::e_xnor == operation) ;
          }
 
-         inline std::string branch_to_id(expression_node_ptr branch)
+         inline std::string branch_to_id(expression_node_ptr branch) const
          {
             static const std::string null_str   ("(null)" );
             static const std::string const_str  ("(c)"    );
@@ -25873,7 +27319,7 @@
                return "ERROR";
          }
 
-         inline std::string branch_to_id(expression_node_ptr (&branch)[2])
+         inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
          {
             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
          }
@@ -25991,7 +27437,7 @@
                       !details::is_constant_node(branch[1]) ;
          }
 
-         inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
          {
             if (is_assignment_operation(operation))
             {
@@ -26013,14 +27459,14 @@
                return false;
          }
 
-         inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2])
+         inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
          {
             if (
-                 !is_constant_node(branch[1]) ||
-                  is_constant_node(branch[0]) ||
-                  is_variable_node(branch[0]) ||
-                  is_vector_node  (branch[0]) ||
-                  is_generally_string_node(branch[0])
+                 !details::is_constant_node(branch[1]) ||
+                  details::is_constant_node(branch[0]) ||
+                  details::is_variable_node(branch[0]) ||
+                  details::is_vector_node  (branch[0]) ||
+                  details::is_generally_string_node(branch[0])
                )
                return false;
 
@@ -26029,7 +27475,7 @@
             return cardinal_pow_optimisable(operation, c);
          }
 
-         inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
+         inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
          {
             return (
                      details::is_break_node   (branch[0]) ||
@@ -26039,7 +27485,7 @@
                    );
          }
 
-         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
          {
             const bool b0_string = is_generally_string_node(branch[0]);
             const bool b1_string = is_generally_string_node(branch[1]);
@@ -26059,7 +27505,7 @@
             return result;
          }
 
-         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
          {
             const bool b0_string = is_generally_string_node(branch[0]);
             const bool b1_string = is_generally_string_node(branch[1]);
@@ -26080,7 +27526,7 @@
             return result;
          }
 
-         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
          {
             const bool b0_string = is_generally_string_node(branch[0]);
             const bool b1_string = is_generally_string_node(branch[1]);
@@ -26088,7 +27534,7 @@
             return (b0_string && b1_string && valid_string_operation(operation));
          }
 
-         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
          {
             const bool b0_string = is_generally_string_node(branch[0]);
             const bool b1_string = is_generally_string_node(branch[1]);
@@ -26098,7 +27544,7 @@
          }
 
          #ifndef exprtk_disable_sc_andor
-         inline bool is_shortcircuit_expression(const details::operator_type& operation)
+         inline bool is_shortcircuit_expression(const details::operator_type& operation) const
          {
             return (
                      (details::e_scand == operation) ||
@@ -26106,13 +27552,13 @@
                    );
          }
          #else
-         inline bool is_shortcircuit_expression(const details::operator_type&)
+         inline bool is_shortcircuit_expression(const details::operator_type&) const
          {
             return false;
          }
          #endif
 
-         inline bool is_null_present(expression_node_ptr (&branch)[2])
+         inline bool is_null_present(expression_node_ptr (&branch)[2]) const
          {
             return (
                      details::is_null_node(branch[0]) ||
@@ -26120,29 +27566,29 @@
                    );
          }
 
-         inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
          {
             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
                return false;
             else
                return (
-                        (details::e_lt     == operation) ||
-                        (details::e_lte    == operation) ||
-                        (details::e_gt     == operation) ||
-                        (details::e_gte    == operation) ||
-                        (details::e_eq     == operation) ||
-                        (details::e_ne     == operation) ||
-                        (details::e_equal  == operation) ||
-                        (details::e_and    == operation) ||
-                        (details::e_nand   == operation) ||
-                        (details::  e_or   == operation) ||
-                        (details:: e_nor   == operation) ||
-                        (details:: e_xor   == operation) ||
-                        (details::e_xnor   == operation)
+                        (details::e_lt    == operation) ||
+                        (details::e_lte   == operation) ||
+                        (details::e_gt    == operation) ||
+                        (details::e_gte   == operation) ||
+                        (details::e_eq    == operation) ||
+                        (details::e_ne    == operation) ||
+                        (details::e_equal == operation) ||
+                        (details::e_and   == operation) ||
+                        (details::e_nand  == operation) ||
+                        (details::  e_or  == operation) ||
+                        (details:: e_nor  == operation) ||
+                        (details:: e_xor  == operation) ||
+                        (details::e_xnor  == operation)
                       );
          }
 
-         inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
          {
             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
                return false;
@@ -26315,15 +27761,19 @@
             return (*this)(operation,branch);
          }
 
-         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
+         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
          {
-            if ((0 == b0) || (0 == b1))
-               return error_node();
-            else
+            expression_node_ptr result = error_node();
+
+            if ((0 != b0) && (0 != b1))
             {
                expression_node_ptr branch[2] = { b0, b1 };
-               return expression_generator<Type>::operator()(operation,branch);
+               result = expression_generator<Type>::operator()(operation, branch);
+               b0 = branch[0];
+               b1 = branch[1];
             }
+
+            return result;
          }
 
          inline expression_node_ptr conditional(expression_node_ptr condition,
@@ -26332,8 +27782,8 @@
          {
             if ((0 == condition) || (0 == consequent))
             {
-               free_node(*node_allocator_, condition  );
-               free_node(*node_allocator_, consequent );
+               free_node(*node_allocator_,   condition);
+               free_node(*node_allocator_,  consequent);
                free_node(*node_allocator_, alternative);
 
                return error_node();
@@ -26344,7 +27794,7 @@
                // True branch
                if (details::is_true(condition))
                {
-                  free_node(*node_allocator_, condition  );
+                  free_node(*node_allocator_,   condition);
                   free_node(*node_allocator_, alternative);
 
                   return consequent;
@@ -26352,7 +27802,7 @@
                // False branch
                else
                {
-                  free_node(*node_allocator_, condition );
+                  free_node(*node_allocator_,  condition);
                   free_node(*node_allocator_, consequent);
 
                   if (alternative)
@@ -26364,11 +27814,11 @@
             else if ((0 != consequent) && (0 != alternative))
             {
                return node_allocator_->
-                        allocate<conditional_node_t>(condition,consequent,alternative);
+                        allocate<conditional_node_t>(condition, consequent, alternative);
             }
             else
                return node_allocator_->
-                        allocate<cons_conditional_node_t>(condition,consequent);
+                        allocate<cons_conditional_node_t>(condition, consequent);
          }
 
          #ifndef exprtk_disable_string_capabilities
@@ -26378,8 +27828,8 @@
          {
             if ((0 == condition) || (0 == consequent))
             {
-               free_node(*node_allocator_, condition  );
-               free_node(*node_allocator_, consequent );
+               free_node(*node_allocator_,   condition);
+               free_node(*node_allocator_,  consequent);
                free_node(*node_allocator_, alternative);
 
                return error_node();
@@ -26390,7 +27840,7 @@
                // True branch
                if (details::is_true(condition))
                {
-                  free_node(*node_allocator_, condition  );
+                  free_node(*node_allocator_,   condition);
                   free_node(*node_allocator_, alternative);
 
                   return consequent;
@@ -26398,7 +27848,7 @@
                // False branch
                else
                {
-                  free_node(*node_allocator_, condition );
+                  free_node(*node_allocator_,  condition);
                   free_node(*node_allocator_, consequent);
 
                   if (alternative)
@@ -26410,7 +27860,7 @@
             }
             else if ((0 != consequent) && (0 != alternative))
                return node_allocator_->
-                        allocate<conditional_string_node_t>(condition,consequent,alternative);
+                        allocate<conditional_string_node_t>(condition, consequent, alternative);
             else
                return error_node();
          }
@@ -26423,6 +27873,19 @@
          }
          #endif
 
+         inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
+         {
+            if (
+                 parser_->loop_runtime_check_ &&
+                 (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
+               )
+            {
+               return parser_->loop_runtime_check_;
+            }
+
+            return loop_runtime_check_ptr(0);
+         }
+
          inline expression_node_ptr while_loop(expression_node_ptr& condition,
                                                expression_node_ptr& branch,
                                                const bool brkcont = false) const
@@ -26437,7 +27900,7 @@
                   result = node_allocator_->allocate<details::null_node<Type> >();
 
                free_node(*node_allocator_, condition);
-               free_node(*node_allocator_, branch   );
+               free_node(*node_allocator_,    branch);
 
                return result;
             }
@@ -26448,10 +27911,20 @@
                return branch;
             }
             else if (!brkcont)
-               return node_allocator_->allocate<while_loop_node_t>(condition,branch);
+               return node_allocator_->allocate<while_loop_node_t>
+                        (
+                          condition,
+                          branch,
+                          get_loop_runtime_check(loop_runtime_check::e_while_loop)
+                        );
             #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
+               return node_allocator_->allocate<while_loop_bc_node_t>
+                        (
+                          condition,
+                          branch,
+                          get_loop_runtime_check(loop_runtime_check::e_while_loop)
+                        );
             #else
                return error_node();
             #endif
@@ -26474,7 +27947,7 @@
                }
 
                free_node(*node_allocator_, condition);
-               free_node(*node_allocator_, branch   );
+               free_node(*node_allocator_,    branch);
 
                return error_node();
             }
@@ -26485,10 +27958,20 @@
                return branch;
             }
             else if (!brkcont)
-               return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
+               return node_allocator_->allocate<repeat_until_loop_node_t>
+                        (
+                          condition,
+                          branch,
+                          get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
+                        );
             #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
+               return node_allocator_->allocate<repeat_until_loop_bc_node_t>
+                        (
+                          condition,
+                          branch,
+                          get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
+                        );
             #else
                return error_node();
             #endif
@@ -26511,16 +27994,16 @@
                   result = node_allocator_->allocate<details::null_node<Type> >();
 
                free_node(*node_allocator_, initialiser);
-               free_node(*node_allocator_, condition  );
+               free_node(*node_allocator_,   condition);
                free_node(*node_allocator_, incrementor);
-               free_node(*node_allocator_, loop_body  );
+               free_node(*node_allocator_,   loop_body);
 
                return result;
             }
-            else if (details::is_null_node(condition))
+            else if (details::is_null_node(condition) || (0 == condition))
             {
                free_node(*node_allocator_, initialiser);
-               free_node(*node_allocator_, condition  );
+               free_node(*node_allocator_,   condition);
                free_node(*node_allocator_, incrementor);
 
                return loop_body;
@@ -26531,7 +28014,8 @@
                                          initialiser,
                                          condition,
                                          incrementor,
-                                         loop_body
+                                         loop_body,
+                                         get_loop_runtime_check(loop_runtime_check::e_for_loop)
                                        );
 
             #ifndef exprtk_disable_break_continue
@@ -26541,7 +28025,8 @@
                                          initialiser,
                                          condition,
                                          incrementor,
-                                         loop_body
+                                         loop_body,
+                                         get_loop_runtime_check(loop_runtime_check::e_for_loop)
                                        );
             #else
             return error_node();
@@ -26549,7 +28034,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             expression_node_ptr result = error_node();
@@ -26585,7 +28070,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             expression_node_ptr result = error_node();
@@ -26622,10 +28107,10 @@
 
          struct switch_nodes
          {
-            typedef std::vector<expression_node_ptr> arg_list_t;
+            typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
 
-            #define case_stmt(N)                                             \
-            if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
+            #define case_stmt(N)                                                         \
+            if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
 
             struct switch_1
             {
@@ -26633,7 +28118,7 @@
                {
                   case_stmt(0)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26643,7 +28128,7 @@
                {
                   case_stmt(0) case_stmt(1)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26654,7 +28139,7 @@
                   case_stmt(0) case_stmt(1)
                   case_stmt(2)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26665,7 +28150,7 @@
                   case_stmt(0) case_stmt(1)
                   case_stmt(2) case_stmt(3)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26677,7 +28162,7 @@
                   case_stmt(2) case_stmt(3)
                   case_stmt(4)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26689,7 +28174,7 @@
                   case_stmt(2) case_stmt(3)
                   case_stmt(4) case_stmt(5)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26702,7 +28187,7 @@
                   case_stmt(4) case_stmt(5)
                   case_stmt(6)
 
-                  return arg.back()->value();
+                  return arg.back().first->value();
                }
             };
 
@@ -26710,15 +28195,14 @@
          };
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
-         inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
+                   template <typename, typename> class Sequence>
+         inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
          {
             if (arg_list.empty())
                return error_node();
             else if (
-                      !all_nodes_valid(arg_list)   ||
-                      (arg_list.size() < 3)        ||
-                      ((arg_list.size() % 2) != 1)
+                      !all_nodes_valid(arg_list) ||
+                      (!default_statement_present && (arg_list.size() < 2))
                     )
             {
                details::free_all_nodes(*node_allocator_,arg_list);
@@ -26750,7 +28234,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             if (!all_nodes_valid(arg_list))
@@ -27062,7 +28546,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             expression_node_ptr temp_node = error_node();
@@ -27094,7 +28578,7 @@
             return node_allocator_->allocate<literal_node_t>(v);
          }
 
-         inline bool special_one_parameter_vararg(const details::operator_type& operation)
+         inline bool special_one_parameter_vararg(const details::operator_type& operation) const
          {
             return (
                      (details::e_sum  == operation) ||
@@ -27106,7 +28590,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             switch (operation)
@@ -27129,7 +28613,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             if (1 == arg_list.size())
@@ -27154,7 +28638,7 @@
          }
 
          template <typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             if (!all_nodes_valid(arg_list))
@@ -27456,7 +28940,7 @@
                   return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
                }
 
-               scope_element& se = parser_->sem_.get_element(symbol,i);
+               const scope_element& se = parser_->sem_.get_element(symbol,i);
 
                if (se.index == i)
                {
@@ -27516,7 +29000,7 @@
 
          template <typename NodePtr,
                    typename Allocator,
-                   template <typename,typename> class Sequence>
+                   template <typename, typename> class Sequence>
          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
          {
             for (std::size_t i = 0; i < b.size(); ++i)
@@ -27662,6 +29146,8 @@
             }
             else if (details::is_vector_elem_node(branch[0]))
             {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
                switch (operation)
                {
                   #define case_stmt(op0,op1)                                                                            \
@@ -27680,6 +29166,8 @@
             }
             else if (details::is_rebasevector_elem_node(branch[0]))
             {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
                switch (operation)
                {
                   #define case_stmt(op0,op1)                                                                                  \
@@ -27698,6 +29186,8 @@
             }
             else if (details::is_rebasevector_celem_node(branch[0]))
             {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
                switch (operation)
                {
                   #define case_stmt(op0,op1)                                                                                   \
@@ -28048,7 +29538,7 @@
          case_stmt(details::e_xnor, details::xnor_op) \
 
          #ifndef exprtk_disable_cardinal_pow_optimisation
-         template <typename TType, template <typename,typename> class IPowNode>
+         template <typename TType, template <typename, typename> class IPowNode>
          inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
          {
             switch (p)
@@ -28098,7 +29588,7 @@
             }
          }
 
-         inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c)
+         inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
          {
             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
          }
@@ -28302,8 +29792,9 @@
                {
                   expression_node_ptr result = error_node();
 
-                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_right<vtype>
-                                                  (expr_gen, v, operation, branch[1], result);
+                  const bool synthesis_result =
+                     synthesize_sf4ext_expression::template compile_right<vtype>
+                        (expr_gen, v, operation, branch[1], result);
 
                   if (synthesis_result)
                   {
@@ -28376,8 +29867,9 @@
                {
                   expression_node_ptr result = error_node();
 
-                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<vtype>
-                                                   (expr_gen, v, operation, branch[0], result);
+                  const bool synthesis_result =
+                     synthesize_sf4ext_expression::template compile_left<vtype>
+                        (expr_gen, v, operation, branch[0], result);
 
                   if (synthesis_result)
                   {
@@ -28536,12 +30028,12 @@
                         {
                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
-                                                       (c / cobnode->c(),cobnode->move_branch(0));
+                                                       (c / cobnode->c(), cobnode->move_branch(0));
                                                  break;
 
                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
-                                                       (c / cobnode->c(),cobnode->move_branch(0));
+                                                       (c / cobnode->c(), cobnode->move_branch(0));
                                                  break;
 
                            default             : return error_node();
@@ -28558,7 +30050,11 @@
                {
                   expression_node_ptr result = error_node();
 
-                  if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
+                  const bool synthesis_result =
+                     synthesize_sf4ext_expression::template compile_right<ctype>
+                        (expr_gen, c, operation, branch[1], result);
+
+                  if (synthesis_result)
                   {
                      free_node(*expr_gen.node_allocator_,branch[1]);
 
@@ -28590,11 +30086,11 @@
             {
                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
 
-               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+               details::free_node(*(expr_gen.node_allocator_), branch[1]);
 
                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
                {
-                  free_node(*expr_gen.node_allocator_,branch[0]);
+                  free_node(*expr_gen.node_allocator_, branch[0]);
 
                   return expr_gen(T(0));
                }
@@ -28673,8 +30169,9 @@
                {
                   expression_node_ptr result = error_node();
 
-                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<ctype>
-                                                   (expr_gen, c, operation, branch[0], result);
+                  const bool synthesis_result =
+                     synthesize_sf4ext_expression::template compile_left<ctype>
+                        (expr_gen, c, operation, branch[0], result);
 
                   if (synthesis_result)
                   {
@@ -29224,7 +30721,8 @@
                if (!expr_gen.sf3_optimisable(id,sf3opr))
                   return false;
                else
-                  result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
+                  result = synthesize_sf3ext_expression::template process<T0, T1, T2>
+                              (expr_gen, sf3opr, t0, t1, t2);
 
                return true;
             }
@@ -29291,7 +30789,7 @@
                if (!expr_gen.sf4_optimisable(id,sf4opr))
                   return false;
                else
-                  result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>
+                  result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
                               (expr_gen, sf4opr, t0, t1, t2, t3);
 
                return true;
@@ -29311,28 +30809,28 @@
                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
 
                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
-               std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
+               const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
 
                switch (n->type())
                {
                   case details::expression_node<Type>::e_covoc : return compile_right_impl
-                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
+                                                                    <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_covov : return compile_right_impl
-                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
+                                                                    <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vocov : return compile_right_impl
-                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
+                                                                    <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
-                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
+                                                                    <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vovov : return compile_right_impl
-                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
+                                                                    <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   default                                      : return false;
@@ -29354,28 +30852,28 @@
 
                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
 
-               std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
+               const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
 
                switch (n->type())
                {
                   case details::expression_node<Type>::e_covoc : return compile_left_impl
-                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
+                                                                    <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_covov : return compile_left_impl
-                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
+                                                                    <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vocov : return compile_left_impl
-                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
+                                                                    <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
-                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
+                                                                    <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   case details::expression_node<Type>::e_vovov : return compile_left_impl
-                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
+                                                                    <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
                                                                        (expr_gen, id, t, sf3node, result);
 
                   default                                      : return false;
@@ -29397,7 +30895,7 @@
                   T1 t1 = n->t1();
                   T2 t2 = n->t2();
 
-                  return synthesize_sf4ext_expression::template compile<ExternalType,T0,T1,T2>
+                  return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
                             (expr_gen, id, t, t0, t1, t2, result);
                }
                else
@@ -29419,7 +30917,7 @@
                   T1 t1 = n->t1();
                   T2 t2 = n->t2();
 
-                  return synthesize_sf4ext_expression::template compile<T0,T1,T2,ExternalType>
+                  return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
                             (expr_gen, id, t0, t1, t2, t, result);
                }
                else
@@ -29483,7 +30981,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -29543,7 +31044,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -29604,7 +31108,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -29664,7 +31171,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -29724,7 +31234,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -29784,7 +31297,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -29844,7 +31360,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -29904,7 +31423,10 @@
 
             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -30003,7 +31525,7 @@
 
                const bool synthesis_result =
                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
-                     (expr_gen, id(expr_gen, o0, o1), c0, v, c1,result);
+                     (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
 
                if (synthesis_result)
                   return result;
@@ -30018,7 +31540,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -30132,7 +31657,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -30255,7 +31783,10 @@
 
             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)";
             }
          };
 
@@ -30377,7 +31908,10 @@
             static inline std::string id(expression_generator<Type>& expr_gen,
                                          const details::operator_type o0, const details::operator_type o1)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "t";
             }
          };
 
@@ -30487,7 +32021,7 @@
 
                const bool synthesis_result =
                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
-                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3,result);
+                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
 
                if (synthesis_result)
                   return result;
@@ -30506,7 +32040,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -30590,7 +32128,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -30674,7 +32216,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -30758,7 +32304,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -30842,7 +32392,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -31031,7 +32585,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -31270,7 +32828,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -31459,7 +33021,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -31647,7 +33213,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "t)" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -31699,7 +33269,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -31755,7 +33329,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -31811,7 +33389,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -31867,7 +33449,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -31924,7 +33510,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -31981,7 +33571,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -32037,7 +33631,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -32093,7 +33691,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -32149,7 +33751,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+               return details::build_string()
+                         << "t"  << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "(t" << expr_gen.to_str(o2)
+                         << "t))";
             }
          };
 
@@ -32205,7 +33811,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32261,7 +33871,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32317,7 +33931,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32373,7 +33991,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32430,7 +34052,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
         };
 
@@ -32487,7 +34113,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32543,7 +34173,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32600,7 +34234,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+               return details::build_string()
+                         << "t"   << expr_gen.to_str(o0)
+                         << "((t" << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t)";
             }
          };
 
@@ -32673,7 +34311,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -32730,7 +34372,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -32786,7 +34432,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -32842,7 +34492,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -32898,7 +34552,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -32954,7 +34612,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33011,7 +34673,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33068,7 +34734,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33124,7 +34794,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "((t" << expr_gen.to_str(o0)
+                         << "t)"  << expr_gen.to_str(o1)
+                         << "t)"  << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33180,7 +34854,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33237,7 +34915,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33293,7 +34975,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33348,7 +35034,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33404,7 +35094,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33460,7 +35154,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33517,7 +35215,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33574,7 +35276,11 @@
                                          const details::operator_type o1,
                                          const details::operator_type o2)
             {
-               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+               return details::build_string()
+                         << "(t" << expr_gen.to_str(o0)
+                         << "(t" << expr_gen.to_str(o1)
+                         << "t)" << expr_gen.to_str(o2)
+                         << "t";
             }
          };
 
@@ -33941,8 +35647,8 @@
          {
             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
                   std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();
-            range_t           rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
-            range_t           rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
+            const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+            const range_t     rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
@@ -33955,9 +35661,9 @@
 
          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            std::string       s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+            const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
             const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();
-            range_t          rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+            const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
 
@@ -33968,10 +35674,10 @@
 
          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
-            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
-            range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
-            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+            const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+            const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+            const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+            const range_t    rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
@@ -34121,9 +35827,9 @@
                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
 
-               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
+               typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
 
-               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
+               return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
             }
             else if (
                       details::is_const_string_node(branch[0]) &&
@@ -34135,12 +35841,12 @@
                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
 
-               typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
+               typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
 
                details::free_node(*node_allocator_,branch[0]);
                details::free_node(*node_allocator_,branch[2]);
 
-               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
+               return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
             }
             else if (
                             details::is_string_node(branch[0]) &&
@@ -34152,11 +35858,11 @@
                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
                std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
 
-               typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
+               typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
 
                details::free_node(*node_allocator_,branch[1]);
 
-               return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
+               return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
             }
             else if (
                       details::is_string_node(branch[0]) &&
@@ -34168,11 +35874,11 @@
                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
 
-               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
+               typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
 
                details::free_node(*node_allocator_,branch[2]);
 
-               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
+               return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
             }
             else if (
                       details::is_const_string_node(branch[0]) &&
@@ -34184,11 +35890,11 @@
                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
                std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
 
-               typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
+               typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
 
                details::free_node(*node_allocator_,branch[0]);
 
-               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
+               return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
             }
             else
                return error_node();
@@ -34216,8 +35922,8 @@
 
             typedef typename details::null_eq_node<T> nulleq_node_t;
 
-            bool b0_null = details::is_null_node(branch[0]);
-            bool b1_null = details::is_null_node(branch[1]);
+            const bool b0_null = details::is_null_node(branch[0]);
+            const bool b1_null = details::is_null_node(branch[1]);
 
             if (b0_null && b1_null)
             {
@@ -34278,21 +35984,22 @@
             {
                return branch[0];
             }
-            else if (
-                      (details::e_lt    == operation) || (details::e_lte  == operation) ||
-                      (details::e_gt    == operation) || (details::e_gte  == operation) ||
-                      (details::e_and   == operation) || (details::e_nand == operation) ||
-                      (details::e_or    == operation) || (details::e_nor  == operation) ||
-                      (details::e_xor   == operation) || (details::e_xnor == operation) ||
-                      (details::e_in    == operation) || (details::e_like == operation) ||
-                      (details::e_ilike == operation)
-                    )
+
+            details::free_node(*node_allocator_, branch[0]);
+
+            if (
+                 (details::e_lt    == operation) || (details::e_lte  == operation) ||
+                 (details::e_gt    == operation) || (details::e_gte  == operation) ||
+                 (details::e_and   == operation) || (details::e_nand == operation) ||
+                 (details::e_or    == operation) || (details::e_nor  == operation) ||
+                 (details::e_xor   == operation) || (details::e_xnor == operation) ||
+                 (details::e_in    == operation) || (details::e_like == operation) ||
+                 (details::e_ilike == operation)
+               )
             {
                return node_allocator_->allocate_c<literal_node_t>(T(0));
             }
 
-            details::free_node(*node_allocator_,branch[0]);
-
             return node_allocator_->allocate<details::null_node<Type> >();
          }
 
@@ -34322,7 +36029,7 @@
 
                if (is_constant_foldable<N>(branch))
                {
-                  Type v = expression_point->value();
+                  const Type v = expression_point->value();
                   details::free_node(*node_allocator_,expression_point);
 
                   return node_allocator_->allocate<literal_node_t>(v);
@@ -34688,48 +36395,125 @@
 
       lexer::helper::helper_assembly helper_assembly_;
 
-      lexer::helper::commutative_inserter commutative_inserter_;
-      lexer::helper::operator_joiner      operator_joiner_2_;
-      lexer::helper::operator_joiner      operator_joiner_3_;
-      lexer::helper::symbol_replacer      symbol_replacer_;
-      lexer::helper::bracket_checker      bracket_checker_;
-      lexer::helper::numeric_checker      numeric_checker_;
-      lexer::helper::sequence_validator   sequence_validator_;
+      lexer::helper::commutative_inserter       commutative_inserter_;
+      lexer::helper::operator_joiner            operator_joiner_2_;
+      lexer::helper::operator_joiner            operator_joiner_3_;
+      lexer::helper::symbol_replacer            symbol_replacer_;
+      lexer::helper::bracket_checker            bracket_checker_;
+      lexer::helper::numeric_checker            numeric_checker_;
+      lexer::helper::sequence_validator         sequence_validator_;
+      lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
+
+      loop_runtime_check_ptr loop_runtime_check_;
 
       template <typename ParserType>
       friend void details::disable_type_checking(ParserType& p);
    };
 
+   namespace details
+   {
+      template <typename T>
+      struct collector_helper
+      {
+         typedef exprtk::symbol_table<T> symbol_table_t;
+         typedef exprtk::expression<T>     expression_t;
+         typedef exprtk::parser<T>             parser_t;
+         typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
+         typedef typename parser_t::unknown_symbol_resolver usr_t;
+
+         struct resolve_as_vector : public parser_t::unknown_symbol_resolver
+         {
+            typedef exprtk::parser<T> parser_t;
+
+            resolve_as_vector()
+            : usr_t(usr_t::e_usrmode_extended)
+            {}
+
+            virtual bool process(const std::string& unknown_symbol,
+                                 symbol_table_t& symbol_table,
+                                 std::string&)
+            {
+               static T v[1];
+               symbol_table.add_vector(unknown_symbol,v);
+               return true;
+            }
+         };
+
+         static inline bool collection_pass(const std::string& expression_string,
+                                            std::set<std::string>& symbol_set,
+                                            const bool collect_variables,
+                                            const bool collect_functions,
+                                            const bool vector_pass,
+                                            symbol_table_t& ext_symbol_table)
+         {
+            symbol_table_t symbol_table;
+            expression_t   expression;
+            parser_t       parser;
+
+            resolve_as_vector vect_resolver;
+
+            expression.register_symbol_table(symbol_table    );
+            expression.register_symbol_table(ext_symbol_table);
+
+            if (vector_pass)
+               parser.enable_unknown_symbol_resolver(&vect_resolver);
+            else
+               parser.enable_unknown_symbol_resolver();
+
+            if (collect_variables)
+               parser.dec().collect_variables() = true;
+
+            if (collect_functions)
+               parser.dec().collect_functions() = true;
+
+            bool pass_result = false;
+
+            details::disable_type_checking(parser);
+
+            if (parser.compile(expression_string, expression))
+            {
+               pass_result = true;
+
+               std::deque<symbol_t> symb_list;
+               parser.dec().symbols(symb_list);
+
+               for (std::size_t i = 0; i < symb_list.size(); ++i)
+               {
+                  symbol_set.insert(symb_list[i].first);
+               }
+            }
+
+            return pass_result;
+         }
+      };
+   }
+
    template <typename Allocator,
              template <typename, typename> class Sequence>
-   inline bool collect_variables(const std::string& expr_str,
+   inline bool collect_variables(const std::string& expression,
                                  Sequence<std::string, Allocator>& symbol_list)
    {
       typedef double T;
-      typedef exprtk::symbol_table<T> symbol_table_t;
-      typedef exprtk::expression<T>     expression_t;
-      typedef exprtk::parser<T>             parser_t;
-      typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
+      typedef details::collector_helper<T> collect_t;
 
-      symbol_table_t symbol_table;
-      expression_t   expression;
-      parser_t       parser;
+      collect_t::symbol_table_t null_symbol_table;
 
-      expression.register_symbol_table(symbol_table);
+      std::set<std::string> symbol_set;
 
-      parser.enable_unknown_symbol_resolver();
-      parser.dec().collect_variables() = true;
+      const bool variable_pass = collect_t::collection_pass
+                                    (expression, symbol_set, true, false, false, null_symbol_table);
+      const bool vector_pass   = collect_t::collection_pass
+                                    (expression, symbol_set, true, false,  true, null_symbol_table);
 
-      if (!parser.compile(expr_str, expression))
+      if (!variable_pass && !vector_pass)
          return false;
 
-      std::deque<symbol_t> symb_list;
+      std::set<std::string>::iterator itr = symbol_set.begin();
 
-      parser.dec().symbols(symb_list);
-
-      for (std::size_t i = 0; i < symb_list.size(); ++i)
+      while (symbol_set.end() != itr)
       {
-         symbol_list.push_back(symb_list[i].first);
+         symbol_list.push_back(*itr);
+         ++itr;
       }
 
       return true;
@@ -34738,37 +36522,28 @@
    template <typename T,
              typename Allocator,
              template <typename, typename> class Sequence>
-   inline bool collect_variables(const std::string& expr_str,
+   inline bool collect_variables(const std::string& expression,
                                  exprtk::symbol_table<T>& extrnl_symbol_table,
                                  Sequence<std::string, Allocator>& symbol_list)
    {
-      typedef exprtk::symbol_table<T> symbol_table_t;
-      typedef exprtk::expression<T>     expression_t;
-      typedef exprtk::parser<T>             parser_t;
-      typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
+      typedef details::collector_helper<T> collect_t;
 
-      symbol_table_t symbol_table;
-      expression_t   expression;
-      parser_t       parser;
+      std::set<std::string> symbol_set;
 
-      expression.register_symbol_table(symbol_table);
-      expression.register_symbol_table(extrnl_symbol_table);
+      const bool variable_pass = collect_t::collection_pass
+                                    (expression, symbol_set, true, false, false, extrnl_symbol_table);
+      const bool vector_pass   = collect_t::collection_pass
+                                    (expression, symbol_set, true, false,  true, extrnl_symbol_table);
 
-      parser.enable_unknown_symbol_resolver();
-      parser.dec().collect_variables() = true;
-
-      details::disable_type_checking(parser);
-
-      if (!parser.compile(expr_str, expression))
+      if (!variable_pass && !vector_pass)
          return false;
 
-      std::deque<symbol_t> symb_list;
+      std::set<std::string>::iterator itr = symbol_set.begin();
 
-      parser.dec().symbols(symb_list);
-
-      for (std::size_t i = 0; i < symb_list.size(); ++i)
+      while (symbol_set.end() != itr)
       {
-         symbol_list.push_back(symb_list[i].first);
+         symbol_list.push_back(*itr);
+         ++itr;
       }
 
       return true;
@@ -34776,34 +36551,30 @@
 
    template <typename Allocator,
              template <typename, typename> class Sequence>
-   inline bool collect_functions(const std::string& expr_str,
+   inline bool collect_functions(const std::string& expression,
                                  Sequence<std::string, Allocator>& symbol_list)
    {
       typedef double T;
-      typedef exprtk::symbol_table<T> symbol_table_t;
-      typedef exprtk::expression<T>     expression_t;
-      typedef exprtk::parser<T>             parser_t;
-      typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
+      typedef details::collector_helper<T> collect_t;
 
-      symbol_table_t symbol_table;
-      expression_t   expression;
-      parser_t       parser;
+      collect_t::symbol_table_t null_symbol_table;
 
-      expression.register_symbol_table(symbol_table);
+      std::set<std::string> symbol_set;
 
-      parser.enable_unknown_symbol_resolver();
-      parser.dec().collect_functions() = true;
+      const bool variable_pass = collect_t::collection_pass
+                                    (expression, symbol_set, false, true, false, null_symbol_table);
+      const bool vector_pass   = collect_t::collection_pass
+                                    (expression, symbol_set, false, true,  true, null_symbol_table);
 
-      if (!parser.compile(expr_str, expression))
+      if (!variable_pass && !vector_pass)
          return false;
 
-      std::deque<symbol_t> symb_list;
+      std::set<std::string>::iterator itr = symbol_set.begin();
 
-      parser.dec().symbols(symb_list);
-
-      for (std::size_t i = 0; i < symb_list.size(); ++i)
+      while (symbol_set.end() != itr)
       {
-         symbol_list.push_back(symb_list[i].first);
+         symbol_list.push_back(*itr);
+         ++itr;
       }
 
       return true;
@@ -34812,37 +36583,28 @@
    template <typename T,
              typename Allocator,
              template <typename, typename> class Sequence>
-   inline bool collect_functions(const std::string& expr_str,
+   inline bool collect_functions(const std::string& expression,
                                  exprtk::symbol_table<T>& extrnl_symbol_table,
                                  Sequence<std::string, Allocator>& symbol_list)
    {
-      typedef exprtk::symbol_table<T> symbol_table_t;
-      typedef exprtk::expression<T>     expression_t;
-      typedef exprtk::parser<T>             parser_t;
-      typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
+      typedef details::collector_helper<T> collect_t;
 
-      symbol_table_t symbol_table;
-      expression_t   expression;
-      parser_t       parser;
+      std::set<std::string> symbol_set;
 
-      expression.register_symbol_table(symbol_table);
-      expression.register_symbol_table(extrnl_symbol_table);
+      const bool variable_pass = collect_t::collection_pass
+                                    (expression, symbol_set, false, true, false, extrnl_symbol_table);
+      const bool vector_pass   = collect_t::collection_pass
+                                    (expression, symbol_set, false, true,  true, extrnl_symbol_table);
 
-      parser.enable_unknown_symbol_resolver();
-      parser.dec().collect_functions() = true;
-
-      details::disable_type_checking(parser);
-
-      if (!parser.compile(expr_str, expression))
+      if (!variable_pass && !vector_pass)
          return false;
 
-      std::deque<symbol_t> symb_list;
+      std::set<std::string>::iterator itr = symbol_set.begin();
 
-      parser.dec().symbols(symb_list);
-
-      for (std::size_t i = 0; i < symb_list.size(); ++i)
+      while (symbol_set.end() != itr)
       {
-         symbol_list.push_back(symb_list[i].first);
+         symbol_list.push_back(*itr);
+         ++itr;
       }
 
       return true;
@@ -34888,8 +36650,8 @@
       if (var)
       {
          T& x = var->ref();
-         T  x_original = x;
-         T result = integrate(e,x,r0,r1,number_of_intervals);
+         const T x_original = x;
+         const T result = integrate(e, x, r0, r1, number_of_intervals);
          x = x_original;
 
          return result;
@@ -34979,8 +36741,8 @@
       if (var)
       {
          T& x = var->ref();
-         T x_original = x;
-         T result = derivative(e,x,h);
+         const T x_original = x;
+         const T result = derivative(e, x, h);
          x = x_original;
 
          return result;
@@ -35007,7 +36769,7 @@
       {
          T& x = var->ref();
          const T x_original = x;
-         const T result = second_derivative(e,x,h);
+         const T result = second_derivative(e, x, h);
          x = x_original;
 
          return result;
@@ -35034,7 +36796,7 @@
       {
          T& x = var->ref();
          const T x_original = x;
-         const T result = third_derivative(e,x,h);
+         const T result = third_derivative(e, x, h);
          x = x_original;
 
          return result;
@@ -35327,62 +37089,62 @@
 
       inline virtual T operator() (const T& x, const T& c1, const T& c0)
       {
-         poly_rtrn(1) poly_impl<T,1>::evaluate(x,c1,c0);
+         poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0);
+         poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0);
+         poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0);
+         poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
       {
-         poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
+         poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       #undef poly_rtrn
@@ -35570,7 +37332,7 @@
 
             typedef typename expression_t::control_block::local_data_list_t ldl_t;
 
-            ldl_t ldl = expr.local_data_list();
+            const ldl_t ldl = expr.local_data_list();
 
             std::vector<std::size_t> index_list;
 
@@ -35840,7 +37602,7 @@
          typedef typename results_context_t::type_store_t type_t;
          typedef typename type_t::scalar_view scalar_t;
 
-         T result = e.value();
+         const T result = e.value();
 
          if (e.return_invoked())
          {
@@ -35871,7 +37633,7 @@
       def_fp_retval(6)
 
       template <typename Allocator,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       inline bool add(const std::string& name,
                       const std::string& expression,
                       const Sequence<std::string,Allocator>& var_list,
@@ -35967,7 +37729,7 @@
    private:
 
       template <typename Allocator,
-                template <typename,typename> class Sequence>
+                template <typename, typename> class Sequence>
       bool compile_expression(const std::string& name,
                               const std::string& expression,
                               const Sequence<std::string,Allocator>& input_var_list,
@@ -36149,89 +37911,90 @@
    template <typename T>
    inline bool pgo_primer()
    {
-      static const std::string expression_list[]
-                                        = {
-                                             "(y + x)",
-                                             "2 * (y + x)",
-                                             "(2 * y + 2 * x)",
-                                             "(y + x / y) * (x - y / x)",
-                                             "x / ((x + y) * (x - y)) / y",
-                                             "1 - ((x * y) + (y / x)) - 3",
-                                             "sin(2 * x) + cos(pi / y)",
-                                             "1 - sin(2 * x) + cos(pi / y)",
-                                             "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
-                                             "(x^2 / sin(2 * pi / y)) -x / 2",
-                                             "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
-                                             "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                                             "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                                             "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
-                                             "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
-                                             "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
-                                             "(yy + xx)",
-                                             "2 * (yy + xx)",
-                                             "(2 * yy + 2 * xx)",
-                                             "(yy + xx / yy) * (xx - yy / xx)",
-                                             "xx / ((xx + yy) * (xx - yy)) / yy",
-                                             "1 - ((xx * yy) + (yy / xx)) - 3",
-                                             "sin(2 * xx) + cos(pi / yy)",
-                                             "1 - sin(2 * xx) + cos(pi / yy)",
-                                             "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
-                                             "(xx^2 / sin(2 * pi / yy)) -xx / 2",
-                                             "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
-                                             "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
-                                             "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
-                                             "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
-                                             "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
-                                             "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
-                                             "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
-                                             "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
-                                             "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
-                                             "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
-                                             "(x + 2) * 3", "x + (2 * 3)",
-                                             "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
-                                             "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
-                                             "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
-                                             "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
-                                             "2 + (x * (y / 3))", "x + (2 * (3 / y))",
-                                             "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
-                                             "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
-                                             "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
-                                             "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
-                                             "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
-                                             "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
-                                             "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
-                                             "((x + (2 * 3)) / y)",
-                                             "(xx + yy) * zz", "xx + (yy * zz)",
-                                             "(xx + yy) * 7", "xx + (yy * 7)",
-                                             "(xx + 7) * yy", "xx + (7 * yy)",
-                                             "(7 + xx) * yy", "7 + (xx * yy)",
-                                             "(2 + x) * 3", "2 + (x * 3)",
-                                             "(2 + 3) * x", "2 + (3 * x)",
-                                             "(x + 2) * 3", "x + (2 * 3)",
-                                             "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
-                                             "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
-                                             "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
-                                             "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
-                                             "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
-                                             "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
-                                             "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
-                                             "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
-                                             "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
-                                             "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
-                                             "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
-                                             "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
-                                             "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
-                                             "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
-                                             "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
-                                             "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
-                                             "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
-                                             "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
-                                             "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
-                                             "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
-                                             "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
-                                             "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
-                                             "((xx + (2 * 3)) / yy)"
-                                          };
+      static const std::string expression_list[] =
+             {
+                "(y + x)",
+                "2 * (y + x)",
+                "(2 * y + 2 * x)",
+                "(y + x / y) * (x - y / x)",
+                "x / ((x + y) * (x - y)) / y",
+                "1 - ((x * y) + (y / x)) - 3",
+                "sin(2 * x) + cos(pi / y)",
+                "1 - sin(2 * x) + cos(pi / y)",
+                "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
+                "(x^2 / sin(2 * pi / y)) -x / 2",
+                "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
+                "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
+                "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
+                "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
+                "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
+                "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
+                "(yy + xx)",
+                "2 * (yy + xx)",
+                "(2 * yy + 2 * xx)",
+                "(yy + xx / yy) * (xx - yy / xx)",
+                "xx / ((xx + yy) * (xx - yy)) / yy",
+                "1 - ((xx * yy) + (yy / xx)) - 3",
+                "sin(2 * xx) + cos(pi / yy)",
+                "1 - sin(2 * xx) + cos(pi / yy)",
+                "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
+                "(xx^2 / sin(2 * pi / yy)) -xx / 2",
+                "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
+                "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
+                "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
+                "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
+                "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
+                "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
+                "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
+                "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
+                "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
+                "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
+                "(x + 2) * 3", "x + (2 * 3)",
+                "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
+                "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
+                "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
+                "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
+                "2 + (x * (y / 3))", "x + (2 * (3 / y))",
+                "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
+                "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
+                "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
+                "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
+                "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
+                "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
+                "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
+                "((x + (2 * 3)) / y)",
+                "(xx + yy) * zz", "xx + (yy * zz)",
+                "(xx + yy) * 7", "xx + (yy * 7)",
+                "(xx + 7) * yy", "xx + (7 * yy)",
+                "(7 + xx) * yy", "7 + (xx * yy)",
+                "(2 + x) * 3", "2 + (x * 3)",
+                "(2 + 3) * x", "2 + (3 * x)",
+                "(x + 2) * 3", "x + (2 * 3)",
+                "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
+                "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
+                "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
+                "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
+                "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
+                "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
+                "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
+                "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
+                "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
+                "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
+                "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
+                "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
+                "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
+                "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
+                "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
+                "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
+                "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
+                "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
+                "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
+                "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
+                "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
+                "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
+                "((xx + (2 * 3)) / yy)"
+             };
+
       static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
 
       T  x = T(0);
@@ -36286,8 +38049,8 @@
          {
             static const T lower_bound = T(-20);
             static const T upper_bound = T(+20);
+            static const T delta       = T(0.1);
 
-            T delta = T(0.1);
             T total = T(0);
 
             for (x = lower_bound; x <= upper_bound; x += delta)
@@ -36311,7 +38074,7 @@
       {
          for (std::size_t i = 0; i < 10000; ++i)
          {
-            T v = T(123.456 + i);
+            const T v = T(123.456 + i);
 
             if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
                return false;
@@ -36416,14 +38179,14 @@
          {
             if (stop_time_.tv_sec >= start_time_.tv_sec)
             {
-               return 1000000LLU * static_cast<unsigned long long int>(stop_time_.tv_sec  - start_time_.tv_sec ) +
-                                   static_cast<unsigned long long int>(stop_time_.tv_usec - start_time_.tv_usec) ;
+               return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec  - start_time_.tv_sec ) +
+                                   static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
             }
             else
-               return std::numeric_limits<unsigned long long int>::max();
+               return std::numeric_limits<details::_uint64_t>::max();
          }
          else
-            return std::numeric_limits<unsigned long long int>::max();
+            return std::numeric_limits<details::_uint64_t>::max();
       }
 
       inline double time() const
@@ -36585,8 +38348,8 @@
             return false;                                                         \
          }                                                                        \
 
-         exprtk_register_function("print"   , p)
-         exprtk_register_function("println" ,pl)
+         exprtk_register_function("print"  ,  p)
+         exprtk_register_function("println", pl)
          #undef exprtk_register_function
 
          return true;
@@ -36754,7 +38517,7 @@
             }
          }
 
-         bool eof()
+         bool eof() const
          {
             switch (mode)
             {
@@ -36765,7 +38528,7 @@
             }
          }
 
-         file_mode get_file_mode(const std::string& access)
+         file_mode get_file_mode(const std::string& access) const
          {
             if (access.empty() || access.size() > 2)
                return e_error;
@@ -36843,11 +38606,9 @@
 
       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
       {
-         std::string file_name;
+         std::string file_name = to_str(string_t(parameters[0]));
          std::string access;
 
-         file_name = to_str(string_t(parameters[0]));
-
          if (file_name.empty())
             return T(0);
 
@@ -36928,27 +38689,27 @@
             case 0  : {
                          const string_t buffer(parameters[1]);
                          amount = buffer.size();
-                         return T(fd->write(buffer,amount) ? 1 : 0);
+                         return T(fd->write(buffer, amount) ? 1 : 0);
                       }
 
             case 1  : {
                          const string_t buffer(parameters[1]);
                          amount = std::min(buffer.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
-                         return T(fd->write(buffer,amount) ? 1 : 0);
+                         return T(fd->write(buffer, amount) ? 1 : 0);
                       }
 
             case 2  : {
                          const vector_t vec(parameters[1]);
                          amount = vec.size();
-                         return T(fd->write(vec,amount) ? 1 : 0);
+                         return T(fd->write(vec, amount) ? 1 : 0);
                       }
 
             case 3  : {
                          const vector_t vec(parameters[1]);
                          amount = std::min(vec.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
-                         return T(fd->write(vec,amount) ? 1 : 0);
+                         return T(fd->write(vec, amount) ? 1 : 0);
                       }
          }
 
@@ -37149,10 +38910,10 @@
    namespace details
    {
       template <typename T>
-      inline void kahan_sum(T& sum, T& error, T v)
+      inline void kahan_sum(T& sum, T& error, const T v)
       {
-         T x = v - error;
-         T y = sum + x;
+         const T x = v - error;
+         const T y = sum + x;
          error = (y - sum) - x;
          sum = y;
       }
@@ -37477,10 +39238,13 @@
             )
             return T(0);
 
-         std::size_t dist  = r1 - r0 + 1;
-         std::size_t shift = n % dist;
+         const std::size_t dist  = r1 - r0 + 1;
+         const std::size_t shift = n % dist;
 
-         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
+         std::rotate(
+            vec.begin() + r0,
+            vec.begin() + r0 + shift,
+            vec.begin() + r1 + 1);
 
          return T(1);
       }
@@ -37528,7 +39292,10 @@
          std::size_t dist  = r1 - r0 + 1;
          std::size_t shift = (dist - (n % dist)) % dist;
 
-         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
+         std::rotate(
+            vec.begin() + r0,
+            vec.begin() + r0 + shift,
+            vec.begin() + r1 + 1);
 
          return T(1);
       }
@@ -37573,12 +39340,15 @@
             )
             return T(0);
 
-         std::size_t dist  = r1 - r0 + 1;
+         const std::size_t dist  = r1 - r0 + 1;
 
          if (n > dist)
             return T(0);
 
-         std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
+         std::rotate(
+            vec.begin() + r0,
+            vec.begin() + r0 + n,
+            vec.begin() + r1 + 1);
 
          for (std::size_t i = r1 - n + 1; i <= r1; ++i)
          {
@@ -37628,14 +39398,17 @@
             )
             return T(0);
 
-         std::size_t dist  = r1 - r0 + 1;
+         const std::size_t dist  = r1 - r0 + 1;
 
          if (n > dist)
             return T(0);
 
-         std::size_t shift = (dist - (n % dist)) % dist;
+         const std::size_t shift = (dist - (n % dist)) % dist;
 
-         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
+         std::rotate(
+            vec.begin() + r0,
+            vec.begin() + r0 + shift,
+            vec.begin() + r1 + 1);
 
          for (std::size_t i = r0; i < r0 + n; ++i)
          {
@@ -37873,10 +39646,10 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
-         T a = scalar_t(parameters[0])();
+         const T a = scalar_t(parameters[0])();
 
          for (std::size_t i = r0; i <= r1; ++i)
          {
@@ -37920,7 +39693,7 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
          const T a = scalar_t(parameters[0])();
@@ -37969,12 +39742,12 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(z,r0,r1))
+         else if (helper::invalid_range(z, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
-         T a = scalar_t(parameters[0])();
+         const T a = scalar_t(parameters[0])();
 
          for (std::size_t i = r0; i <= r1; ++i)
          {
@@ -38019,9 +39792,9 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(z,r0,r1))
+         else if (helper::invalid_range(z, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
          const T a = scalar_t(parameters[0])();
@@ -38069,7 +39842,7 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(z,r0,r1))
+         else if (helper::invalid_range(z, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
          const T a = scalar_t(parameters[0])();
@@ -38116,7 +39889,7 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
          T result = T(0);
@@ -38162,7 +39935,7 @@
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
             return std::numeric_limits<T>::quiet_NaN();
-         else if (helper::invalid_range(y,r0,r1))
+         else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
 
          T result = T(0);
@@ -38218,7 +39991,7 @@
          exprtk_register_function("any_true"     ,nt)
          exprtk_register_function("any_false"    ,nf)
          exprtk_register_function("count"        , c)
-         exprtk_register_function("copy"        , cp)
+         exprtk_register_function("copy"         ,cp)
          exprtk_register_function("rotate_left"  ,rl)
          exprtk_register_function("rol"          ,rl)
          exprtk_register_function("rotate_right" ,rr)
@@ -38252,9 +40025,11 @@
    namespace information
    {
       static const char* library = "Mathematical Expression Toolkit";
-      static const char* version = "2.71828182845904523536028747135266249775724709369"
-                                   "9959574966967627724076630353547594571382178525166";
-      static const char* date    = "20180101";
+      static const char* version = "2.71828182845904523536028747135"
+                                   "2662497757247093699959574966967"
+                                   "6277240766303535475945713821785"
+                                   "2516642742746639193200305992181";
+      static const char* date    = "20200101";
 
       static inline std::string data()
       {
diff --git a/exprtk_benchmark.cpp b/exprtk_benchmark.cpp
index e219765..8e9c5fa 100644
--- a/exprtk_benchmark.cpp
+++ b/exprtk_benchmark.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * ExprTk vs Native Benchmarks                                *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
diff --git a/exprtk_simple_example_01.cpp b/exprtk_simple_example_01.cpp
index 04656bd..80eafe1 100644
--- a/exprtk_simple_example_01.cpp
+++ b/exprtk_simple_example_01.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 1                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,8 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
+   const std::string expression_string =
+                     "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
 
    T x;
 
@@ -44,8 +46,8 @@
 
    for (x = T(-5); x <= T(+5); x += T(0.001))
    {
-      T y = expression.value();
-      printf("%19.15f\t%19.15f\n",x,y);
+      const T y = expression.value();
+      printf("%19.15f\t%19.15f\n", x, y);
    }
 }
 
diff --git a/exprtk_simple_example_02.cpp b/exprtk_simple_example_02.cpp
index 0dedde1..56b9c9b 100644
--- a/exprtk_simple_example_02.cpp
+++ b/exprtk_simple_example_02.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 2                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,14 +29,15 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expr_string = "a*(4/pi)*"
-                             "((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+"
-                             " (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+"
-                             " (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+"
-                             " (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+"
-                             " (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+"
-                             " (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+"
-                             " (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))";
+   const std::string expr_string =
+                  "a*(4/pi)*"
+                  "((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+"
+                  " (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+"
+                  " (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+"
+                  " (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+"
+                  " (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+"
+                  " (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+"
+                  " (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))";
 
    static const T pi = T(3.141592653589793238462643383279502);
 
@@ -59,8 +61,8 @@
 
    for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
    {
-      T result = expression.value();
-      printf("%19.15f\t%19.15f\n",t,result);
+      const T result = expression.value();
+      printf("%19.15f\t%19.15f\n", t, result);
    }
 }
 
diff --git a/exprtk_simple_example_03.cpp b/exprtk_simple_example_03.cpp
index b1abe63..8e5a164 100644
--- a/exprtk_simple_example_03.cpp
+++ b/exprtk_simple_example_03.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 3                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,8 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
+   const std::string expression_string =
+                  "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
 
    const T r0 = T(0);
    const T r1 = T(1);
@@ -47,7 +49,7 @@
 
    for (x = r0; x <= r1; x += delta)
    {
-      printf("%19.15f\t%19.15f\n",x,expression.value());
+      printf("%19.15f\t%19.15f\n", x, expression.value());
    }
 }
 
diff --git a/exprtk_simple_example_04.cpp b/exprtk_simple_example_04.cpp
index f394d7e..aca7014 100644
--- a/exprtk_simple_example_04.cpp
+++ b/exprtk_simple_example_04.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 4                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -72,7 +73,7 @@
    {
       x = static_cast<T>(i);
 
-      T result = expression.value();
+      const T result = expression.value();
 
       printf("fibonacci(%3d) = %10.0f\n",
              static_cast<int>(i),
diff --git a/exprtk_simple_example_05.cpp b/exprtk_simple_example_05.cpp
index f563a4c..50d7987 100644
--- a/exprtk_simple_example_05.cpp
+++ b/exprtk_simple_example_05.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 5                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -49,7 +50,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expression_string =
+   const std::string expression_string =
                   "myfunc(sin(x / pi), otherfunc(3 * y, x / 2, x * y))";
 
    T x = T(1);
@@ -69,7 +70,7 @@
    parser_t parser;
    parser.compile(expression_string,expression);
 
-   T result = expression.value();
+   const T result = expression.value();
    printf("Result: %10.5f\n",result);
 }
 
diff --git a/exprtk_simple_example_06.cpp b/exprtk_simple_example_06.cpp
index 15ae070..0af6f8b 100644
--- a/exprtk_simple_example_06.cpp
+++ b/exprtk_simple_example_06.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 6                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expression_string =
+   const std::string expression_string =
                   " for (var i := 0; i < min(x[],y[],z[]); i += 1) "
                   " {                                              "
                   "   z[i] := 3sin(x[i]) + 2log(y[i]);             "
diff --git a/exprtk_simple_example_07.cpp b/exprtk_simple_example_07.cpp
index ecaa08a..bdf3c3b 100644
--- a/exprtk_simple_example_07.cpp
+++ b/exprtk_simple_example_07.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 7                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string expression_string = "not(A and B) or C";
+   const std::string expression_string = "not(A and B) or C";
 
    symbol_table_t symbol_table;
    symbol_table.create_variable("A");
@@ -52,7 +53,7 @@
       symbol_table.get_variable("B")->ref() = T((i & 0x02) ? 1 : 0);
       symbol_table.get_variable("C")->ref() = T((i & 0x04) ? 1 : 0);
 
-      int result = static_cast<int>(expression.value());
+      const int result = static_cast<int>(expression.value());
 
       printf(" %d | %d | %d | %d | %d \n",
              i,
diff --git a/exprtk_simple_example_08.cpp b/exprtk_simple_example_08.cpp
index cd21bb9..4565098 100644
--- a/exprtk_simple_example_08.cpp
+++ b/exprtk_simple_example_08.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 8                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -27,7 +28,7 @@
    typedef exprtk::symbol_table<T>      symbol_table_t;
    typedef exprtk::expression<T>          expression_t;
    typedef exprtk::parser<T>                  parser_t;
-   typedef exprtk::parser_error::type          error_t;
+   typedef exprtk::parser_error::type            err_t;
    typedef exprtk::function_compositor<T> compositor_t;
    typedef typename compositor_t::function  function_t;
 
@@ -64,7 +65,7 @@
 
       for (std::size_t i = 0; i < parser.error_count(); ++i)
       {
-         error_t error = parser.get_error(i);
+         const err_t error = parser.get_error(i);
 
          printf("Error: %02d  Position: %02d Type: [%14s] Msg: %s\tExpression: %s\n",
                 static_cast<unsigned int>(i),
@@ -77,7 +78,7 @@
       return;
    }
 
-   T result = expression.value();
+   const T result = expression.value();
 
    printf("%s = %e\n", expression_string.c_str(), result);
 }
diff --git a/exprtk_simple_example_09.cpp b/exprtk_simple_example_09.cpp
index 4b61efe..b11f193 100644
--- a/exprtk_simple_example_09.cpp
+++ b/exprtk_simple_example_09.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 9                                           *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -132,9 +133,9 @@
    {
       x = static_cast<T>(i);
 
-      T result1 = expression1.value();
-      T result2 = expression2.value();
-      T result3 = expression3.value();
+      const T result1 = expression1.value();
+      const T result2 = expression2.value();
+      const T result3 = expression3.value();
 
       printf("%03d  Result1: %c  Result2: %c  Result3: %c\n",
              static_cast<unsigned int>(i),
diff --git a/exprtk_simple_example_10.cpp b/exprtk_simple_example_10.cpp
index 1d75dc1..13728da 100644
--- a/exprtk_simple_example_10.cpp
+++ b/exprtk_simple_example_10.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 10                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -19,6 +19,7 @@
 #include <cmath>
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -44,25 +45,26 @@
       .add(
       function_t( // define function: newton_sqrt(x)
            "newton_sqrt",
-           " switch                                              "
-           " {                                                   "
-           "   case x < 0  : -inf;                               "
-           "   case x == 0 : 0;                                  "
-           "   case x == 1 : 1;                                  "
-           "   default:                                          "
-           "   ~{                                                "
-           "      var z := 100;                                  "
-           "      var sqrt_x := x / 2;                           "
-           "      repeat                                         "
-           "        sqrt_x := (1 / 2) * (sqrt_x + (x / sqrt_x)); "
-           "        if (equal(sqrt_x^2, x))                      "
-           "          break[sqrt_x];                             "
-           "      until ((z -= 1) <= 0);                         "
-           "    };                                               "
-           " }                                                   ",
+           " switch                                                "
+           " {                                                     "
+           "   case x < 0  : null;                                 "
+           "   case x == 0 : 0;                                    "
+           "   case x == 1 : 1;                                    "
+           "   default:                                            "
+           "   ~{                                                  "
+           "      var z := 100;                                    "
+           "      var sqrt_x := x / 2;                             "
+           "      repeat                                           "
+           "        if (equal(sqrt_x^2, x))                        "
+           "          break[sqrt_x];                               "
+           "        else                                           "
+           "          sqrt_x := (1 / 2) * (sqrt_x + (x / sqrt_x)); "
+           "      until ((z -= 1) <= 0);                           "
+           "    };                                                 "
+           " }                                                     ",
            "x"));
 
-   std::string expression_str = "newton_sqrt(x)";
+   const std::string expression_str = "newton_sqrt(x)";
 
    expression_t expression;
    expression.register_symbol_table(symbol_table);
@@ -74,9 +76,9 @@
    {
       x = static_cast<T>(i);
 
-      T result = expression.value();
+      const T result = expression.value();
 
-      printf("sqrt(%03d) - Result: %12.10f\tReal: %12.10f\n",
+      printf("sqrt(%03d) - Result: %15.13f\tReal: %15.13f\n",
              static_cast<unsigned int>(i),
              result,
              std::sqrt(x));
diff --git a/exprtk_simple_example_11.cpp b/exprtk_simple_example_11.cpp
index e280611..454c8f0 100644
--- a/exprtk_simple_example_11.cpp
+++ b/exprtk_simple_example_11.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 11                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string wave_program =
+   const std::string wave_program =
                   " var r := 0;                                         "
                   " for (var i := 0; i < 1000; i += 1)                  "
                   " {                                                   "
@@ -58,8 +59,8 @@
 
    for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
    {
-      T result = expression.value();
-      printf("%19.15f\t%19.15f\n",t,result);
+      const T result = expression.value();
+      printf("%19.15f\t%19.15f\n", t, result);
    }
 }
 
diff --git a/exprtk_simple_example_12.cpp b/exprtk_simple_example_12.cpp
index dd63592..ce398bd 100644
--- a/exprtk_simple_example_12.cpp
+++ b/exprtk_simple_example_12.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 12                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string bubblesort_program =
+   const std::string bubblesort_program =
                   " var upper_bound := v[];                           "
                   " var swapped := false;                             "
                   " repeat                                            "
diff --git a/exprtk_simple_example_13.cpp b/exprtk_simple_example_13.cpp
index df68035..e1922e8 100644
--- a/exprtk_simple_example_13.cpp
+++ b/exprtk_simple_example_13.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 13                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -20,6 +20,7 @@
 #include <cstdlib>
 #include <ctime>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -30,7 +31,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string sgfilter_program =
+   const std::string sgfilter_program =
                   " var weight[9] :=                                          "
                   "       {                                                   "
                   "         -21, 14,  39,                                     "
@@ -88,7 +89,7 @@
 
    for (std::size_t i = 0; i < v_out.size(); ++i)
    {
-      printf("%10.6f\t%10.6f\n",v_in[i],v_out[i]);
+      printf("%10.6f\t%10.6f\n", v_in[i], v_out[i]);
    }
 }
 
diff --git a/exprtk_simple_example_14.cpp b/exprtk_simple_example_14.cpp
index 7f7f8d3..bc508a2 100644
--- a/exprtk_simple_example_14.cpp
+++ b/exprtk_simple_example_14.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 14                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -27,7 +28,7 @@
    typedef exprtk::expression<T> expression_t;
    typedef exprtk::parser<T>         parser_t;
 
-   std::string stddev_program =
+   const std::string stddev_program =
                   " var x[25] := {                     "
                   "                 1,  2,  3,  4,  5, "
                   "                 6,  7,  8,  9, 10, "
@@ -43,7 +44,7 @@
    parser_t parser;
    parser.compile(stddev_program,expression);
 
-   T stddev = expression.value();
+   const T stddev = expression.value();
 
    printf("stddev(1..25) = %10.6f\n",stddev);
 }
diff --git a/exprtk_simple_example_15.cpp b/exprtk_simple_example_15.cpp
index b70c2c0..f7364fd 100644
--- a/exprtk_simple_example_15.cpp
+++ b/exprtk_simple_example_15.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 15                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -18,6 +18,7 @@
 
 #include <cstdio>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -28,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string bsm_model_program =
+   const std::string bsm_model_program =
                   " var d1 := (log(s / x) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
                   " var d2 := d1 - v * sqrt(t);                                 "
                   "                                                             "
@@ -70,7 +71,7 @@
 
       printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n",
              callput_flag.c_str(),
-             s,x,t,r,v,
+             s, x, t, r, v,
              bsm);
    }
 
@@ -81,7 +82,7 @@
 
       printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n",
              callput_flag.c_str(),
-             s,x,t,r,v,
+             s, x, t, r, v,
              bsm);
    }
 }
diff --git a/exprtk_simple_example_16.cpp b/exprtk_simple_example_16.cpp
index 1483c50..cd76f84 100644
--- a/exprtk_simple_example_16.cpp
+++ b/exprtk_simple_example_16.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 16                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -19,6 +19,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <string>
+
 #include "exprtk.hpp"
 
 
@@ -29,7 +30,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string linear_least_squares_program =
+   const std::string linear_least_squares_program =
                   " if (x[] == y[])                                       "
                   " {                                                     "
                   "   beta  := (sum(x * y) - sum(x) * sum(y) / x[]) /     "
diff --git a/exprtk_simple_example_17.cpp b/exprtk_simple_example_17.cpp
index a80e0ca..50263aa 100644
--- a/exprtk_simple_example_17.cpp
+++ b/exprtk_simple_example_17.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 17                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -47,7 +47,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string monte_carlo_pi_program =
+   const std::string monte_carlo_pi_program =
                   " var experiments[5 * 10^7] := [(rnd_01^2 + rnd_01^2) <= 1]; "
                   " 4 * sum(experiments) / experiments[];                      ";
 
diff --git a/exprtk_simple_example_18.cpp b/exprtk_simple_example_18.cpp
index c5bdf04..4fabc72 100644
--- a/exprtk_simple_example_18.cpp
+++ b/exprtk_simple_example_18.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 18                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -29,7 +29,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string fileio_program =
+   const std::string fileio_program =
                 " var file_name := 'file.txt';                         "
                 " var stream    := null;                               "
                 "                                                      "
diff --git a/exprtk_simple_example_19.cpp b/exprtk_simple_example_19.cpp
index d317559..5d0fc20 100644
--- a/exprtk_simple_example_19.cpp
+++ b/exprtk_simple_example_19.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Simple Example 19                                          *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -55,7 +55,7 @@
       if (
            (1 == ps_index) &&
            !exprtk::rtl::vecops::helper::
-              load_vector_range<T>::process(parameters,r0,r1,1,2,0)
+              load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
          )
          return T(0);
 
@@ -84,7 +84,7 @@
    typedef exprtk::expression<T>     expression_t;
    typedef exprtk::parser<T>             parser_t;
 
-   std::string vecrandu_program =
+   const std::string vecrandu_program =
                 " var noise[6] := [0];                     "
                 "                                          "
                 " if (randu(noise,0,5) == false)           "
diff --git a/exprtk_test.cpp b/exprtk_test.cpp
index aaf3901..91e7593 100644
--- a/exprtk_test.cpp
+++ b/exprtk_test.cpp
@@ -3,7 +3,7 @@
  *         C++ Mathematical Expression Toolkit Library        *
  *                                                            *
  * Examples and Unit-Tests                                    *
- * Author: Arash Partow (1999-2018)                           *
+ * Author: Arash Partow (1999-2020)                           *
  * URL: http://www.partow.net/programming/exprtk/index.html   *
  *                                                            *
  * Copyright notice:                                          *
@@ -23,6 +23,7 @@
 #include <deque>
 #include <fstream>
 #include <iostream>
+#include <numeric>
 #include <string>
 #include <vector>
 
@@ -2450,7 +2451,92 @@
                              test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)),
                              test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)),
                              test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)),
-                             test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0))
+                             test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)),
+
+                             test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] += 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) + (v[] * 10)", "","",T(1.0)),
+                             test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] -= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) - (v[] * 10)", "","",T(1.0)),
+                             test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] *= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) * 10", "","",T(1.0)),
+                             test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] /= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) / 10", "","",T(1.0)),
+
+                             test_ab<T>("a like b", "abcd", "abcd*", T(1.0)),
+                             test_ab<T>("a like b", "abcd", "abcd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "abc*" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*bcd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "abc?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?bcd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "ab?d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "ab*d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a?cd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a*cd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a??d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a*?d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*bc*" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?bc?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "????" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a???" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "ab??" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "abc?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "???d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "??cd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?bcd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?b?d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a?c?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a??d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?bc?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "ab**" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "ab*?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "a***" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "**cd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*?cd" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "***d" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*bc*" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*bc?" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*b??" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "?bc*" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "??c*" , T(1.0)),
+                             test_ab<T>("a like b", "abcd", "*b?*" , T(1.0)),
+                             test_ab<T>("a like b", "ab"  , "a*"   , T(1.0)),
+                             test_ab<T>("a like b", "ab"  , "a?"   , T(1.0)),
+
+                             test_ab<T>("a ilike b", "aBcD", "abcd*", T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "abcd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "abc*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*bcd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "abc?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?bcd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "ab?d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "ab*d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a?cd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a*cd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a??d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a*?d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*bc*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?bc?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "????" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a???" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "ab??" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "abc?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "???d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "??cd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?bcd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?b?d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a?c?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a??d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?bc?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "ab**" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "ab*?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "a***" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "**cd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*?cd" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "***d" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*bc*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*bc?" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*b??" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "?bc*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "??c*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aBcD", "*b?*" , T(1.0)),
+                             test_ab<T>("a ilike b", "aB"  , "a*"   , T(1.0)),
+                             test_ab<T>("a ilike b", "aB"  , "a?"   , T(1.0))
                            };
 
    static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
@@ -2589,6 +2675,10 @@
 template <typename T>
 inline bool run_test03()
 {
+   typedef exprtk::symbol_table<T> symbol_table_t;
+   typedef exprtk::expression<T>     expression_t;
+   typedef exprtk::parser<T>             parser_t;
+
    std::string expression_string = "A+A0+aA+Aa0+b+B1+Bb+bB1+A+A0+AA+AA0+B+B1+BB+BB1+a+a0+aa+aa0+b+b1+bb+bb1+"
                                    "c+C2+Cc+Cc2+D+D3+dD+dD3+C+C2+CC+CC2+D+D3+DD+DD3+c+c2+cc+cc2+d+d3+dd+dd3+"
                                    "E+E4+eE+Ee4+f+F5+Ff+fF5+E+E4+EE+EE4+F+F5+FF+FF5+e+e4+ee+ee4+f+f5+ff+ff5+"
@@ -2626,9 +2716,9 @@
 
    for (std::size_t r = 0; r < rounds; ++r)
    {
-      exprtk::symbol_table<T> symbol_table_0;
-      exprtk::symbol_table<T> symbol_table_1;
-      exprtk::expression<T> expression;
+      symbol_table_t symbol_table_0;
+      symbol_table_t symbol_table_1;
+      expression_t   expression;
 
       std::vector<T> v;
       v.resize(variable_list_size);
@@ -2726,7 +2816,38 @@
                                    "1 v x",
                                    "1 v y",
                                    "x v 1",
-                                   "y v 1"
+                                   "y v 1",
+
+                                   "(x == 'a string'                    )",
+                                   "(x == 'a string'[1:2]               )",
+                                   "(x == 'a string' + 'b string'       )",
+                                   "(x == ('a string' + 'b string')[3:5])",
+                                   "('a string' == x                    )",
+                                   "('a string'[1:2] == x               )",
+                                   "('a string' + 'b string' == x       )",
+                                   "(('a string' + 'b string')[3:5] == x)",
+
+                                   "var a; var b; 3in(a)+sin(b)               ",
+                                   "var a; var b; sin(a)+3in(b)               ",
+                                   "var a; var b; sqrt(a)<3in(8)              ",
+                                   "var a; var b; (1.99-3in((b-b)))           ",
+                                   "var a; var b; ((3in(sin((b+b)))/1.06)-a)  ",
+                                   "var a; var b; ((sin(3in((b+b)))/1.06)-a)  ",
+                                   "var a; var b; (3in(x*(y+z))+cos(x*(y-z))) ",
+                                   "var a; var b; (cos(x*(y+z))+3in(x*(y-z))) ",
+
+                                   "1++++",
+                                   "1+-+-+",
+                                   "1===",
+                                   "1====",
+                                   "[*][*][*][*][*]",
+
+                                   "var v[1] := {}; var s0appe0 := false; repeat s0appe0 false for(){(){}}",
+                                   "var v[2] := {}; repeat var s0appe0 := false; s0appe0 false for(){(){}}",
+                                   "var v[3] := {}; repeat var s0appe0 := false; for(){(){}} s0appe0 false",
+                                   "var v[4] := {}; repeat var s0appe0 := false; s0appe0 for(){(){}} false",
+                                   "var v[5] := {}; repeat for(){(){}} var s0appe0 := false; s0appe0 false",
+                                   "var v{};v ;v  60;v 60;v o5"
                                  };
 
       const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string);
@@ -2734,9 +2855,9 @@
       {
          for (std::size_t i = 0; i < invalid_expr_size; ++i)
          {
-            exprtk::symbol_table<T> symbol_table;
-
-            exprtk::expression<T> expression;
+            symbol_table_t symbol_table;
+            expression_t   expression;
+            parser_t       parser;
 
             T x = T(0);
             std::string s;
@@ -2746,8 +2867,6 @@
             symbol_table.add_stringvar("s",s);
             symbol_table.add_vector   ("v",v);
 
-            exprtk::parser<T> parser;
-
             if (parser.compile(invalid_expr[i],expression))
             {
                printf("run_test03() - Error: [1] Invalid expression compiled successfuly.   Expression: %s\n",
@@ -2763,14 +2882,13 @@
          std::string s;
          std::vector<T> v(10, T(1.234));
 
-         exprtk::symbol_table<T> symbol_table;
+         symbol_table_t symbol_table;
+         parser_t parser;
 
          symbol_table.add_variable ("x",x);
          symbol_table.add_stringvar("s",s);
          symbol_table.add_vector   ("v",v);
 
-         exprtk::parser<T> parser;
-
          for (std::size_t i = 0; i < invalid_expr_size; ++i)
          {
             exprtk::expression<T> expression;
@@ -2784,6 +2902,64 @@
             }
          }
       }
+
+      {
+         const std::string base_expression =
+                              "1+(2+2(3+3(4+4cos(((((a+((x*(e-tan((cos((((((b/(tan(((1.60*a)-0.34))-0.76))-x)+y)-3.27)+a))/pi))))^a))+y)*b)-e))+e)/z)+w)+"
+                              "(((b+(a/((((tan((b*((((((a-(cos((cos(tan(((a+a)*3.33)))-b))/2.52))*x)/b)+3.07)^0.86)+b)))*3.95)/0.39)*y)+a)))*a)*z)";
+
+         const std::string mod =
+                              "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^+-/*,;:<>=%?[]{}() #&'\"\\\t\r\n";
+
+         symbol_table_t symbol_table;
+         expression_t   expression;
+         parser_t       parser;
+
+         T a = T(1.1     );
+         T b = T(2.2     );
+         T c = T(3.3     );
+         T d = T(4.5     );
+         T e = T(4.5     );
+         T x = T(2.123456);
+         T y = T(3.123456);
+         T z = T(4.123456);
+         T w = T(5.123456);
+
+         symbol_table.add_variable("a", a);
+         symbol_table.add_variable("b", b);
+         symbol_table.add_variable("c", c);
+         symbol_table.add_variable("d", d);
+         symbol_table.add_variable("e", e);
+
+         symbol_table.add_variable("x", x);
+         symbol_table.add_variable("y", y);
+         symbol_table.add_variable("z", z);
+         symbol_table.add_variable("w", w);
+
+         expression.register_symbol_table(symbol_table);
+
+         T total = T(0);
+
+         for (std::size_t j = 0; j < base_expression.size(); ++j)
+         {
+            std::string expression_str = base_expression;
+            const char old_c = base_expression[j];
+
+            for (std::size_t i = 0; i < mod.size(); ++i)
+            {
+               expression_str[j] = mod[i];
+
+               if (parser.compile(expression_str, expression))
+               {
+                  total += expression.value();
+               }
+            }
+
+            expression_str[j] = old_c;
+         }
+
+         if (total == T(12345.6789)) { printf(" "); }
+      }
    }
 
    return true;
@@ -4075,6 +4251,62 @@
    }
 
    {
+      const std::string expression =
+                           "for (var i := 0; i < min(x[],y[],z[]); i += 1)"
+                           "{ z[i] := 3sin(x[i]) + 2log(y[i]); }";
+
+      std::vector<std::string> var_symbol_list;
+      std::vector<std::string> func_symbol_list;
+
+      if (!exprtk::collect_variables(expression, var_symbol_list))
+      {
+         printf("run_test10() - Failed to collect variables.\n");
+         return false;
+      }
+
+      if (!exprtk::collect_functions(expression, func_symbol_list))
+      {
+         printf("run_test10() - Failed to collect functions.\n");
+         return false;
+      }
+
+      std::sort(var_symbol_list .begin(), var_symbol_list .end());
+      std::sort(func_symbol_list.begin(), func_symbol_list.end());
+
+      std::vector<std::string> expected_var_symbol_list;
+      std::vector<std::string> expected_func_symbol_list;
+
+      expected_var_symbol_list.push_back("i");
+      expected_var_symbol_list.push_back("x");
+      expected_var_symbol_list.push_back("y");
+      expected_var_symbol_list.push_back("z");
+
+      expected_func_symbol_list.push_back("log");
+      expected_func_symbol_list.push_back("min");
+      expected_func_symbol_list.push_back("sin");
+
+      const bool var_result = (var_symbol_list.size() == expected_var_symbol_list.size()) &&
+                               std::equal(var_symbol_list.begin(),
+                                          var_symbol_list.end(),
+                                          expected_var_symbol_list.begin());
+      if (!var_result)
+      {
+         printf("run_test10() - Failed collected variable comparison between recieved and expected variables\n");
+         return false;
+      }
+
+      const bool func_result = (func_symbol_list.size() == expected_func_symbol_list.size()) &&
+                               std::equal(func_symbol_list.begin(),
+                                          func_symbol_list.end(),
+                                          expected_func_symbol_list.begin());
+      if (!func_result)
+      {
+         printf("run_test10() - Failed collected fuctions comparison between recieved and expected functions\n");
+         return false;
+      }
+   }
+
+   {
       std::string expression_list[] =
       {
         "var x; 1",
@@ -5578,6 +5810,109 @@
    }
 };
 
+template <typename T>
+struct vecrebase_func : public exprtk::igeneric_function<T>
+{
+   typedef typename exprtk::igeneric_function<T>::parameter_list_t
+                                                  parameter_list_t;
+
+   typedef typename exprtk::igeneric_function<T>::generic_type
+                                                  generic_type;
+
+   typedef typename generic_type::vector_view vector_t;
+
+   using exprtk::igeneric_function<T>::operator();
+
+   vecrebase_func()
+   : exprtk::igeneric_function<T>("V")
+   {}
+
+   inline T operator()(parameter_list_t params)
+   {
+      vector_t v(params[0]);
+      return std::accumulate(v.begin(), v.end(), T(0));
+   }
+};
+
+template <typename T>
+struct overload_func : exprtk::igeneric_function<T>
+{
+   typedef typename exprtk::igeneric_function<T> igfun_t;
+   typedef typename igfun_t::parameter_list_t    parameter_list_t;
+   typedef typename igfun_t::generic_type        generic_type;
+   typedef typename generic_type::vector_view    vector_t;
+
+   using exprtk::igeneric_function<T>::operator();
+
+   overload_func(const std::string& param_seq_list)
+   : exprtk::igeneric_function<T>(param_seq_list, igfun_t::e_rtrn_overload),
+     current_ps_index(std::numeric_limits<std::size_t>::max())
+   {
+      clear();
+   }
+
+   void clear()
+   {
+      current_ps_index  = std::numeric_limits<std::size_t>::max();
+      current_param_seq = "";
+   }
+
+   inline T operator()(const std::size_t& ps_index,
+                       parameter_list_t parameters)
+   {
+      current_ps_index = ps_index;
+      determine_param_seq(parameters);
+      return T(1);
+   }
+
+   inline T operator()(const std::size_t& ps_index,
+                       std::string& result,
+                       parameter_list_t parameters)
+   {
+      current_ps_index = ps_index;
+      determine_param_seq(parameters);
+      result = "string result";
+      return T(1);
+   }
+
+   void determine_param_seq(parameter_list_t parameters)
+   {
+      current_param_seq = "";
+
+      for (std::size_t i = 0; i < parameters.size(); ++i)
+      {
+         generic_type& gt = parameters[i];
+
+         switch (gt.type)
+         {
+            case generic_type::e_scalar : current_param_seq += "T";
+                                          break;
+
+            case generic_type::e_vector : current_param_seq += "V";
+                                          break;
+
+            case generic_type::e_string : current_param_seq += "S";
+                                          break;
+
+            default                     : continue;
+         }
+      }
+   }
+
+   std::size_t current_ps_index;
+   std::string current_param_seq;
+
+   struct test_result_t
+   {
+      test_result_t(const std::size_t psi, const std::string& ps)
+      : ps_index(psi),
+        param_seq(ps)
+      {}
+
+      std::size_t ps_index;
+      std::string param_seq;
+   };
+};
 
 template <typename T>
 inline bool run_test18()
@@ -6517,6 +6852,68 @@
    }
 
    {
+      typedef exprtk::symbol_table<T> symbol_table_t;
+      typedef exprtk::expression<T>     expression_t;
+      typedef exprtk::parser<T>             parser_t;
+
+      T v0[] = { T(0), T(1), T(2), T(3), T(4) };
+      T v1[] = { T(5), T(6), T(7), T(8), T(9) };
+
+      const std::size_t v0_size = sizeof(v0) / sizeof (T);
+      const std::size_t v1_size = sizeof(v1) / sizeof (T);
+
+      exprtk::vector_view<T> v = exprtk::make_vector_view(v0, v0_size);
+
+      vecrebase_func<T> vec_sum;
+
+      symbol_table_t symbol_table;
+      symbol_table.add_vector("v",v);
+      symbol_table.add_function("vec_sum",vec_sum);
+
+      expression_t expression;
+      expression.register_symbol_table(symbol_table);
+
+      parser_t parser;
+
+      const std::string expr_string = "vec_sum(v)";
+
+      if (!parser.compile(expr_string,expression))
+      {
+         printf("run_test18() - Error: %s\tExpression: %s\n",
+                parser.error().c_str(),
+                expr_string.c_str());
+
+         return false;
+      }
+
+      const T expected_result0 = std::accumulate(v0, v0 + v0_size,T(0));
+
+      if (expression.value() != expected_result0)
+      {
+         printf("run_test18() - Error in evaluation! (10.1) Expression: %s  Expected: %5.3f  Computed: %5.3f\n",
+                expr_string.c_str(),
+                expected_result0,
+                expression.value());
+
+         return false;
+      }
+
+      v.rebase(v1);
+
+      const T expected_result1 = std::accumulate(v1, v1 + v1_size,T(0));
+
+      if (expression.value() != expected_result1)
+      {
+         printf("run_test18() - Error in evaluation! (10.2) Expression: %s  Expected: %5.3f  Computed: %5.3f\n",
+                expr_string.c_str(),
+                expected_result1,
+                expression.value());
+
+         return false;
+      }
+   }
+
+   {
       bool failure = false;
 
       typedef exprtk::symbol_table<T> symbol_table_t;
@@ -6648,7 +7045,7 @@
 
          if (result != T(1))
          {
-            printf("run_test18() - Error in evaluation! (10) Expression: %s\n",
+            printf("run_test18() - Error in evaluation! (11) Expression: %s\n",
                    expr_str_list[i].c_str());
 
             failure = true;
@@ -6659,6 +7056,295 @@
          return false;
    }
 
+   {
+      typedef exprtk::expression<T> expression_t;
+
+      std::string a = "a";
+      std::string b = "b";
+      std::string c = "c";
+      std::string d = "d";
+
+      T x = T(1.1);
+      T y = T(2.2);
+      T z = T(3.3);
+      T w = T(4.4);
+
+      overload_func<T> ovrld_func
+                        (
+                          "T:T|T:TT|T:TTT|T:TTTT|"
+                          "T:S|T:SS|T:SSS|T:SSSS|"
+                          "T:ST|T:STS|T:STST|"
+                          "T:TS|T:TST|T:TSTS|"
+                          "T:TTSS|T:SSTT|T:STTS|T:TSST"
+                        );
+
+      exprtk::symbol_table<T> symbol_table;
+
+      symbol_table.add_constants();
+      symbol_table.add_variable ("x",x);
+      symbol_table.add_variable ("y",y);
+      symbol_table.add_variable ("z",z);
+      symbol_table.add_variable ("w",w);
+
+      symbol_table.add_stringvar("a",a);
+      symbol_table.add_stringvar("b",b);
+      symbol_table.add_stringvar("c",c);
+      symbol_table.add_stringvar("d",d);
+
+      symbol_table.add_function("foo",ovrld_func);
+
+      typedef typename overload_func<T>::test_result_t test_result_t;
+      typedef std::pair<std::string, typename overload_func<T>::test_result_t> test_pack_t;
+
+      static const test_pack_t test_pack_list[] =
+                                  {
+                                    test_pack_t("foo(x)"                          , test_result_t( 0, "T"   )),
+                                    test_pack_t("foo(x, y)"                       , test_result_t( 1, "TT"  )),
+                                    test_pack_t("foo(x, y, z)"                    , test_result_t( 2, "TTT" )),
+                                    test_pack_t("foo(x, y, z, w)"                 , test_result_t( 3, "TTTT")),
+                                    test_pack_t("foo(x + y)"                      , test_result_t( 0, "T"   )),
+                                    test_pack_t("foo(x + y, y + z)"               , test_result_t( 1, "TT"  )),
+                                    test_pack_t("foo(x + y, y + z, z + w)"        , test_result_t( 2, "TTT" )),
+                                    test_pack_t("foo(x + y, y + z, z + w, w)"     , test_result_t( 3, "TTTT")),
+                                    test_pack_t("foo(a)"                          , test_result_t( 4, "S"   )),
+                                    test_pack_t("foo(a, b)"                       , test_result_t( 5, "SS"  )),
+                                    test_pack_t("foo(a, b, c)"                    , test_result_t( 6, "SSS" )),
+                                    test_pack_t("foo(a, b, c, d)"                 , test_result_t( 7, "SSSS")),
+                                    test_pack_t("foo(a + b)"                      , test_result_t( 4, "S"   )),
+                                    test_pack_t("foo(a + b, b + c)"               , test_result_t( 5, "SS"  )),
+                                    test_pack_t("foo(a + b, b + c, c + d)"        , test_result_t( 6, "SSS" )),
+                                    test_pack_t("foo(a + b, b + c, c + d, d)"     , test_result_t( 7, "SSSS")),
+                                    test_pack_t("foo(a, x)"                       , test_result_t( 8, "ST"  )),
+                                    test_pack_t("foo(a, x, b)"                    , test_result_t( 9, "STS" )),
+                                    test_pack_t("foo(a, x, b, y)"                 , test_result_t(10, "STST")),
+                                    test_pack_t("foo(a + b, x + y)"               , test_result_t( 8, "ST"  )),
+                                    test_pack_t("foo(a + b, x + y, b + c)"        , test_result_t( 9, "STS" )),
+                                    test_pack_t("foo(a + b, x + y, b + c, y + z)" , test_result_t(10, "STST")),
+                                    test_pack_t("foo(x, a)"                       , test_result_t(11, "TS"  )),
+                                    test_pack_t("foo(x, a, y)"                    , test_result_t(12, "TST" )),
+                                    test_pack_t("foo(x, a, y, b)"                 , test_result_t(13, "TSTS")),
+                                    test_pack_t("foo(x + y, a + b)"               , test_result_t(11, "TS"  )),
+                                    test_pack_t("foo(x + y, a + b, y + z)"        , test_result_t(12, "TST" )),
+                                    test_pack_t("foo(x + y, a + b, y + z, b + c)" , test_result_t(13, "TSTS")),
+                                    test_pack_t("foo(x, y, a, b)"                 , test_result_t(14, "TTSS")),
+                                    test_pack_t("foo(a, b, x, y)"                 , test_result_t(15, "SSTT")),
+                                    test_pack_t("foo(a, x, y, b)"                 , test_result_t(16, "STTS")),
+                                    test_pack_t("foo(x, a, b, y)"                 , test_result_t(17, "TSST")),
+                                    test_pack_t("foo(x + y, y + z, a + b, b + c)" , test_result_t(14, "TTSS")),
+                                    test_pack_t("foo(a + b, b + c, x + y, y + z)" , test_result_t(15, "SSTT")),
+                                    test_pack_t("foo(a + b, x + y, y + z, b + c)" , test_result_t(16, "STTS")),
+                                    test_pack_t("foo(x + y, a + b, b + c, y + z)" , test_result_t(17, "TSST"))
+                                  };
+
+      static const std::size_t test_pack_list_size = sizeof(test_pack_list) / sizeof(test_pack_t);
+
+      std::deque<expression_t> expression_list;
+
+      for (std::size_t i = 0; i < test_pack_list_size; ++i)
+      {
+         expression_t expression;
+         expression.register_symbol_table(symbol_table);
+
+         exprtk::parser<T> parser;
+
+         if (!parser.compile(test_pack_list[i].first, expression))
+         {
+            printf("run_test18() - (12) Overload VarArg Error: %s   Expression: %s\n",
+                   parser.error().c_str(),
+                   test_pack_list[i].first.c_str());
+
+            return false;
+         }
+         else
+            expression_list.push_back(expression);
+      }
+
+      bool failure = false;
+
+      for (std::size_t i = 0; i < expression_list.size(); ++i)
+      {
+         ovrld_func.clear();
+
+         if (T(1) != expression_list[i].value())
+         {
+            printf("run_test18() - Error in evaluation! (12) Expression: %s\n",
+                   test_pack_list[i].first.c_str());
+
+            failure = true;
+         }
+
+         if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index)
+         {
+            printf("run_test18() - Error with ps_index (12) Expression: %s  Expected: %d  Got: %d\n",
+                   test_pack_list[i].first.c_str(),
+                   static_cast<int>(test_pack_list[i].second.ps_index),
+                   static_cast<int>(ovrld_func.current_ps_index));
+
+            failure = true;
+         }
+
+         if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq)
+         {
+            printf("run_test18() - Error with parameter seq (12) Expression: %s  Expected: %s  Got: %s\n",
+                   test_pack_list[i].first.c_str(),
+                   test_pack_list[i].second.param_seq.c_str(),
+                   ovrld_func.current_param_seq.c_str());
+
+            failure = true;
+         }
+         ::fflush(stdout);
+      }
+
+      if (failure)
+         return false;
+   }
+
+   {
+      typedef exprtk::expression<T> expression_t;
+
+      std::string a = "a";
+      std::string b = "b";
+      std::string c = "c";
+      std::string d = "d";
+      std::string result = "";
+
+      T x = T(1.1);
+      T y = T(2.2);
+      T z = T(3.3);
+      T w = T(4.4);
+
+      overload_func<T> ovrld_func
+                        (
+                          "S:T|S:TT|S:TTT|S:TTTT|"
+                          "S:S|S:SS|S:SSS|S:SSSS|"
+                          "S:ST|S:STS|S:STST|"
+                          "S:TS|S:TST|S:TSTS|"
+                          "S:TTSS|S:SSTT|S:STTS|S:TSST"
+                        );
+
+      exprtk::symbol_table<T> symbol_table;
+
+      symbol_table.add_constants();
+      symbol_table.add_variable ("x",x);
+      symbol_table.add_variable ("y",y);
+      symbol_table.add_variable ("z",z);
+      symbol_table.add_variable ("w",w);
+
+      symbol_table.add_stringvar("a",a);
+      symbol_table.add_stringvar("b",b);
+      symbol_table.add_stringvar("c",c);
+      symbol_table.add_stringvar("d",d);
+      symbol_table.add_stringvar("result",result);
+
+      symbol_table.add_function("foo",ovrld_func);
+
+      typedef typename overload_func<T>::test_result_t test_result_t;
+      typedef std::pair<std::string, typename overload_func<T>::test_result_t> test_pack_t;
+
+      static const test_pack_t test_pack_list[] =
+                                  {
+                                    test_pack_t("result := foo(x)"                          , test_result_t( 0, "T"   )),
+                                    test_pack_t("result := foo(x, y)"                       , test_result_t( 1, "TT"  )),
+                                    test_pack_t("result := foo(x, y, z)"                    , test_result_t( 2, "TTT" )),
+                                    test_pack_t("result := foo(x, y, z, w)"                 , test_result_t( 3, "TTTT")),
+                                    test_pack_t("result := foo(x + y)"                      , test_result_t( 0, "T"   )),
+                                    test_pack_t("result := foo(x + y, y + z)"               , test_result_t( 1, "TT"  )),
+                                    test_pack_t("result := foo(x + y, y + z, z + w)"        , test_result_t( 2, "TTT" )),
+                                    test_pack_t("result := foo(x + y, y + z, z + w, w)"     , test_result_t( 3, "TTTT")),
+                                    test_pack_t("result := foo(a)"                          , test_result_t( 4, "S"   )),
+                                    test_pack_t("result := foo(a, b)"                       , test_result_t( 5, "SS"  )),
+                                    test_pack_t("result := foo(a, b, c)"                    , test_result_t( 6, "SSS" )),
+                                    test_pack_t("result := foo(a, b, c, d)"                 , test_result_t( 7, "SSSS")),
+                                    test_pack_t("result := foo(a + b)"                      , test_result_t( 4, "S"   )),
+                                    test_pack_t("result := foo(a + b, b + c)"               , test_result_t( 5, "SS"  )),
+                                    test_pack_t("result := foo(a + b, b + c, c + d)"        , test_result_t( 6, "SSS" )),
+                                    test_pack_t("result := foo(a + b, b + c, c + d, d)"     , test_result_t( 7, "SSSS")),
+                                    test_pack_t("result := foo(a, x)"                       , test_result_t( 8, "ST"  )),
+                                    test_pack_t("result := foo(a, x, b)"                    , test_result_t( 9, "STS" )),
+                                    test_pack_t("result := foo(a, x, b, y)"                 , test_result_t(10, "STST")),
+                                    test_pack_t("result := foo(a + b, x + y)"               , test_result_t( 8, "ST"  )),
+                                    test_pack_t("result := foo(a + b, x + y, b + c)"        , test_result_t( 9, "STS" )),
+                                    test_pack_t("result := foo(a + b, x + y, b + c, y + z)" , test_result_t(10, "STST")),
+                                    test_pack_t("result := foo(x, a)"                       , test_result_t(11, "TS"  )),
+                                    test_pack_t("result := foo(x, a, y)"                    , test_result_t(12, "TST" )),
+                                    test_pack_t("result := foo(x, a, y, b)"                 , test_result_t(13, "TSTS")),
+                                    test_pack_t("result := foo(x + y, a + b)"               , test_result_t(11, "TS"  )),
+                                    test_pack_t("result := foo(x + y, a + b, y + z)"        , test_result_t(12, "TST" )),
+                                    test_pack_t("result := foo(x + y, a + b, y + z, b + c)" , test_result_t(13, "TSTS")),
+                                    test_pack_t("result := foo(x, y, a, b)"                 , test_result_t(14, "TTSS")),
+                                    test_pack_t("result := foo(a, b, x, y)"                 , test_result_t(15, "SSTT")),
+                                    test_pack_t("result := foo(a, x, y, b)"                 , test_result_t(16, "STTS")),
+                                    test_pack_t("result := foo(x, a, b, y)"                 , test_result_t(17, "TSST")),
+                                    test_pack_t("result := foo(x + y, y + z, a + b, b + c)" , test_result_t(14, "TTSS")),
+                                    test_pack_t("result := foo(a + b, b + c, x + y, y + z)" , test_result_t(15, "SSTT")),
+                                    test_pack_t("result := foo(a + b, x + y, y + z, b + c)" , test_result_t(16, "STTS")),
+                                    test_pack_t("result := foo(x + y, a + b, b + c, y + z)" , test_result_t(17, "TSST"))
+                                  };
+
+      static const std::size_t test_pack_list_size = sizeof(test_pack_list) / sizeof(test_pack_t);
+
+      std::deque<expression_t> expression_list;
+
+      for (std::size_t i = 0; i < test_pack_list_size; ++i)
+      {
+         expression_t expression;
+         expression.register_symbol_table(symbol_table);
+
+         exprtk::parser<T> parser;
+
+         if (!parser.compile(test_pack_list[i].first, expression))
+         {
+            printf("run_test18() - (13) Overload VarArg Error: %s   Expression: %s\n",
+                   parser.error().c_str(),
+                   test_pack_list[i].first.c_str());
+
+            return false;
+         }
+         else
+            expression_list.push_back(expression);
+      }
+
+      bool failure = false;
+
+      for (std::size_t i = 0; i < expression_list.size(); ++i)
+      {
+         ovrld_func.clear();
+         result = "";
+         expression_list[i].value();
+
+         if (result != "string result")
+         {
+            printf("run_test18() - Error in evaluation! (13) Expression: %s\n",
+                   test_pack_list[i].first.c_str());
+
+            failure = true;
+         }
+
+         if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index)
+         {
+            printf("run_test18() - Error with ps_index (13) Expression: %s  Expected: %d  Got: %d\n",
+                   test_pack_list[i].first.c_str(),
+                   static_cast<int>(test_pack_list[i].second.ps_index),
+                   static_cast<int>(ovrld_func.current_ps_index));
+
+            failure = true;
+         }
+
+         if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq)
+         {
+            printf("run_test18() - Error with parameter seq (13) Expression: %s  Expected: %s  Got: %s\n",
+                   test_pack_list[i].first.c_str(),
+                   test_pack_list[i].second.param_seq.c_str(),
+                   ovrld_func.current_param_seq.c_str());
+
+            failure = true;
+         }
+      }
+
+      if (failure)
+         return false;
+   }
+
    return true;
 }
 
@@ -7826,6 +8512,126 @@
       }
    }
 
+   {
+      T              var;
+      std::string    str;
+      std::vector<T> vec(10,0.0);
+
+      typedef exprtk::symbol_table<T> symbol_table_t;
+
+      bool result = true;
+
+      {
+         symbol_table_t symbol_table;
+
+         symbol_table.add_variable ("val",var);
+         symbol_table.add_stringvar("str",str);
+         symbol_table.add_vector   ("vec",vec);
+
+         if (symbol_table.get_variable("val") == 0 || !symbol_table.symbol_exists("val"))
+         {
+            printf("run_test20() - [3] Failed to get 'val' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_stringvar("str") == 0 || !symbol_table.symbol_exists("str"))
+         {
+            printf("run_test20() - [3] Failed to get 'str' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_vector("vec") == 0 || !symbol_table.symbol_exists("vec"))
+         {
+            printf("run_test20() - [3] Failed to get 'vec' from symbol_table\n");
+            result = false;
+         }
+      }
+
+      if (!result)
+         return result;
+
+      {
+         symbol_table_t symbol_table;
+
+         symbol_table.add_variable("val",var);
+
+         if (symbol_table.get_variable("val") == 0 || !symbol_table.symbol_exists("val"))
+         {
+            printf("run_test20() - [4] Failed to get 'val' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_stringvar("str") != 0 || symbol_table.symbol_exists("str"))
+         {
+            printf("run_test20() - [4] Failed to get 'str' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_vector("vec") != 0 || symbol_table.symbol_exists("vec"))
+         {
+            printf("run_test20() - [4] Failed to get 'vec' from symbol_table\n");
+            result = false;
+         }
+      }
+
+      if (!result)
+         return result;
+
+      {
+         symbol_table_t symbol_table;
+
+         symbol_table.add_stringvar("str",str);
+
+         if (symbol_table.get_stringvar("str") == 0 || !symbol_table.symbol_exists("str"))
+         {
+            printf("run_test20() - [5] Failed to get 'str' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_variable("val") != 0 || symbol_table.symbol_exists("val"))
+         {
+            printf("run_test20() - [5] Failed to get 'val' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_vector("vec") != 0 || symbol_table.symbol_exists("vec"))
+         {
+            printf("run_test20() - [5] Failed to get 'vec' from symbol_table\n");
+            result = false;
+         }
+      }
+
+      if (!result)
+         return result;
+
+      {
+         symbol_table_t symbol_table;
+
+         symbol_table.add_vector("vec",vec);
+
+         if (symbol_table.get_vector("vec") == 0 || !symbol_table.symbol_exists("vec"))
+         {
+            printf("run_test20() - [6] Failed to get 'vec' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_variable("val") != 0 || symbol_table.symbol_exists("val"))
+         {
+            printf("run_test20() - [6] Failed to get 'val' from symbol_table\n");
+            result = false;
+         }
+
+         if (symbol_table.get_stringvar("str") != 0 || symbol_table.symbol_exists("str"))
+         {
+            printf("run_test20() - [6] Failed to get 'str' from symbol_table\n");
+            result = false;
+         }
+      }
+
+      if (!result)
+         return result;
+   }
+
    return true;
 }
 
diff --git a/readme.txt b/readme.txt
index a819125..8e4dc46 100644
--- a/readme.txt
+++ b/readme.txt
@@ -428,8 +428,8 @@
 | [r0:r1]  | The closed interval [r0,r1] of the specified string.    |
 |          | eg: Given a string x with a value of 'abcdefgh' then:   |
 |          | 1. x[1:4] == 'bcde'                                     |
-|          | 2. x[ :5] == x[:5] == 'abcdef'                          |
-|          | 3. x[3: ] == x[3:] =='cdefgh'                           |
+|          | 2. x[ :5] == x[:10 / 2] == 'abcdef'                     |
+|          | 3. x[2 + 1: ] == x[3:] =='defgh'                        |
 |          | 4. x[ : ] == x[:] == 'abcdefgh'                         |
 |          | 5. x[4/2:3+2] == x[2:5] == 'cdef'                       |
 |          |                                                         |
@@ -706,6 +706,61 @@
 the  expression  instance  and  to also  allow  the  expression  to be
 evaluated using the current value of the element.
 
+Note:  Any  variable  reference  provided  to  a  given   symbol_table
+instance, must have a life time  at least as long as the  life-time of
+the  symbol_table instance.  In the  event the  variable reference  is
+invalidated  before  the  symbol_table  or  any  dependent  expression
+instances  have  been  destructed,  then  any  associated   expression
+evaluations or variable referencing via the symbol_table instance will
+result in undefined behaviour.
+
+The following bit of  code instantiates a symbol_table  and expression
+instance,  then  proceeds  to   demonstrate  various  ways  in   which
+references to  variables can  be added  to the  symbol_table, and  how
+those  references are  subsequently invalidated  resulting in  various
+forms of undefined behaviour.
+
+   typedef exprtk::symbol_table<double> symbol_table_t;
+
+   symbol_table_t symbol_table;
+   expression_t expression;
+
+   {
+      double x = 123.4567;
+      symbol_table.add_variable("x", x);
+   }             // Reference to variable x has been invalidated
+
+   std::deque<double> y {1.1, 2.2, 3.3};
+
+   symbol_table.add_variable("y", y.back());
+
+   y.pop_back(); // Reference to variable y has been invalidated
+
+   std::vector<double> z {4.4, 5.5, 6.6};
+
+   symbol_table.add_variable("z", z.front());
+
+   z.erase(z.begin());
+                 // Reference to variable z has been invalidated
+
+   double* w = new double(123.456);
+
+   symbol_table.add_variable("w", *w);
+
+   delete w;     // Reference to variable w has been invalidated
+
+   const std::string expression_str = "x + y / z * w";
+
+                 // Compilation of expression will succeed
+   parser.compile(expression_str,expression);
+
+   expression.value();
+                // Evaluation will result in undefined behaviour
+
+   symbol_table.get_variable("x")->ref() = 135.791;
+                // Assignment will result in undefined behaviour
+
+
 The  example  below demonstrates  the  relationship between variables,
 symbol_table and expression. Note  the variables are modified  as they
 normally would in a program, and when the expression is  evaluated the
@@ -865,7 +920,7 @@
 Generally an expression in ExprTk can be thought of as a free function
 similar to those  found in imperative  languages. This form  of pseudo
 function will have a name, it may have a set of one or more inputs and
-will return at least one value as its result. Futhermore the  function
+will return at least one value as its result. Furthermore the function
 when invoked, may  cause a side-effect  that changes the  state of the
 host program.
 
@@ -968,7 +1023,7 @@
 utilizing the exact same  references for variables. This  obviously is
 not the  default assumed  scenario and  will give  rise to non-obvious
 behaviours  when  using the  expressions in  various contexts such  as
-muli-threading et al.
+multi-threading et al.
 
 The prescribed method for cloning an expression is to compile it  from
 its string  form. Doing so will allow the 'user' to  properly consider
@@ -1260,7 +1315,7 @@
    (b) Invoking a user-defined function that has side-effects
 
 The following are examples of expressions where the side-effect status
-of the statements (or sub-exressions) within the expressions have been
+of the  statements (sub-expressions) within the expressions  have been
 noted:
 
   +-+----------------------+------------------------------+
@@ -1537,7 +1592,7 @@
        var y := 3;
 
    (c) Initialise z to the expression
-       var z := if (max(1,x + y) > 2,w,v);
+       var z := if (max(1, x + y) > 2, w, v);
 
 
 (2) Vector Definition
@@ -1552,7 +1607,7 @@
        var x[3] := {};
 
    (c) Initialise all values to given expression
-       var x[3] := [123 + 3y + sin(w/z)];
+       var x[3] := [123 + 3y + sin(w / z)];
 
    (d) Initialise the first two values, all other elements to zero
        var x[3] := { 1 + x[2], sin(y[0] / x[]) + 3 };
@@ -1814,15 +1869,16 @@
 
 There are five types of function interface:
 
-  +---+----------------------+-------------+----------------------+
-  | # |         Name         | Return Type | Input Types          |
-  +---+----------------------+-------------+----------------------+
-  | 1 | ifunction            | Scalar      | Scalar               |
-  | 2 | ivararg_function     | Scalar      | Scalar               |
-  | 3 | igeneric_function    | Scalar      | Scalar,Vector,String |
-  | 4 | igeneric_function II | String      | Scalar,Vector,String |
-  | 5 | function_compositor  | Scalar      | Scalar               |
-  +---+----------------------+-------------+----------------------+
+  +---+----------------------+--------------+----------------------+
+  | # |         Name         | Return Type  | Input Types          |
+  +---+----------------------+--------------+----------------------+
+  | 1 | ifunction            | Scalar       | Scalar               |
+  | 2 | ivararg_function     | Scalar       | Scalar               |
+  | 3 | igeneric_function    | Scalar       | Scalar,Vector,String |
+  | 4 | igeneric_function II | String       | Scalar,Vector,String |
+  | 5 | igeneric_function III| String/Scalar| Scalar,Vector,String |
+  | 6 | function_compositor  | Scalar       | Scalar               |
+  +---+----------------------+--------------+----------------------+
 
 (1) ifunction
 This interface supports zero to 20 input parameters of only the scalar
@@ -2198,7 +2254,60 @@
    (4) Scalar                                (4) String
 
 
-(5) function_compositor
+(5) igeneric_function III
+In this section we will discuss an extension of the  igeneric_function
+interface that will allow for the overloading of a user defined custom
+function, where by it can return either a scalar or string value  type
+depending on the input parameter  sequence with which the function  is
+invoked.
+
+   template <typename T>
+   struct foo : public exprtk::igeneric_function<T>
+   {
+      typedef typename exprtk::igeneric_function<T>::parameter_list_t
+                                                     parameter_list_t;
+
+      foo()
+      : exprtk::igeneric_function<T>
+        (
+          "T:T|S:TS",
+          igfun_t::e_rtrn_overload
+        )
+      {}
+
+      // Scalar value returning invocations
+      inline T operator()(const std::size_t& ps_index,
+                          parameter_list_t parameters)
+      {
+         ...
+      }
+
+      // String value returning invocations
+      inline T operator()(const std::size_t& ps_index,
+                          std::string& result,
+                          parameter_list_t& parameters)
+      {
+         ...
+      }
+   };
+
+
+In the  example above  the custom  user defined  function "foo" can be
+invoked by using  either one of  two input parameter  sequences, which
+are defined as follows:
+
+   Sequence-0    Sequence-1
+   'T' -> T      'TS' -> S
+   (1) Scalar    (1) Scalar
+                 (2) String
+
+
+The parameter  sequence definitions  are identical  to the  previously
+define igeneric_function, with the  exception of the inclusion  of the
+return type - which can only be either a scalar T or a string S.
+
+
+(6) function_compositor
 The function  compositor is  a factory  that allows  one to define and
 construct a function using ExprTk syntax. The functions are limited to
 returning a single scalar value and consuming up to six parameters  as
@@ -2355,11 +2464,11 @@
 in constant folding optimisations.
 
 In the following  example, a two  input parameter free  function named
-'compute', and a three input parameter lambda will be registered  with
-the given symbol_table instance:
+'compute1', and a three  input parameter lambda named  'compute2' will
+be registered with the given symbol_table instance:
 
 
-   double compute(double v0, double v1)
+   double compute1(double v0, double v1)
    {
       return 2.0 * v0 + v1 / 3.0;
    }
@@ -2372,12 +2481,12 @@
 
    symbol_table_t symbol_table;
 
-   symbol_table.add_function("compute", compute);
+   symbol_table.add_function("compute1", compute1);
 
-   symbol_table.add_function("lambda",
-                             [](double v0, double v1, double v2) -> double
-                             { return v0 / v1 + v2; });
-
+   symbol_table.add_function(
+      "compute2",
+      [](double v0, double v1, double v2) -> double
+      { return v0 / v1 + v2; });
 
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -2715,7 +2824,7 @@
 
 This can become problematic, as in the default scenario it is  assumed
 the symbol_table that is registered with the expression instance  will
-already  posses  the  externally  available  variables,  functions and
+already possess  the  externally  available  variables,  functions and
 constants needed during the compilation of the expression.
 
 In the event there are symbols in the expression that can't be  mapped
@@ -2838,7 +2947,7 @@
 
    for (auto& var_name : variable_list)
    {
-      T& v = symbol_table.variable_ref(var_name);
+      T& v = unknown_var_symbol_table.variable_ref(var_name);
 
       v = ...;
    }
@@ -2999,6 +3108,24 @@
 Note: The primary symbol table  for an expression is the  first symbol
 table to be registered with that instance of the expression.
 
+Note: For a successful symbol  resolution using the normal USR  all of
+the following are required:
+
+   (1) Only if successful shall the process method return TRUE
+   (2) The default_value parameter will have been set
+   (3) The error_message parameter will be empty
+   (4) usr_symbol_type input parameter field will be set to either:
+         (*) e_usr_variable_type
+         (*) e_usr_constant_type
+
+Note: For a successful symbol resolution using the extended USR all of
+the following are required:
+
+   (1) Only if successful shall the process method return TRUE
+   (2) symbol_table parameter will have had the newly resolved
+       variable or string added to it
+   (3) error_message parameter will be empty
+
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 [SECTION 19 - ENABLING & DISABLING FEATURES]
@@ -3710,13 +3837,13 @@
 
    if (exprtk::collect_variables(expression, variable_list))
    {
-      for (auto var : variable_list)
+      for (const auto& var : variable_list)
       {
          ...
       }
    }
    else
-     printf("An error occured.");
+     printf("An error occurred.");
 
 
 (b) collect_functions
@@ -3734,13 +3861,13 @@
 
    if (exprtk::collect_functions(expression, function_list))
    {
-      for (auto func : function_list)
+      for (const auto& func : function_list)
       {
          ...
       }
    }
    else
-     printf("An error occured.");
+     printf("An error occurred.");
 
 
 Note: When either the 'collect_variables'  or 'collect_functions' free
@@ -3752,10 +3879,10 @@
 
 Note: The  default interface  provided for  both the collect_variables
 and collect_functions  free_functions, assumes  that expressions  will
-only be utilising  the ExprTk reserved  funnctions (eg: abs,  cos, min
+only be utilising  the ExprTk  reserved  functions (eg: abs,  cos, min
 etc). When user defined functions are  to be used in an expression,  a
 symbol_table  instance  containing  said functions  can  be  passed to
-either routine, and  will be incorparated  during the compilation  and
+either routine, and  will be incorporated  during the compilation  and
 Dependent Entity  Collection processes.  In the  following example,  a
 user  defined  free  function   named  'foo'  is  registered   with  a
 symbol_table.  Finally  the   symbol_table  instance  and   associated
@@ -3779,13 +3906,13 @@
 
    if (exprtk::collect_functions(expression, sym_tab, function_list))
    {
-      for (auto func : function_list)
+      for (const auto& func : function_list)
       {
          ...
       }
    }
    else
-     printf("An error occured.");
+     printf("An error occurred.");
 
 
 (c) compute
@@ -3910,7 +4037,7 @@
    // Differentiate expression at value of x = 12.3 using a reference
    // to the x variable
    x = T(12.3);
-   T derivative1 = exprtk::derivative(expression,x);
+   T derivative1 = exprtk::derivative(expression, x);
 
    // Differentiate expression where value x = 45.6 using name
    // of the x variable
@@ -3988,7 +4115,7 @@
    // Third derivative of expression where value of x = 12.3 using a
    // reference to the x variable
    x = T(12.3);
-   T derivative1 = exprtk::third_derivative(expression,x);
+   T derivative1 = exprtk::third_derivative(expression, x);
 
    // Third derivative of expression where value of x = 45.6 using
    // name of the x variable
@@ -4168,9 +4295,11 @@
       function names are case-insensitive.
 
  (07) Variable, vector, string variable and function names must begin
-      with  a letter  (A-Z or  a-z), then  can be  comprised of  any
-      combination of letters, digits,  underscores and dots. (eg:  x,
-      var1 or power_func99, person.age, item.size.0)
+      with  a letter  (A-Z or  a-z), then  can  be  comprised of  any
+      combination of letters, digits, underscores and dots, ending in
+      either a letter (A-Z or a-z), digit or underscore. (eg: x,  y2,
+      var1,  power_func99,  person.age,  item.size.0). The associated
+      regex pattern is: [a-zA-Z]([a-zA-Z0-9_.]*|[a-zA-Z0-9_])
 
  (08) Expression lengths and sub-expression lists are limited only by
       storage capacity.